Developers API v1

Schemas and validation

Every object in the contract, every field, and every rule your payload is validated against. 69 schemas, generated from the specification itself.

This page is generated, not written

It is produced directly from openapi.yaml version 1.0, so it cannot drift from the contract your requests are actually validated against. If a rule is here, the validator enforces it.

Unknown fields are rejected, not ignored

Almost every object sets no unknown fields. A misspelled or extra property returns 400 naming it in param, rather than being silently dropped. A silently dropped field is a value you believe you sent and we never received.

The rule behind most of the conditional validation

A value that could not be obtained is never given a favourable reading. If availability is anything but available, the schema forces the accompanying value and band to null and the accompanying result to not_evaluated. You cannot construct a payload in which an unobtainable input scores well, and neither can we.

Envelope#

Assessment#

One assessment of one applicant against one policy version.

Inputs are append-only and results are written once. There is no endpoint that modifies a completed assessment. Re-running a case creates a new assessment carrying previous_assessment_id, which means a re-run can never overwrite the verdict a lender has already acted on, and the history of what was decided when survives intact.

Validated conditionally

This object carries a conditional rule: some fields are required, or constrained to null, depending on the value of another field. A payload that ignores it is rejected rather than accepted and corrected.

idstringrequired
pattern: ^asm_[A-Za-z0-9]+$
objectstringrequired
const: assessment
modeAssessmentModerequired
statusAssessmentStatusrequired
countrystringrequired
pattern: ^[A-Z]{2}$
livemodebooleanrequired

Always true in v1. There is no test environment; the documented examples are the only keyless surface. Carried from the start so that adding one later does not change the shape of a response.

created_atstringrequired
format: date-time
updated_atstring | null
format: date-time
completed_atstring | null
format: date-time
expires_atstring | null

The deadline for input an assessment is waiting on.

Treat this as the deadline to act on, not as a state to wait for. The transition to expired can lag this time. Stop waiting when expires_at passes; do not wait for status to become expired.

format: date-time
policy_versionstringrequired

Tenant-scoped, not a bare date. Two tenants cannot share a version namespace, so the version string identifies whose policy as well as which one.

previous_assessment_idstring | null

Set when this assessment re-runs an earlier one.

applicantApplicant
coverageCoveragerequired
resultAssessmentResult | null
failureError | null

Present only when status is failed.

metadatamap<string, string>

The opaque key-value pairs supplied on the create request, returned verbatim.

Never interpreted, never used in any evaluation, and never a place to put anything the contract has its own field for. Present on the assessment and on every callback carrying it, which is the cleanest way to correlate a result with your own case record without keeping a map of our identifiers.

Absent where the create request carried none.

Example
{
  "id": "asm_7NpF4c2wQ9",
  "object": "assessment",
  "mode": "screening",
  "status": "screening",
  "country": "EE",
  "livemode": true,
  "created_at": "2026-07-06T09:14:23Z",
  "updated_at": "2026-07-06T09:14:23Z",
  "completed_at": null,
  "expires_at": null,
  "policy_version": "tenant-policy-2026-07",
  "previous_assessment_id": null,
  "applicant": {
    "country": "EE",
    "registry_code": "10000000",
    "legal_name": "Example Trading OU"
  },
  "coverage": {
    "registry": "live",
    "financial_statements": "live",
    "tax": "not_supported",
    "bureau": "live",
    "sanctions": "live",
    "legal": "live",
    "beneficial_owners": "not_entitled",
    "bank_data": "not_consented",
    "acquiring": "not_supported",
    "bank_labels": "classifier"
  },
  "result": null
}

AssessmentList#

objectstringrequired
const: list
dataarray<Assessment>required
has_morebooleanrequired
next_cursorstring | null

Pass as starting_after to fetch the next page.

AssessmentMode#

Which of the two stages to run.

screening runs the first stage only. Cases that clear it are the only ones that go further.

Which conditions and ratios make up the first stage is declared on the policy version, at GET /v1/policies/{version}. It is a property of the policy, not of the market. What a first stage can actually reach depends on what the market publishes, and that is reported per case in coverage.

Both modes return 202 and deliver by callback, and both return the same response shape. They differ only in how far the evaluation runs.

ValueMeaning
screening
full

AssessmentStatus#

Where the assessment is. Terminal states are complete, failed and expired.

result is present if and only if the status is complete, and the schema enforces it.

ValueMeaning
screening

Public registry sources are being gathered and the first-stage gates evaluated.

awaiting_bank_data

Screening finished without a terminal outcome and bank data is required to go further. POST /v1/assessments/{id}/bank-data is accepted in this state and in no other.

processing

Paid sources and the full policy evaluation are running.

complete

Terminal. result is present.

failed

Terminal. Processing could not complete. Distinct from a policy rejection, which is a complete assessment whose outcome is reject.

expired

Terminal. Required input did not arrive within the window, so the assessment was closed without a result.

AssessmentResult#

The evaluated output. Written once and never modified.

policy_outcomePolicyOutcomerequired
supportable_amountSupportableAmount
gatesGatesrequired
financialsobjectrequired
no unknown fields
checksarray<PolicyCheck>

Every non-ratio condition the policy defines, including those that could not be evaluated. A condition absent from this array was not defined by the policy; a condition that could not be evaluated is present with result: not_evaluated.

credit_exposurearray<CreditExposure>

Existing credit per subject, as the bureau reports it. Empty where the policy runs no bureau enquiry.

indicatorsarray<Indicator>
reason_codesarray<ReasonCode>
analyst_questionsarray<AnalystQuestion>
evidenceEvidencerequired
inputsobject

The lender-supplied values this evaluation consumed, echoed raw. Present so a result is reproducible from the result alone, without going back to the request that produced it.

no unknown fields

Inputs#

Applicant#

Who is being assessed, in the identifiers the country's registries actually key on. Which identifiers are required, and their formats, are published per country at GET /v1/countries/{code} rather than fixed here.

countrystringrequired

ISO 3166-1 alpha-2.

pattern: ^[A-Z]{2}$
registry_codestringrequired

The national company registration number.

vat_numberstring | null
legal_formstring | null
legal_namestring | null
additional_identifiersmap<string, string>

The identifiers a market uses that are not one of the fields above.

Poland keys registry lookups on a tax number, holds its companies on a court register under a second number, and carries a third statistical number; the Baltic markets need none of those.

The accepted keys are exactly the field values that GET /v1/countries/{code} publishes for this country. Any other key is rejected with 400.

industry_codesarray<IndustryCode>

What the applicant trades in, each code qualified by its scheme. Supply whichever the lender holds; where none is supplied, Credit Atlas uses the classification the national registry carries for the entity, and an eligibility rule written against a scheme the case has no code for returns not_supported rather than passing by default.

Representative#

One natural person connected to the applicant.

A company may have several, and the contract takes them as a list. A company with two signatories and a separate majority owner is three people, and a policy that runs a personal condition reports its result per person.

Every check evaluated against a person names that person in PolicyCheck.subject.ref, which is why ref is required rather than convenient.

Personal identifiers are accepted only where the country's registry or bureau keys on them, and the assessment records which consent authorised each use. Where a market's beneficial-ownership or bureau source is restricted to entity classes that Credit Atlas does not belong to, the corresponding coverage is not_entitled or lender_supplied, and it is not attempted on the caller's behalf.

refstringrequired

Your own identifier for this person, unique within the request. It is echoed on every check evaluated against them and is never interpreted. Use whatever your own case record uses.

pattern: ^[A-Za-z0-9_.:-]{1,64}$
namestringrequired
rolestring | null

How this person is connected to the applicant, in your own vocabulary. Carried through to the audit trail and never parsed.

national_idstring | null

