Authentication and connecting
One key, one header, no token exchange. Everything harder than that is on our side of the boundary.
What you receive at onboarding#
| Item | Used for |
|---|---|
| API key | Every request, in the X-Api-Key header |
| Host | The base URL. Environment-specific, which is why it is not published here |
| Signing secret | Verifying the callbacks we send you. Different from the API key |
| Policy version identifiers | The strings you send as policy_version |
| Source addresses | Where our callbacks originate, if you allowlist inbound traffic |
You supply one thing in return: the HTTPS endpoint that will receive callbacks. It can be changed later without reissuing anything.
Configuring your policy#
You supply your rules: thresholds, band boundaries, evidence floors, and which conditions
are mandatory. They are configured as a named policy version, one per lending product. The
identifiers come back to you in the table above, and those are the strings you send as
policy_version.
A change is requested through your account contact and comes back as a new version identifier. Versions are never edited in place, which is what lets an assessment from months ago still resolve to the exact rules that produced it.
Registering or changing the callback URL#
Also through your account contact. Send us the HTTPS endpoint at onboarding and tell us when you want it changed. A change takes effect for events generated after it lands; events already queued for delivery finish against the old endpoint, so keep the old one answering until you stop seeing traffic on it.
One endpoint receives every event type. Branch on type.
Using your key#
Send it as X-Api-Key on every request, including the ones that touch no
upstream source. There is no bearer token, no OAuth exchange and no session. A key that
works keeps working until it is revoked.
The key identifies your tenant. Everything the API returns is scoped to it: your assessments, your policy versions, your coverage. There is no cross-tenant read of any kind, and the error codes are chosen to keep it that way.
Making your first call#
Start with GET /v1/countries. It consults no upstream source, so it confirms
three things at once, without consuming anything chargeable: that your key is valid, that
your host is right, and that your network path works.
A 200 with a list of markets means you are connected. A 401 means
the key or the header name is wrong. A connection error means the host is wrong.
Test environment#
There is none in v1. Every key is live, and every assessment consumes real sources, some of which are chargeable.
mode: screening
It runs the first stage and stops, so you can exercise the whole request, callback and result path, including signature verification and your error handling, without running the rest of the policy.
livemode is on every response and is always true, so adding a
test environment later changes nothing about the shape of anything you have already
built.
Storing the key#
- Server-side only. It grants access to your whole book of assessments.
- Never in browser code, a mobile app, or anything shipped to a device.
- Never in source control, including private repositories.
- In a secret manager or an injected environment variable.
- Not in log lines. Redact the header when logging requests.
Tell us immediately if a key appears in a log aggregator, a screenshot, a ticket or a repository, and we will replace it.
Verifying callbacks#
The one piece of cryptography in this integration, and the one place a shortcut costs you something real. Full detail and the common failure modes are on the webhooks page; the samples are in the right-hand column here.
Three rules: sign the raw bytes, compare in constant time, reject a stale timestamp.
Tenant scoping#
A request for another tenant's assessment returns 404, not
403.
A 403 would confirm the resource exists, which discloses something about
another tenant. 404 tells you the only thing you are entitled to know: it is
not yours.
Rate limits#
Per-tenant limits apply to request volume and to how many assessments you may have running at once. Your values are issued at onboarding.
| Limit | Value | Scope |
|---|---|---|
| Requests | Set at onboarding | Per tenant, all endpoints |
| Assessments created | Set at onboarding | Per tenant |
| Assessments in flight | Set at onboarding | Per tenant |
| Callback delivery | 7 attempts over 24 hours | Per event |
An assessment we are actively working on: screening or
processing. An assessment sitting in awaiting_bank_data is
waiting on you, holds none of our capacity, and does not count.
Terminal states never count.
A borrower who starts an application and never finishes the bank-data step therefore
cannot consume your concurrency. An abandoned case holds no slot, and
expires_at is the point after which it will never produce a result.
429 from the first day
Exceeding a limit returns 429 with Retry-After. Treat it as an
expected response with a documented remedy, not as an error to escalate. Retry after the
interval, with jitter if you are running several workers.
Consent and data protection#
You attest and Credit Atlas records. The consents object states what the
borrower agreed to and when. It is stored with the assessment, so any later question about
the basis for processing has an answer attached to the case rather than to a policy
document.
| Consent | Needed for |
|---|---|
data_processing | Always required |
bureau_enquiry | Any bureau lookup, where one is in scope |
account_information | Submitting bank data |
A missing consent returns 402 with consent_error, separately from
a validation error, because the remedy is different: you need something from the borrower,
not a corrected field.
The account-information relationship stays with you. You initiate the borrower's journey under your own agreement and submit the result. Credit Atlas does not stand between you and that relationship, which keeps the regulated party where it already sits.
On the decision itself: policy_outcome reports the result of applying the
configured policy to the evidence. It is not a creditworthiness decision made by Credit
Atlas, and your analyst retains decision authority. analyst_questions arrives
as structured data so each question can be routed, tracked and closed against the driver
that raised it.
Versioning policy#
The version is in the path: /v1. It changes only for a breaking change. Inside
v1, the following holds.
Current contract: version 1.0, released 6 July 2026.
| May change | Will not change |
|---|---|
| Add a new optional request field | Add a required request field |
| Add a new response field | Remove or rename a response field |
| Add a new enum value | Remove an enum value or change its meaning |
| Add a new endpoint or event type | Change an endpoint's semantics |
| Add a new success status code to an existing operation | Change which status code an existing outcome returns |
| Relax a validation rule | Tighten one |
| Raise a rate limit | Lower one without notice |
Tolerate unknown enum values. New markets, new reason codes and new check keys will appear. A consumer that throws on an unrecognised enum value will break on an additive change. One that routes unknown values to a review queue will not.
Tolerate unknown response fields. Fields get added, so do not validate responses with a strict closed schema. Unknown fields are rejected on the way in, and that asymmetry is deliberate.