REST API

Response format and errors

Branch on the status field of the body, never on the HTTP code or on message text.

Status is the signal

All calls are POST and answer JSON, except file downloads. A failure normally arrives as HTTP 200 with a body whose status is error. Code that treats 200 as success is wrong on every error path. Branch on the status field of the body.

On most operations status is one of four values:

ValueMeaning
okThe operation succeeded.
errorThe request failed.
failedThe request was well formed, but the operation could not be performed on the input given.
infoAn informational answer.

KYC session operations carry the vocabulary of the session instead: idle, processing, success, failed, exception, expired and suspicious. There status is the state of the verification, not the success flag of the call. See session statuses.

The message field is human-readable English prose that is reworded without notice. It is illustrative only: never match on it.

Validation errors

A body that is valid JSON but does not match the request schema is refused with status of error. A details list names every offending field with path, expected and actual.

Refusals that come before the operation

Two checks run before any operation and answer in a shape of their own:

SituationAnswer
A token bound to one IP address is used from anotherHTTP 401 with an errors list whose entry has extensions.code of IP_MISMATCH, and the two addresses. There is no status field.
A request comes from an address outside your IP allowlistHTTP 403 with {"message":"Access Denied"}. There is no status field. An empty allowlist accepts any address.

A body that is not valid JSON under the JSON content type is rejected before any handler runs, with HTTP 400 and an HTML error page. An unknown path answers HTTP 405 in the same way. Those are malformed requests, not failures of one operation.

Authentication failures

A missing, expired or unknown token answers HTTP 401 with status of error. The body is JSON in both cases, but a token rejected in the header is typed text/html, while one rejected in the body is typed application/json. Parse the body as JSON whatever the content type says. See authentication.

Other shapes to know

  • Unexpected failure. HTTP 500 with status of error and the fixed text internal error. Nothing in the body helps you branch beyond the code.
  • Busy session. HTTP 409: another request to the same session was still being processed. Nothing of the refused request was applied. Repeat it once the other request has been answered.
  • Bare success. List operations such as list persons and list sources send the array or object itself, without a status wrapper.
  • User authorization. A refusal of user authorization is HTTP 403 with a body that still says status of ok. On that one operation the HTTP code is the only signal.
  • Redacted fields. When your token lacks a viewing permission, the matching key arrives as the string Access denied rather than being left out.
  • Downloads. Download logs archive answers a failure with a body that carries an error key and no status.
  • Erasure. Erase session personal data is read through its result field: erased is the only value that means the destruction is finished.

Where to go next

Questions, answered plainly

Why does my call return a success code with an error inside?

A failure normally arrives with a successful HTTP code and a body whose status is error. Read the status field of the body.

Can I match on the message text?

No. The message is English prose that is reworded without notice. Branch on status and on the documented fields.

Questions while integrating?

Write to us with the details and we will help.

Talk to us