National personal identifier, where the market's sources require one. Optional everywhere. Policy.borrower_checks.required_identifiers says when a policy needs it.

date_of_birthstring | null
format: date

LoanRequest#

amountnumberrequired
min: 0
currencystringrequired
term_monthsinteger | null
min: 1
productstring | null

Tenant-defined product identifier.

PartnerData#

The data only the lender holds, because it describes the lender's own relationship with the borrower: how long that relationship has run, what the lender's own lists say about the counterparty, and the commercial data the lender holds from the products it already sells. A lender that also acquires the borrower's card payments holds processed turnover and chargeback behaviour that no registry publishes.

Where this object is absent, indicators defined over lender-held data return not_supported with requires naming what was missing, rather than being silently skipped.

relationship_monthsinteger | null
min: 0
mccstring | null

Merchant category code. Note that a code may sit under more than one category in a scheme's own tables, so an exclusion list keyed on it is not a clean lookup and the tenant's policy decides the mapping.

acquiring_turnover_monthly_avgnumber | null
min: 0
acquiring_currencystring | null
chargeback_ratio_30dnumber | null
min: 0max: 1
refund_ratio_30dnumber | null
min: 0max: 1
internal_list_matchobject | null

The lender's own list, as the lender resolved it.

The internal_blacklist condition is lender-supplied by definition. The contract takes the outcome of the lender's own lookup, not the list itself.

Omit the object entirely where no lookup was performed: the condition then reports not_supported with requires: [partner_data] rather than passing by default. An absent list is not a clean list.

no unknown fields
beneficial_ownersobject | null

The outcome of the lender's own beneficial-ownership screening.

Same pattern as internal_list_match. Access to beneficial-ownership registers is restricted to entities with a statutory basis for customer due diligence, so the lender performs the lookup and supplies the outcome.

Supplying this sets coverage.beneficial_owners to lender_supplied, which is a distinct state from live and from not_entitled: it records that the screening happened and that the lender did it.

Omit the object entirely where no screening was performed. The beneficial_owners_screened condition then reports not_evaluated, and if the policy marks it mandatory the outcome is capped. An absent screening is not a clean one.

no unknown fields

Consents#

The lender's attestation that it holds the consents its request requires.

Credit Atlas does not capture consent from the borrower and does not present a consent screen. The lender is the controller of that relationship; this object records what the lender attests to holding, with the time it was captured, so the attestation is auditable against the assessment it authorised.

data_processing must be true for any assessment. The others gate specific sources: without bureau_enquiry no bureau is called, and without account_information bank data is refused rather than merely unused, with coverage.bank_data: not_consented.

data_processinganyrequired

Must be true. An assessment cannot proceed without it.

const: True
bureau_enquiryboolean
default: False
account_informationboolean

PSD2 account-information access for the borrower's bank data.

default: False
captured_atstringrequired
format: date-time
referencestring | null

The lender's own reference for the consent record.

Bank data#

BankDataSubmission#

Bank transaction data for an assessment, submitted by the lender.

The lender initiates the borrower's account-information journey on its own institution agreement and submits the result here.

Volume and currency. A submission carries at most 50,000 transactions across at most 50 accounts, and the request body must not exceed 10 MB. A file larger than this is a sign that the window is wider than any policy needs; narrow the window rather than splitting the submission, because there is exactly one permitted submission per assessment and a partial one cannot be topped up.

Transaction currency does not have to match the currency of the loan request, and accounts in several currencies may be submitted together. Amounts are used as supplied, in the currency each transaction declares; the contract performs no conversion. Where a policy's threshold is stated in one currency and the evidence arrives in another, the indicator reports the currency it measured in and the policy decides whether the comparison is meaningful.

Minimum history is tenant policy, not a fixed number in this contract. It is evaluated against coverage.days_measured, meaning what actually arrived, and never against declared_from/declared_to, which is what the upstream promised.

providerBankDataProviderrequired
accountsarray<BankAccount>required
min items: 1max items: 50
transactionsarray<BankTransaction>required

At most 50,000 items. A submission exceeding this, or exceeding the 10 MB body limit, is rejected with 413 and nothing is stored. The assessment stays in awaiting_bank_data and the corrected submission is still the one permitted submission.

max items: 50000
declared_fromstring | null

The start of the window the upstream says it covers, where it says so. What was actually measured is reported back in coverage.

format: date
declared_tostring | null
format: date

BankDataProvider#

Which shape the submitted bank data has. Not a vendor name: the contract cares about one difference only, which is whether transactions arrive categorised.

The schema normalises transport, direction, dates and balances across both shapes. It does not invent categories the upstream never sent.

ValueMeaning
labelled

Transactions arrive with a category per row supplied by the provider. category_source is provider.

unlabelled

Transactions arrive as amount, date, counterparty and free text. Categories are present only if a classifier is deployed for this market, and coverage.bank_labels says which case applies.

BankAccount#

idstringrequired

The submitter's identifier for the account. Used to group transactions.

iban_last4string | null

Last four characters only. The full account identifier is not required to compute anything in this contract and is not accepted.

currencystringrequired
institutionstring | null

Opaque institution identifier as the submitter's provider issues it.

balancenumber | null
balance_atstring | null
format: date-time

BankTransaction#

Validated conditionally

This object carries a conditional rule: some fields are required, or constrained to null, depending on the value of another field. A payload that ignores it is rejected rather than accepted and corrected.

idstring | null

The provider's transaction identifier where one exists. Some feeds issue none, in which case deduplication falls back to account, date and amount. That is weaker, and is why this field is requested whenever available.

account_idstringrequired
booked_atstringrequired
format: date
value_datestring | null

Where the upstream distinguishes booking date from value date. Absent from some feeds, which is why both are carried rather than one being assumed.

format: date
amountnumberrequired

Unsigned. Direction is carried separately.

min: 0
currencystringrequired
directionTransactionDirectionrequired
counterpartystring | null
descriptionstring | null
balance_afternumber | null
categorystring | null

Null when no categories are available for this market.

category_sourceCategorySource | null
category_confidencenumber | null

Present when category_source is classifier. A provider label carries no confidence because none is published with it.

min: 0max: 1

TransactionDirection#

Normalised direction. Submitted amounts may be signed or unsigned depending on the upstream; direction is always explicit here so that sign conventions cannot silently invert a cash-flow calculation.

ValueMeaning
credit
debit

CategorySource#

Where a transaction's category came from. Required whenever a category is present, so that a threshold calibrated on provider labels is never applied unknowingly to classifier output.

ValueMeaning
provider
classifier

BankDataCoverage#

How much history the bank data actually spans, declared and measured separately.

Only some upstreams declare a coverage window up front. Where one does, the declared window and the window the transactions actually occupy can differ. A policy requiring a minimum history must be evaluated against what arrived, not against what was promised. Reporting one number for both is how a short file passes a history test it should have failed.

declared_fromstring | null
format: date
declared_tostring | null
format: date
days_declaredinteger | null

Null where the upstream declares no window.

min: 0
measured_fromstring | nullrequired
format: date
measured_tostring | nullrequired
format: date
days_measuredintegerrequired

Span actually covered by the submitted transactions.

min: 0
accountsinteger
min: 0
transactionsinteger
min: 0

Financials#

CanonicalKey#

Country-neutral name for a financial statement line item. Fifteen keys carry every ratio this API computes. A market is added by mapping its filing scheme onto these keys. No ratio definition changes.

ValueMeaning
cash

Cash and cash equivalents.

receivables

Trade receivables and prepayments.

inventory

Inventories.

current_assets

Total current assets.

total_assets

Total assets.

short_term_borrowings

Borrowings falling due within twelve months.

current_liabilities

Total current liabilities.

total_liabilities

