Start here
Credit Atlas is a credit risk engine for business lending. A company identifier goes in. A scored credit assessment comes out, with every input that produced it. One integration covers Estonia, Latvia and Poland.
What Credit Atlas does#
You send the company you are assessing and the policy version to apply. Credit Atlas gathers the evidence that is publicly and lawfully available about that company, normalises it, computes the ratios and checks the policy names, and returns a structured result: the outcome, and every observation that led to it.
The work happens in the background: a create is accepted immediately and answered later on a signed callback, so nothing in your code waits on a registry having a slow morning. What comes back is a scored assessment rather than a single opaque number: a policy outcome, twelve financial ratios each in a band, every policy check with its own result, and reason codes carrying the value observed and the threshold it was compared against.
How an assessment is built#
- Company and borrower data. The identifiers that market uses, the representatives and related companies to screen, and the loan being requested. In Estonia the company identifier is an eight-digit registry code. In Latvia it is a registration number of six, eight, nine or eleven digits. Do not assume eleven. In Poland it is a ten-digit tax identification number.
- Public and bureau evidence. From the identifier, Credit Atlas reaches the company registry, the statutory filings, the tax authority, the legal registers, the credit bureau, including the credit each subject already carries, and sanctions screening.
- Bank account data. The applicant's account history, obtained by you under your own account-information agreement and submitted to Credit Atlas. You initiate the borrower's journey, so Credit Atlas never stands between you and that relationship.
The policy version#
Every request names a policy_version. It is the rule set applied to the
evidence: which checks run, the thresholds they run against, and the extra fields your
product sends. One version per lending product, so this one string is the only selector
there is.
Versions are configured by Credit Atlas from the rules you supply and issued to you at
onboarding. They are never edited in place: a change returns a new identifier, so an
outcome can be replayed later against the exact rules that produced it. Read one back at
GET /v1/policies/{version}.
Custom inputs
Most products score on something only the lender holds, such as a basket value or a
repeat-customer flag. The policy version declares those fields up front, with their type,
unit and allowed range. You send them as custom_inputs and they come back as
checks alongside every other condition, with the values you sent echoed.
An undeclared name, or a value outside the declared range, returns 400. It is
never quietly ignored, because a silently dropped input changes an outcome and nobody
notices. A declared input that is mandatory and absent is reported as missing and never
read as favourable.
One integration, three markets#
Markets differ in filing scheme, identifier format, rating scale and in what is obtainable
at all. Those differences are published as data at GET /v1/countries/{code}
rather than written into the request and response shapes, so the shapes never change.
Statement line items are normalised to a fixed vocabulary of canonical keys such as
current_assets and revenue, and every ratio is defined on those
keys. Adding a country is a mapping table on our side, not a new integration on yours.
Read GET /v1/countries/{code} at runtime and branch on what it says. A client
that hard-codes one market's identifier pattern, ratio list or rating direction will break
when it meets the next market. Rating scales in particular are not comparable between
markets, and a floor set in one says nothing about any other.
The model page has the detail.
Where the lender decides#
Credit Atlas is an evidence and infrastructure provider. policy_outcome states
the result of applying the configured policy to the evidence gathered. It is not a
creditworthiness decision made by Credit Atlas, and the lender's analyst retains decision
authority.
Every outcome names the policy version that produced it, every reason code carries the
value observed and the boundary it was compared against, and
analyst_questions arrives as structured data. An outcome you cannot replay
months later is not one you can defend.
All endpoints#
Eight operations, and that is the whole surface. Each links to its full reference.
202 immediately; the outcome arrives on a callback.
GET
/v1/assessments
List your assessments, newest first. This is how you find work that finished while you were down.
GET
/v1/assessments/{id}
Current status of one assessment, and its result once there is one.
GET
/v1/assessments/{id}/result
Just the evaluated output, without the envelope around it.
POST
/v1/assessments/{id}/bank-data
Attach the account history. Accepted once, and only while the assessment is waiting for it.
GET
/v1/countries
Every market we serve and what each one can answer.
GET
/v1/countries/{code}
One market: its identifier schema, its rating scales and its industry schemes.
GET
/v1/policies/{version}
The policy version as it was applied: the bands, the thresholds, the rules and the first stage.
Five callback events carry the work back to you, two of them terminal. The catalogue, the payloads and the signature scheme are on the webhooks page.
Connect#
You are issued a per-tenant key at onboarding, along with the host to send it to and the
signing secret for verifying callbacks. Send the key as X-Api-Key on every
request. The host is environment-specific and given to you at onboarding rather than
published here.
Confirm the key and the host together with GET /v1/countries. It touches no
upstream source, so it costs nothing.
Create an assessment#
Pick a mode. screening runs the first stage and stops there.
full continues into the rest of the policy and, where it needs it, into bank
data. Both return 202. What the first stage contains is declared on the policy
version and readable at GET /v1/policies/{version}.
Send an Idempotency-Key on every create. An assessment can trigger a
chargeable lookup, so a retry without a key bills twice.
Evaluation stops at the first gate that fails, so a case rejected on eligibility never
reaches a paid source. A follow-up linked with previous_assessment_id is a
full run rather than a resume, so one full assessment is cheaper than a
screening one followed by a full one.
consents.account_information defaults to false. Without it
attested on the assessment, a later bank-data submission returns 402, and no
endpoint adds a consent after the fact. The only remedy is a new assessment.
Collect it from every applicant you send in full mode, not only the ones you
expect to reach that stage. It costs nothing when unused.
Receive the callback#
Register one HTTPS endpoint. Every event is delivered to it, signed. Verify the signature
over the raw body before parsing, compare in constant time, and reject a stale timestamp.
Deduplicate on event.id, because an acknowledgement that times out is retried
even though the first delivery arrived. Verification samples are on the
authentication page.
Attach bank data#
When assessment.bank_data.required arrives, start the borrower's
account-information journey under your own agreement, then post the result back.
This call is legal only while the assessment is in awaiting_bank_data. In
every other state, including after a successful submission, it returns 409.
To re-evaluate with different data, create a new assessment with
previous_assessment_id set.
Read the result#
result is present if and only if status is complete,
and the schema enforces it. Six things to read, in the order most integrations need them:
A full worked result for each market ships with the contract, at
api/examples/ee/assessment.json and the same path for
lv and pl.
The full contract is api/openapi.yaml.
| Field | What it tells you |
|---|---|
policy_outcome.value |
approve, review, reject or
insufficient_evidence. Read capped_by alongside it: a
review chosen by the rules means something different from one forced
by thin evidence
|
supportable_amount |
Capacity, with its own availability. A capacity of zero and a capacity
that could not be computed are opposite findings
|
reason_codes |
Why, as data. Each carries the observed value, the threshold and the policy version |
checks |
Every non-ratio condition, such as a rating floor, a default count, a sanctions
result or an eligibility test, each with its own availability. A condition that was
never evaluated reports not_evaluated, never pass
|
credit_exposure |
The credit the company and each representative already carry, from the bureau: open facilities, outstanding balance, monthly instalments and credit limits |
coverage |
Which sources were consulted, and why any of them were not |
insufficient_evidence means no conclusion about the applicant was reached,
because too little could be computed. Mapping it to a rejection turns an applicant's size
into a credit negative.
Integration checklist#
- Send
Idempotency-Keyon everyPOST. - Handle
202as the only success response to a create. - Verify the callback signature over the raw body, and reject stale timestamps.
- Deduplicate callbacks on
event.id. - Treat
429as expected and retry with backoff from day one. - Distinguish
failedfrom an outcome ofreject. - Never map
insufficient_evidenceto a rejection. - Never read a
nullband as a favourable one. It means not computable. - Read
GET /v1/countries/{code}before promising anything about a market. - Stop waiting at
expires_at; do not wait forstatusto becomeexpired.