Total liabilities, current and non-current.

equity

Total equity.

revenue

Net sales revenue for the period.

depreciation_amortisation

Depreciation, amortisation and impairment of fixed assets.

operating_profit

Operating profit.

interest_expense

Interest and similar finance costs.

net_profit

Profit for the reporting period.

operating_cash_flow

Net cash flow from operating activities.

LineItem#

Validated conditionally

This object carries a conditional rule: some fields are required, or constrained to null, depending on the value of another field. A payload that ignores it is rejected rather than accepted and corrected.

keyCanonicalKeyrequired
valuenumber | null

Null whenever availability is anything but available.

currencystring | null

ISO 4217.

availabilityAvailabilityrequired
reasonstring | null

Human-readable explanation, generated from availability and the entity's circumstances. Present whenever availability is not available.

source_refSourceRef | null
Example
{
  "key": "current_assets",
  "value": 412300,
  "currency": "EUR",
  "availability": "available",
  "source_ref": {
    "scheme": "XX_NATIONAL_REGISTER",
    "row": "0000",
    "period": "2025"
  }
}

SourceRef#

Where a value came from, in the source's own terms. Present only when availability is available.

scheme and row are the native identifiers of the filing scheme the value was read from, and are opaque to the contract: ratios are defined on canonical keys, never on scheme rows.

schemestringrequired

Identifier of the filing or reporting scheme.

rowstring

The line reference within that scheme, as the scheme labels it.

periodstring

Reporting period the value was read from.

retrieved_atstring
format: date-time

Availability#

Why a value is or is not present. Applies uniformly to line items, ratios and indicators.

A missing value is a state, not an error. not_filed and source_unavailable are different facts about the borrower, and only one of them is worth retrying.

ValueMeaning
available

Obtained.

not_filed

The entity is legally exempt from filing this, or filed an abridged form that omits it. Not an error, and not a negative signal by itself.

not_published

No public source exists for this item for this entity type in this country. Typically sole traders, whose financial statements are not published anywhere.

not_consented

Requires a consent that has not been recorded yet. Usually bank data before the borrower has completed the account-information journey.

not_entitled

Requires an entitlement or licence that the caller, or Credit Atlas, does not hold for this source in this market. Distinct from a failure: the source is working and the request was well formed, but it may not lawfully be served.

source_unavailable

The source exists and we are entitled to it, but the call did not succeed. Retryable.

not_supported

The country adapter does not implement this item yet. Declared in advance via the country capability map, never discovered at runtime.

Ratio#

Validated conditionally

This object carries a conditional rule: some fields are required, or constrained to null, depending on the value of another field. A payload that ignores it is rejected rather than accepted and corrected.

keystringrequired

Stable identifier for the ratio.

One of current_ratio, quick_ratio, cash_ratio, equity_ratio, net_profit_margin, operating_profit_margin, return_on_assets, operating_cash_flow_ratio, days_sales_outstanding, interest_coverage, debt_service_coverage, debt_to_ebitda

labelstring
groupRatioGrouprequired
directionRatioDirectionrequired
formulastring

The definition in canonical keys. Stated so an integrator can reproduce the number without reference to any national filing scheme.

inputsarray<CanonicalKey>

Canonical keys this ratio consumes.

valuenumber | null
unitstring

One of ratio, percent, days, times

availabilityAvailabilityrequired
bandBandrequired
missing_inputsarray<CanonicalKey>

Canonical keys that prevented computation. Empty when availability is available. This is what makes an uncomputed ratio diagnosable rather than merely absent.

reasonstring | null
thresholdsarray | null

The band boundaries applied, from the policy version named on the assessment. Three boundaries produce four bands. Returned only to the tenant that owns the policy.

min items: 3max items: 3
Example
{
  "key": "current_ratio",
  "label": "Current ratio",
  "group": "liquidity",
  "direction": "higher_is_better",
  "formula": "current_assets / current_liabilities",
  "inputs": [
    "current_assets",
    "current_liabilities"
  ],
  "value": 2.08,
  "unit": "ratio",
  "availability": "available",
  "band": "strong",
  "missing_inputs": [],
  "thresholds": [
    0.9,
    1.4,
    1.8
  ]
}

RatioGroup#

Ratio grouping. The group is reported on every ratio because a policy may apply different rules to different groups; what those rules are is tenant configuration.

ValueMeaning
liquidity
profitability
operating_efficiency
credit_risk

RatioDirection#

Which end of the scale is strong. higher_is_better bands ascending; lower_is_better bands descending. Direction is explicit on every ratio rather than implied by its name.

ValueMeaning
higher_is_better
lower_is_better

Band#

Ordinal assessment band, weakest first. Null means the ratio could not be computed, because an input was unavailable or the arithmetic was undefined, such as a zero denominator.

A null band is never treated as a passing band, and is never substituted with a favourable one. Policies that count "poor" ratios must count null separately; it is an absence of evidence, not weak evidence.

ValueMeaning
poor
fair
good
strong
null

RatioSummary#

Counts of ratios by band, split by group. Which rule applies to which group is tenant configuration and is not described here.

unavailable is reported alongside poor and never folded into it, and computable is the denominator a poor count is measured against.

poorobjectrequired
no unknown fields
unavailableobjectrequired
no unknown fields
computableobject

The denominator each group's poor count is measured against. It counts ratios that could actually be computed, not ratios that are defined. A rule stated as a count is meaningless without it.

no unknown fields
poor_rateobject

poor divided by computable, per group. Which line items an entity must file depends on its size class, so the denominator varies between borrowers and a rule expressed as a rate keeps its meaning at any denominator. EvidenceSufficiency sets the floor below which the rate is not read at all.

no unknown fields
evaluatedintegerrequired

Ratios with a non-null band.

totalintegerrequired

Ratios defined for this assessment.

Example
{
  "poor": {
    "credit_risk": 1,
    "other": 3
  },
  "unavailable": {
    "credit_risk": 0,
    "other": 1
  },
  "computable": {
    "credit_risk": 3,
    "other": 8
  },
  "poor_rate": {
    "credit_risk": 0.333,
    "other": 0.375
  },
  "evaluated": 11,
  "total": 12
}

Outcome#

PolicyOutcome#

The outcome, the policy version that produced it, and what constrained it.

capped_by says which happened: policy means the rules chose the outcome, evidence means thin evidence forced it. Those need different handling in a queue.

Validated conditionally

One or more ceiling rules apply: a more favourable value is rejected when the evidence does not support it. The constraint is one-directional, so a less favourable value always remains valid.

valuePolicyOutcomeValuerequired
policy_versionstringrequired

The tenant policy version applied. Every outcome is reproducible from it.

evidence_sufficiencyEvidenceSufficiencyrequired
capped_bystring | null

evidence when the sufficiency gate capped the outcome below what the policy's rules alone would have produced; policy when the rules themselves determined it; null when nothing capped it.

One of evidence, policy, null

Example
{
  "value": "review",
  "policy_version": "tenant-policy-2026-07",
  "capped_by": "evidence",
  "evidence_sufficiency": {
    "level": "degraded",
    "outcome_ceiling": "review",
    "groups": {
      "credit_risk": {
        "computable": 2,
        "defined": 3,
        "floor": 3,
        "met": false
      },
      "other": {
        "computable": 8,
        "defined": 9,
        "floor": 8,
        "met": true
      }
    },
    "reason": "A ratio in the credit-risk group could not be computed for this entity class."
  },
  "ratios": {
    "poor": {
      "credit_risk": 0,
      "other": 1
    },
    "unavailable": {
      "credit_risk": 1,
      "other": 1
    },
    "computable": {
      "credit_risk": 2,
      "other": 8
    },
    "poor_rate": {
      "credit_risk": 0,
      "other": 0.125
    },
    "evaluated": 10,
    "total": 12
  }
}

PolicyOutcomeValue#

The result of applying the lender's own configured policy to the evidence gathered. It is not a creditworthiness decision made by Credit Atlas, and it does not replace one. The lender's analyst retains decision authority.

ValueMeaning
approve

The policy's conditions for its most favourable outcome were all met.

review

The policy routed this to a human, or the evidence was too thin to permit a more favourable outcome. Which of the two it was is in capped_by.

reject

The policy's own rejection conditions were triggered by observed values.

insufficient_evidence

This is not a rejection, and integrators must not map it to one. No conclusion about the subject was reached, because too little could be computed. An entity's filing obligations follow from its size class, so mapping this outcome to a rejection turns an applicant's size into a credit negative.

EvidenceSufficiency#

The sufficiency gate, evaluated per ratio group and before the policy's decision rules. It can cap an outcome. It can never improve one.

Groups are judged separately rather than on the total, so thin evidence in one group is visible rather than averaged away.

Floors are policy configuration, returned only to the tenant that owns the policy.

Validated conditionally

One or more ceiling rules apply: a more favourable value is rejected when the evidence does not support it. The constraint is one-directional, so a less favourable value always remains valid.

levelEvidenceLevelrequired
outcome_ceilingPolicyOutcomeValuerequired

The most favourable outcome reachable given the evidence. The policy's own rules may land below this; they can never land above it.

groupsobjectrequired
no unknown fields
unavailable_mandatory_checksarray<string>

Non-ratio conditions the policy marks mandatory that could not be evaluated.

Any entry here forces outcome_ceiling below approve, enforced by the schema. The ceiling constrains only the favourable direction, so reject stays reachable and a condition that did fire still fires on a thin file.

A condition the policy runs per representative or per related company appears here once per subject it could not be evaluated for, written <key>:<ref>, so a reader can tell one unscreened director from three.

reasonstring | null

Why the level is what it is, naming the group or the condition and the shortfall. Present whenever level is not sufficient.

Example
{
  "level": "degraded",
  "outcome_ceiling": "review",
  "groups": {
    "credit_risk": {
      "computable": 2,
      "defined": 3,
      "floor": 3,
      "met": false
    },
    "other": {
      "computable": 8,
      "defined": 9,
      "floor": 8,
      "met": true
    }
  },
  "unavailable_mandatory_checks": [],
  "reason": "A ratio in the credit-risk group could not be computed for this entity class, so the group is below the floor its rules assume."
}

EvidenceLevel#

How much evidence the assessment has, judged before any policy rule is applied to it.

An input that could not be obtained never improves an outcome. Unavailable items leave the denominator the policy's counts are measured against, and this level independently caps what outcome is reachable at all. It can only cap a result, never raise one.

ValueMeaning
sufficient

Enough of each group was computable for the policy's rules to carry their intended meaning. The full decision table applies.

degraded

Computable, but on a materially thinner base than the policy assumes. The outcome is capped, so the most favourable outcome becomes unreachable however good the computed values look.

insufficient

Too little was computable to support any conclusion about the subject. This is a statement about the evidence, never about the subject.

EvidenceGroup#

computableintegerrequired

Ratios in this group that could actually be computed.

min: 0
definedintegerrequired

Ratios the catalogue defines for this group.

min: 0
floorintegerrequired

Minimum computable count this group requires. Tenant configuration.

min: 0
metbooleanrequired

Gates#

The assessment's stages and how each one ended, so an analyst can see where a case turned.

Which gates exist is fixed by the contract; what each one does is the policy. Evaluation stops at the first fail, so no further source is consulted once a case has ended.

eligibilityGateResultrequired
registryGateResultrequired
amlGateResultrequired
financialGateResultrequired
monitoringGateResultrequired
Example
{
  "eligibility": "pass",
  "registry": "pass",
  "aml": "pass",
  "financial": "review",
  "monitoring": "pass"
}

GateResult#

Per-stage result. not_evaluated is distinct from pass: a gate that never ran because an earlier gate stopped the assessment has not passed anything.

ValueMeaning
pass
review
fail
not_evaluated

SupportableAmount#

The amount the evidence supports, with its own availability.

A capacity of zero and a capacity that could not be computed are opposite findings: a null value means the capacity could not be computed, a zero value means the computed capacity is nothing.

Validated conditionally

This object carries a conditional rule: some fields are required, or constrained to null, depending on the value of another field. A payload that ignores it is rejected rather than accepted and corrected.

valuenumber | nullrequired
min: 0
currencystring | nullrequired

ISO 4217. Explicit, never inferred from the country.

availabilityAvailabilityrequired
basisstring | null

Which computed quantity the cap derives from, named in the contract's own vocabulary so it can be traced to a ratio or an indicator.

reasonstring | null
Example
{
  "value": 84000,
  "currency": "EUR",
  "availability": "available",
  "basis": "debt_service_coverage"
}

Checks#

PolicyCheck#

One non-ratio condition, evaluated against one subject: what it observed, what it was compared against, and whether it could be evaluated at all.

Reported for every condition the policy defines, including the ones that could not be evaluated. A condition absent from this array was not defined by the policy.

One condition can appear more than once. A condition the policy runs against each representative produces one entry per person, distinguished by subject. A consumer that assumes key is unique in this array will silently drop all but one of them.

Threshold values are policy configuration, returned only to the tenant that owns the policy.

Validated conditionally

This object carries a conditional rule: some fields are required, or constrained to null, depending on the value of another field. A payload that ignores it is rejected rather than accepted and corrected.

keyCheckKey | stringrequired

Which condition this is.

Either one of the contract's own CheckKey values, or a condition this product's policy version declared for itself, written custom.<name>. The fixed vocabulary is what lets two integrators agree on what a condition is called; the custom form is what lets a lender bring a condition the vocabulary does not have.

customboolean

True when key is a custom.<name> condition. Present so a consumer can separate the contract's own vocabulary from a tenant's own without parsing the key.

default: False
subjectCheckSubjectrequired
labelstring

Display name. Generated from key; never the only place a fact appears.

stagestringrequired

Which gate this condition belongs to. Matches a key of gates.

One of eligibility, registry, aml, financial, monitoring

availabilityAvailabilityrequired
resultCheckResultrequired
mandatorybooleanrequired

Whether the policy's most favourable outcome depends on this condition being evaluated.

A mandatory condition that could not be evaluated caps the outcome. See EvidenceSufficiency.unavailable_mandatory_checks. A non-mandatory one that could not be evaluated is recorded and does not cap anything.

observednumber | string | boolean | null

The value measured. Null whenever availability is not available, enforced by the schema below.

scalestring | null

The RatingScale.id that observed and threshold are expressed on, where this condition is a comparison on a scale. Null for conditions that are not, such as a boolean or a bare count.

Present so the comparison can be reproduced. On an ordinal scale the ranking is the position of the value in the scale's grades array; comparing the grades as strings gives the wrong answer and must not be done.

thresholdnumber | array<number> | string | boolean | null

What observed was compared against. Polymorphic by necessity: a floor is a number, a review corridor is a pair, a rating floor is a grade on the scale named in scale, and a condition such as a sanctions result has no threshold at all.

sourcestring | null

Which evidence produced the observation, in the same vocabulary as evidence.sources[].source.

messagestring | null

Display string, generated from the fields above.

Example
{
  "key": "sanctions_match",
  "subject": {
    "kind": "company"
  },
  "stage": "aml",
  "label": "Sanctions screening",
  "availability": "not_entitled",
  "result": "not_evaluated",
  "mandatory": true,
  "observed": null,
  "threshold": null,
  "source": "sanctions.screening",
  "message": "Sanctions screening was not performed, because it requires an entitlement that is not in place for this market. This is not a statement that the applicant is clear."
}

CheckKey#

The vocabulary of non-ratio conditions a policy may evaluate.

Which of these a given policy actually uses, in what order, and against what boundary is tenant configuration. The vocabulary is fixed by the contract so that two integrators building against it agree on what a condition is called.

A key appearing here is not a promise that the data behind it is obtainable in every market. GET /v1/countries/{code} says where it is, and each check carries its own availability.

ValueMeaning
registered_address

Whether the entity is registered in a market the policy admits.

annual_reports_available

How many periods of filed statements exist.

industry_eligibility

Whether the borrower's trade category is admitted. Evaluated against the applicant's industry_codes, each of which names the scheme its code belongs to. A policy's admitted and excluded lists are configured per scheme, because a card scheme's merchant categories and a national activity classification are different vocabularies and do not map onto one another. Note that a code alone can be ambiguous, because the same code is used by more than one trade in the published assignments, so a policy that turns solely on it will misclassify some borrowers in both directions.

partner_relationship_length

How long the applicant has been a customer of the lender.

average_monthly_turnover

Turnover over the policy's averaging window.

chargeback_ratio

Chargebacks as a share of acquiring volume.

credit_rating

An external rating or score, compared against a floor on a declared scale. The scale is named in PolicyCheck.scale and published in Country.rating_scales; the floor is tenant configuration expressed on that same scale. Markets do not share a scale and the contract does not convert between them.

probability_of_default

An externally supplied default probability, compared against a reject boundary and a review corridor. Two boundaries, not one. Where a market publishes a default probability rather than a graded rating, this is the condition a policy writes instead of credit_rating, and the scale runs in the opposite direction, so lower is better.

tax_debt

Outstanding tax debt, usually expressed relative to turnover.

payment_defaults

Count of historical defaults within a lookback window. A policy may require a default to clear more than one test before it counts, a minimum age and a minimum amount for instance, so the count reported here is the count after the policy's own qualifying rule has been applied.

active_defaults

Whether any default is currently open.

legal_proceedings

Court rulings or proceedings on record against the entity.

sanctions_match

Result of sanctions screening. Where screening cannot lawfully be performed on the caller's behalf, availability is not_entitled and the check is not_evaluated, never pass.

beneficial_owners_screened

Whether beneficial owners were identified and screened. Public access to beneficial-ownership registers is restricted in several markets to entities with a statutory basis, so this is frequently not_entitled.

high_risk_jurisdiction

Exposure to a jurisdiction the policy treats as high risk.

internal_blacklist

A match against the lender's own list. Lender-supplied by definition.

revenue_trend

Average monthly revenue over the recent window divided by the average over an earlier window, from bank data. Both windows are policy configuration. Compared against a reject floor and a review corridor.

ebitda_positive

Whether earnings before interest, tax, depreciation and amortisation are positive.

CheckResult#

How one condition ended.

not_evaluated is distinct from pass. Sanctions screening that could not be performed is not a statement that the applicant is clear, and the contract will not let it be reported as one.

ValueMeaning
pass
review
fail
not_evaluated

Explainability#

ReasonCode#

Why the outcome is what it is, as data rather than prose.

Every code carries the value observed and the threshold it was compared against and the policy version that set that threshold, so an outcome can be replayed months later against the rules that were in force when it was produced.

message is generated from the structured fields. It is never the only place a fact appears. Anything an integrator might want to act on is a field.

codestringrequired

Stable identifier, unique within a policy version.

severityReasonSeverityrequired
driverstringrequired

What was measured, in the contract's own vocabulary: a ratio key, an indicator key, or a named gate input.

observednumber | string | null

The value measured. Null when the code fired on an absence.

thresholdnumber | array<number> | string | boolean | null

What observed was compared against. Polymorphic by necessity: a floor is a number, a review corridor is a pair, a rating floor is a string, and a condition that is simply required is a boolean.

Boundaries are policy configuration, returned only to the tenant that owns the policy.

bandBand
sourcestring | null

Which evidence produced the observation, in the same vocabulary as evidence.sources[].source.

policy_versionstringrequired

The policy version whose threshold this code was evaluated against. Repeated per code rather than only on the assessment, because a code may be carried forward from an earlier evaluation.

messagestringrequired

Display string, generated from the fields above.

Example
{
  "code": "FIN-07",
  "severity": "review",
  "driver": "debt_service_coverage",
  "observed": 0.94,
  "threshold": 1.35,
  "band": "poor",
  "source": "registry.financial_statements",
  "policy_version": "tenant-policy-2026-07",
  "message": "Debt service coverage below the configured floor."
}

ReasonSeverity#

ValueMeaning
info

Recorded as a driver but did not constrain the outcome.

review

Contributed to routing the case to a human.

reject

Sufficient on its own, under the tenant's policy, to trigger its rejection conditions.

AnalystQuestion#

A question for the lender's analyst to put to the borrower, generated from the drivers that constrained the outcome.

The API produces the evidence and the questions that evidence raises, and the lender's analyst decides.

text is the question as it should be shown. The structured fields are there so each question can be routed, tracked and closed against the driver that raised it.

idstringrequired
textstringrequired
driverstring | null

The ratio, indicator or gate input that raised it.

relates_tostring | null

The ReasonCode.code this question exists to resolve, when there is one.

evidence_requestedstring | null

What would answer it, stated so the request can be made once.

Indicator#

A single behavioural or fraud signal. Indicators follow the same availability discipline as ratios: one that could not be computed is reported with triggered: null, never triggered: false.

false means the pattern was looked for and is absent. null means nobody looked, and it is never reported as false.

Validated conditionally

This object carries a conditional rule: some fields are required, or constrained to null, depending on the value of another field. A payload that ignores it is rejected rather than accepted and corrected.

keyIndicatorKeyrequired
labelstring
categoryIndicatorCategoryrequired
availabilityAvailabilityrequired
triggeredboolean | nullrequired

Null whenever availability is not available. Never defaulted to false.

observednumber | string | null
requiresarray<IndicatorRequirement>

Capabilities this indicator needs. Explains any non-available state.

reasonstring | null
Example
{
  "key": "single_day_turnover_spike",
  "label": "Single-day turnover spike",
  "category": "fraud",
  "availability": "available",
  "triggered": false,
  "observed": 2.4,
  "requires": [
    "transaction_amounts"
  ]
}

IndicatorCategory#

What an indicator is about. fraud and lending are derived from bank transaction data; acquiring needs card-level data that only the lender's own acquiring relationship produces.

ValueMeaning
fraud
lending
acquiring

IndicatorRequirement#

A capability an indicator cannot be computed without. Published on the indicator itself, so the reason an indicator is unavailable in a market can be read in advance.

ValueMeaning
transaction_amounts

Amounts and dates only. Available from every bank-data adapter.

transaction_labels

A category per transaction. Some aggregators supply these; a raw PSD2 feed does not, and no classifier exists for every market. See coverage.bank_labels.

counterparty_names

A named creditor or debtor per transaction.

counterparty_jurisdiction

The country of the counterparty, which most PSD2 feeds do not carry.

acquiring_data

Card-level settlement data. Held by the lender when the lender is also the acquirer, and obtainable nowhere else.

Evidence#

Evidence#

Everything the assessment was built from. Present on every result, including a rejected one.

sourcesarray<EvidenceSource>required
statements_probearray<StatementsProbe>
bank_dataBankDataCoverage | null

EvidenceSource#

One source consulted, and what came back.

sourcestringrequired

Stable, country-neutral identifier for the source class. Named third parties do not appear in this field.

availabilityAvailabilityrequired
retrieved_atstring | null
format: date-time
periodstring | null
billableboolean | null

Whether this retrieval was chargeable. Reported so a lender can reconcile its own source costs per assessment.

referencestring | null

The source's own reference for the retrieval, where it issues one.

reasonstring | null

StatementsProbe#

What the entity actually filed for a period, established by a capability probe before any statement is fetched.

One probe call per entity turns a missing value into a statement that was never required: not_filed rather than source_unavailable.

periodstringrequired
size_classSizeClassrequired
abridgedboolean | null

Whether the entity filed an abridged form. Where a filing exemption is conditional on the abridged format, an entity that filed in full may carry items its size class would ordinarily omit, so this is probed and never assumed from size class alone.

statements_filedarray<string>
statements_absentarray<string>

SizeClass#

The entity's reporting size class, which governs what it is obliged to file and therefore which ratios can exist at all.

The class is established before any statement is fetched, so the ratio set a borrower can produce is known in advance rather than inferred from what came back empty.

ValueMeaning
micro
small
medium
large
unknown

Capability#

Coverage#

What was consulted for this assessment, and why anything was not. Returned on every assessment, so no absence has to be inferred from a gap in the output.

This is a record, not a forecast. It says what happened on this case and makes no claim about what a different case in the same market would reach.

registryCoverageStaterequired
financial_statementsCoverageStaterequired
taxCoverageStaterequired
bureauCoverageStaterequired
sanctionsCoverageStaterequired
legalanyrequired

Court rulings, insolvency proceedings and enforcement records. Reported separately from registry because the register that holds a company's identity and the register that holds proceedings against it are different registers, on different terms, in every market this contract serves. A policy evaluating legal_proceedings reads this field to learn whether the condition could be evaluated at all.

beneficial_ownersCoverageStaterequired
bank_dataCoverageStaterequired
acquiringCoverageStaterequired
bank_labelsBankLabelSourcerequired
Example
{
  "registry": "live",
  "financial_statements": "live",
  "tax": "not_supported",
  "bureau": "live",
  "sanctions": "live",
  "legal": "live",
  "beneficial_owners": "lender_supplied",
  "bank_data": "live",
  "acquiring": "not_consented",
  "bank_labels": "classifier"
}

CoverageState#

Whether a *source* is usable for this assessment. A different enum from Availability, which describes a *value*: a source can be live while a particular value is absent because the entity never filed it.

ValueMeaning
live

Implemented, licensed, and called for this assessment.

lender_supplied

Not retrieved by Credit Atlas. The lender performed the lookup under its own entitlement and supplied the outcome on the request, and the assessment used what it was given. Reported distinctly so the audit trail records which party performed the lookup.

not_consented

Implemented, but the required consent has not been recorded.

not_entitled

Implemented, but serving it in this market requires an entitlement that is not in place, and the lender supplied nothing in its place.

not_supported

Not implemented for this market.

source_unavailable

Implemented and entitled, but the call did not succeed.

BankLabelSource#

Where transaction categories come from in this market, or that there are none.

Some account-information providers return a category per transaction. A raw open-banking feed returns a counterparty name, a free-text reference and nothing else. Any indicator defined over categories is unavailable in the second case unless a classifier has been built for that market's language and text.

ValueMeaning
provider

The bank-data provider supplies a category per transaction.

classifier

Categories are derived by a Credit Atlas classifier from unlabelled transaction text. Each category carries a confidence, and category_source says so on every transaction.

not_supported

No categories are available in this market. Indicators requiring transaction_labels return not_supported rather than a default value.

Country#

What a market can do, declared in advance.

A market that is declared but not implemented appears here with status: declared, never absent from the list and never failing at runtime.

What a market reached on any individual case is reported on that assessment, in Assessment.coverage. It is not promised here.

codestringrequired
pattern: ^[A-Z]{2}$
namestringrequired
statusstringrequired

One of live, limited, declared

identifier_schemaarray<IdentifierField>required
rating_scalesarray<RatingScale>

The rating and score scales this market's sources actually return.

Published per country because markets do not share one. A bureau in one market grades on ordered letters, another returns a number where a higher value is better, a third returns a number where a lower value is better. A policy that names a floor names it on one of these scales, and a consumer that wants to render or re-check the comparison needs the scale to do it.

A market with no rating source publishes an empty array.

industry_schemesarray<string>

The classification schemes an eligibility rule can be written against in this market. A card scheme's merchant categories are global; a national activity classification is not, and the two do not map onto one another cleanly.

currencystring | null
notesstring | null

CountryList#

objectstringrequired
const: list
dataarray<Country>required

IdentifierField#

One identifier a country requires, with the format its registry actually uses. Published so an integrator can validate before sending rather than discovering the format from a 400.

fieldstringrequired
labelstring
requiredbooleanrequired
patternstring | null

Regular expression the value must match.

notesstring | null

Policy#

A tenant's own policy version, as applied.

One version corresponds to one lending product. A lender running several products holds several versions, and policy_version on the assessment is the only thing that selects between them: the rules, the boundaries and the custom inputs all travel together under that one identifier, so an outcome is reproducible from it.

This endpoint returns only the calling tenant's configuration. A tenant can read the policy it owns and no other, and no boundary from any other tenant's policy appears in any field.

versionstringrequired
countrystringrequired
pattern: ^[A-Z]{2}$
productstring | null

Which lending product this version governs, in the lender's own vocabulary. Recorded so two versions can be told apart without decoding the identifier.

effective_fromstring | null
format: date
effective_tostring | null

Null while current. A superseded version stays readable so past outcomes replay.

format: date
screening_stageobjectrequired

What mode: screening evaluates.

The first stage is a property of the policy, not of the market, so it means the same thing in every country the policy covers.

A condition named here that the market cannot reach still reports not_evaluated on the assessment. Declaring a condition does not make its source exist.

no unknown fields
ratio_bandsmap<string, array<number>>required

Per ratio key, the three boundaries that produce the four bands, in the direction the ratio bands. The caller's own values.

check_thresholdsmap<string, number | array<number> | string | boolean | null>

Per condition, the boundary it is compared against.

Keyed by CheckKey or by custom.<name>. The value takes the same shapes as PolicyCheck.threshold: a number for a floor, a pair for a review corridor, a grade for a rating floor on that market's scale, a boolean for a condition that is simply required, or null for one that has no boundary.

mandatory_checksarray | null

Which conditions cap the outcome when they cannot be evaluated. The same list that drives EvidenceSufficiency.unavailable_mandatory_checks.

evidence_floorsmap<string, integer>required

Minimum computable ratio count per group, as configured.

decision_rulesarray | null

The ordered rules that map observations to an outcome. First match wins; reaching the end without a match yields review.

rating_floorsobject | null

Per RatingScale.id, the least favourable value the policy admits on that scale, expressed in that scale's own terms.

A floor is written on one scale and is meaningful only on it. The contract performs no conversion between scales, so a policy operating in several markets carries a floor per market rather than one global grade.

custom_inputsarray | null

The inputs this product accepts beyond the contract's own fields, and the shape each value must take. Null or empty where this product declares none.

borrower_checksobject

Whether this policy evaluates conditions against the people representing the applicant, and which.

Declared on the policy, not inferred from whether representatives was sent.

no unknown fields
related_company_checksobject | null

Whether this policy screens the companies supplied in related_companies, and with which conditions. Null or enabled: false means related_companies is recorded but not used.

no unknown fields
requires_bank_dataobject | null

The setting that sends an assessment to awaiting_bank_data.

A full assessment moves to awaiting_bank_data when the policy defines any condition that bank data is the only evidence for, and the first stage has not already reached a terminal outcome. Read this to know, before sending a case, whether it will be asked for bank data.

mode: screening never enters this state whatever this setting says, because the first stage does not run conditions that need bank data.

no unknown fields
Example
{
  "version": "tenant-policy-bnpl-2026-07",
  "country": "EE",
  "product": "bnpl",
  "effective_from": "2026-07-01",
  "effective_to": null,
  "screening_stage": {
    "checks": [
      "registered_address",
      "industry_eligibility",
      "annual_reports_available"
    ],
    "ratios": [
      "current_ratio",
      "equity_ratio"
    ],
    "terminal_outcomes": [
      "reject"
    ]
  },
  "ratio_bands": {
    "current_ratio": [
      0.9,
      1.4,
      1.8
    ],
    "equity_ratio": [
      0.1,
      0.25,
      0.4
    ]
  },
  "check_thresholds": {
    "probability_of_default": [
      2.0,
      6.0
    ],
    "payment_defaults": 5,
    "sanctions_match": null,
    "custom.basket_value": 1000
  },
  "mandatory_checks": [
    "sanctions_match",
    "registered_address"
  ],
  "evidence_floors": {
    "credit_risk": 3,
    "other": 8
  },
  "decision_rules": [
    {
      "id": "R-01",
      "outcome": "reject",
      "conditions": [
        {
          "subject": "check.sanctions_match",
          "operator": "eq",
          "value": "fail"
        }
      ]
    },
    {
      "id": "R-02",
      "outcome": "approve",
      "conditions": [
        {
          "subject": "poor_count.credit_risk",
          "operator": "eq",
          "value": 0
        }
      ]
    }
  ],
  "rating_floors": {
    "bureau_alpha_7": "B1",
    "bureau_pd_percent": 6.0
  },
  "custom_inputs": [
    {
      "name": "basket_value",
      "label": "Basket value",
      "type": "number",
      "unit": "EUR",
      "minimum": 0,
      "maximum": 5000,
      "mandatory": true,
      "description": "Value of the transaction being financed."
    }
  ],
  "borrower_checks": {
    "enabled": true,
    "checks": [
      "payment_defaults",
      "sanctions_match"
    ],
    "required_identifiers": [
      "national_id"
    ]
  },
  "related_company_checks": {
    "enabled": true,
    "checks": [
      "sanctions_match",
      "high_risk_jurisdiction"
    ]
  },
  "requires_bank_data": {
    "required": true,
    "minimum_days": 180,
    "conditions": [
      "revenue_trend"
    ]
  }
}

Events#

Event#

The body of a callback. One shape for every event type; data.object is always the full assessment as it stood when the event fired.

The object is always re-readable at GET /v1/assessments/{id}, which is the recovery path when a callback is missed.

idstringrequired
pattern: ^evt_[A-Za-z0-9]+$
objectstringrequired
const: event
typeEventTyperequired
created_atstringrequired
format: date-time
livemodebooleanrequired
api_versionstring
dataobjectrequired
no unknown fields
metadatamap<string, string>

The opaque key-value pairs supplied on the create request, returned verbatim.

Never interpreted, never used in any evaluation, and never a place to put anything the contract has its own field for. Present on the assessment and on every callback carrying it, which is the cleanest way to correlate a result with your own case record without keeping a map of our identifiers.

Absent where the create request carried none.

EventType#

ValueMeaning
assessment.screening.completed
assessment.bank_data.required
assessment.bank_data.received
assessment.completed
assessment.failed

Errors#

ErrorResponse#

errorErrorrequired

Error#

Errors follow one shape everywhere, including inside a failed assessment's failure field.

typeErrorTyperequired
codestringrequired

Stable, specific identifier. Switch on this, not on message.

messagestringrequired

Human-readable. May change; never parse it.

paramstring | null

The offending field, dotted from the request root.

doc_urlstring | null
request_idstring | null

Quote this when asking about a specific call.

ErrorType#

ValueMeaning
authentication_error

The API key is missing, malformed, revoked or not valid for this environment.

invalid_request_error

The request was understood and is not acceptable: a malformed field, an unknown country, or an operation that is not legal in the assessment's current state.

consent_error

A required consent was not attested. Separate from a validation error because the remedy is different: the caller must obtain something from the borrower, not correct a field.

entitlement_error

The request is well formed but requires an entitlement that is not in place for this source in this market. Separate from an authentication failure, and from a source outage, because it will not resolve by retrying.

idempotency_error

An Idempotency-Key was reused with a different request body.

rate_limit_error

Too many requests.

api_error

Something failed on our side. Safe to retry.

Other#

CheckSubject#

Who a condition was evaluated against.

A policy may test a company's rating and, separately, the payment history of each person representing it, so a clean company with one problematic director is distinguishable from the reverse.

A condition evaluated against three representatives produces three entries in checks, one per person, each with its own result. Related companies are reported the same way. Each entry names the ref the request supplied, so a consumer can join a result back to its own record without matching on a name.

Validated conditionally

This object carries a conditional rule: some fields are required, or constrained to null, depending on the value of another field. A payload that ignores it is rejected rather than accepted and corrected.

kindstringrequired

One of company, representative, related_company

refstring | null

The ref from representatives or related_companies. Null when kind is company, required otherwise, enforced below.

namestring | null

Echoed for display. Never the only place the identity appears.

CreditExposure#

The credit a subject already carries, as the credit bureau reports it: how many facilities are open, what is outstanding, and what is repaid each month.

One entry per subject the bureau was queried for: the company and, where the policy runs personal conditions, each representative.

monthly_instalments is the sum of the scheduled instalments across every open facility. Revolving facilities carry no instalment, and their use is reported in credit_limit_used. A revolving line is never left out of the totals.

Amounts are in currency, as reported. Exposure is reported for the analyst and for the policy; it is not an input to any ratio.

Validated conditionally

This object carries a conditional rule: some fields are required, or constrained to null, depending on the value of another field. A payload that ignores it is rejected rather than accepted and corrected.

subjectCheckSubjectrequired
availabilityAvailabilityrequired
sourcestring | null

In the same vocabulary as evidence.sources[].source.

currencystring | null

ISO 4217.

open_facilitiesinteger | null

Number of open facilities of every type.

min: 0
outstanding_balancenumber | null

Total outstanding across every open facility, revolving included.

min: 0
monthly_instalmentsnumber | null

Total scheduled monthly instalments across every open facility.

min: 0
credit_limit_totalnumber | null

Total limit across open revolving facilities.

min: 0
credit_limit_usednumber | null

Amount drawn against those limits.

min: 0
facilitiesarray<CreditFacility>

The open facilities behind the totals, where the bureau itemises them.

reasonstring | null

Present whenever availability is not available.

Example
{
  "subject": {
    "kind": "company"
  },
  "availability": "available",
  "source": "bureau.credit_report",
  "currency": "EUR",
  "open_facilities": 3,
  "outstanding_balance": 186400,
  "monthly_instalments": 7350,
  "credit_limit_total": 40000,
  "credit_limit_used": 12600,
  "facilities": [
    {
      "type": "instalment",
      "lender_category": "bank",
      "outstanding": 141000,
      "instalment": 5900,
      "limit": null,
      "days_past_due": 0,
      "opened_on": "2023-03-01",
      "maturity_on": "2028-02-29"
    },
    {
      "type": "leasing",
      "lender_category": "non_bank",
      "outstanding": 32800,
      "instalment": 1450,
      "limit": null,
      "days_past_due": 0,
      "opened_on": "2024-09-15",
      "maturity_on": "2027-09-14"
    },
    {
      "type": "revolving",
      "lender_category": "bank",
      "outstanding": 12600,
      "instalment": null,
      "limit": 40000,
      "days_past_due": 0,
      "opened_on": "2022-05-10",
      "maturity_on": null
    }
  ]
}

CreditFacility#

One open credit facility on the bureau report.

typestringrequired

One of instalment, revolving, leasing, factoring, other

lender_categorystring | null

Whether the facility is with a bank or a non-bank lender. Lenders are not named.

One of bank, non_bank, null

outstandingnumber | null

Balance outstanding.

min: 0
instalmentnumber | null

Scheduled monthly instalment. Null on a revolving facility.

min: 0
limitnumber | null

Credit limit, on a revolving facility.

min: 0
days_past_dueinteger | null

Days currently overdue. Zero when the facility is up to date.

min: 0
opened_onstring | null
format: date
maturity_onstring | null
format: date

CustomInputDeclaration#

One input a policy version accepts, and the shape a value for it must take.

Published so an integrator can validate before sending rather than discovering the rule from a 400.

namestringrequired

The key used in custom_inputs, and the part after the dot in the custom.<name> check key.

pattern: ^[a-z][a-z0-9_]{0,39}$
labelstring | null
typestringrequired

One of number, integer, boolean, string, enum

unitstring | null

Free text, for display. Never used to convert a value.

minimumnumber | null

Numeric types only. A value below this is rejected, never clamped.

maximumnumber | null

Numeric types only. A value above this is rejected, never clamped.

allowed_valuesarray | null

The complete set of values accepted, where type is enum.

mandatorybooleanrequired

Whether a condition defined over this input caps the outcome when the value is absent. Follows the same rule as PolicyCheck.mandatory.

descriptionstring | null

What the lender means by this input. Recorded, never interpreted.

Example
{
  "name": "basket_value",
  "label": "Basket value",
  "type": "number",
  "unit": "EUR",
  "minimum": 0,
  "maximum": 5000,
  "mandatory": true,
  "description": "Value of the transaction being financed."
}

CustomInputs#

Values for the inputs this policy version declares for itself.

partner_data covers the lender-held facts that are common to lending generally. This object covers the ones specific to one product, that the contract has no field for.

A lender running several products declares a policy version per product, and each version declares the inputs its rules need. Read them back at GET /v1/policies/{version} before sending.

Three rules:

1. Declared or rejected. A name this policy version did not declare, a value of the wrong type, or a number outside the declared range, returns 400 with type invalid_request_error. Nothing is coerced and nothing is ignored. 2. Absence is never favourable. A declared input that is mandatory and absent makes its condition not_evaluated with requires: [custom_inputs], exactly as an absent registry value would. It never passes by default. 3. Values are evidence, not configuration. These are facts about this borrower on this case. The boundaries they are compared against live in the policy version, where every other boundary lives. A caller cannot send a threshold.

Each declared input is reported back as a custom.<name> entry in checks, and the raw values are echoed under result.inputs.custom.

Example
{
  "basket_value": 340.0,
  "repeat_customer": true,
  "settlement_delay_days": 14
}

DecisionRule#

One rule in the ordered list that maps what was observed to an outcome.

Rules are evaluated in order and the first one whose conditions all hold decides the outcome. A policy that reaches the end without a match yields review, because falling off the end of a rule list is not evidence of creditworthiness.

The sufficiency gate is applied afterwards and can only lower the result. A rule that yields approve on an insufficient file produces review or insufficient_evidence, and PolicyOutcome.capped_by records that it was the evidence rather than these rules that decided it.

idstringrequired

Stable identifier for this rule within the policy version.

outcomePolicyOutcomeValuerequired
descriptionstring | null

The lender's own wording for what this rule is for.

conditionsarray<object>required

All conditions must hold for the rule to fire. An empty array is a rule that always fires, which is how a policy writes its fallback.

Example
{
  "id": "R-01",
  "outcome": "reject",
  "description": "Any hard stop rejects, whatever the ratios say.",
  "conditions": [
    {
      "subject": "check.sanctions_match",
      "operator": "eq",
      "value": "fail"
    }
  ]
}

IndicatorKey#

The vocabulary of behavioural and fraud signals. New keys may be added within v1, so a consumer should tolerate a key it does not recognise.

ValueMeaning
single_day_turnover_spike

Largest single-day inflow against the average day in its month.

balance_below_zero_days

Days in the window with a negative closing balance.

payments_to_other_lenders

Repayments to other lenders as a share of turnover.

collections_activity

Payments to debt collection agencies as a share of turnover.

round_value_transfers

Round-value incoming payments as a share of turnover or of payment count.

cash_credits_share

Cash deposits as a share of inflow.

counterparty_concentration

The largest single counterparty's share of inflow.

cross_border_counterparties

Transactions with counterparties outside the market, by value.

chargeback_rate

Chargebacks as a share of acquiring volume.

refund_rate

Refunds as a share of acquiring volume.

IndustryCode#

One classification of what the applicant trades in, qualified by the scheme the code belongs to.

The scheme is required because the same digits mean different things in different schemes, and because an eligibility list written against a card scheme's merchant categories cannot be applied to a national activity classification. Note also that within a single scheme a code can sit under more than one trade, so a rule turning solely on a code will misclassify some borrowers in both directions.

schemestringrequired

Which classification the code belongs to. Published per market in Country.industry_schemes.

codestringrequired
labelstring | null

The scheme's own description of the code, where the source supplies one.

RatingScale#

An ordered scale that a rating or score in this market is expressed on.

Grades are compared by position, never as strings. On an ordinal scale the first entry in grades is the most favourable and each subsequent entry is less favourable, so a comparison is an index comparison. Comparing grades lexicographically is a defect: it ranks AAA above AA, B above AAA, and it passes a grade that should fail. Producers and consumers both resolve grades through this object.

Validated conditionally

One or more ceiling rules apply: a more favourable value is rejected when the evidence does not support it. The constraint is one-directional, so a less favourable value always remains valid.

idstringrequired

Stable identifier for the scale, referenced by PolicyCheck.scale. Scoped to the source and the market, because two providers in one country may grade differently.

labelstringrequired

Display name for the scale.

kindstringrequired

One of ordinal, numeric

directionstringrequired

Which end of the scale is the favourable one. Required on every scale, including ordinal ones, so that a consumer never has to infer it from the grade names. A default-probability scale and a credit-quality scale run in opposite directions and can otherwise look identical.

One of higher_is_better, lower_is_better

gradesarray | null

For an ordinal scale, every grade in order from most to least favourable. Position in this array is the only ranking that the contract recognises. Null on a numeric scale.

minnumber | null

Lower bound of a numeric scale. Null on an ordinal scale.

maxnumber | null

Upper bound of a numeric scale. Null on an ordinal scale.

notesstring | null
Example
{
  "id": "bureau_alpha_7",
  "label": "Bureau letter grade",
  "kind": "ordinal",
  "direction": "higher_is_better",
  "grades": [
    "A1",
    "A2",
    "B1",
    "B2",
    "C1",
    "C2",
    "D"
  ],
  "min": null,
  "max": null,
  "notes": "Seven ordered grades, most favourable first. A policy floor names one of them, and every grade below that position fails. Ranking is decided by index, never by comparing the grades as text."
}

RelatedCompany#

One company connected to the applicant.

Screened against the conditions the policy lists in related_company_checks, typically sanctions and high-risk jurisdiction. Every check evaluated against it names it in PolicyCheck.subject.ref.

refstringrequired

Your own identifier for this company, unique within the request. Echoed on every check evaluated against it and never interpreted.

pattern: ^[A-Za-z0-9_.:-]{1,64}$
countrystringrequired

ISO 3166-1 alpha-2. May differ from the applicant's.

pattern: ^[A-Z]{2}$
registry_codestringrequired

The company's national registration number in country.

legal_namestring | null
relationstring | null

How this company is connected to the applicant, in your own vocabulary. Carried through to the audit trail and never parsed.