Error catalog
Every error response is RFC 9457 problem details (Content-Type: application/problem+json)
with a stable code. Its type is https://api.datasourcecorp.app/docs/errors.md#<code>, a link to the entry below.
Branch on code: titles and details are for people and may change.
{
"type": "https://api.datasourcecorp.app/docs/errors.md#client_not_found",
"title": "Client not found",
"status": 404,
"detail": "No client 'acct-7731' exists under your account.",
"code": "client_not_found"
}
Validation errors (validation_failed, invalid_cursor) also carry errors: an object from field name to a list of
messages, for example { "applicant.ssn": ["applicant.ssn must be a valid 9-digit Social Security number."] }. Messages
never repeat the values you sent.
Two documented responses are not problem details:
409onPOST /clients/{clientRef}/checks/directwithcodeduplicate_check: the body is{ code, message, currentStatus, instructions, order }, with the existing check inorder.502onPOST /clients/{clientRef}/checks/directwhen the body is a check (statusPENDINGorERROR, nocode). See upstream_unavailable.
Read the HTTP status first, then code when the body has one.
All codes
code |
HTTP | Retry the same request? | What to do |
|---|---|---|---|
validation_failed |
400 | No | Fix each field named in errors, then send again. |
invalid_cursor |
400 | No | Start again from the first page (omit cursor). |
invalid_json |
400 | No | Send a valid JSON body with Content-Type: application/json, and values of the right type. |
invalid_api_key |
401 | No | Use a valid key for this environment (pk_test_ on the sandbox, pk_live_ on production). |
not_available_for_account_type |
403 | No | The operation isn't part of the wholesale API. Use the operations in this reference. |
client_not_found |
404 | No | Use account, or a sub-account's clientId or externalClientId. |
check_not_found |
404 | No | Check the id or externalIdentifier, and the account it was ordered on. |
not_found |
404 | No | The route doesn't exist. Check the method and path. |
method_not_allowed |
405 | No | Use the method the reference lists for this path. |
duplicate_check |
409 | No | Use the existing check in order. Only send forceReorder: true if you want a new, billed check. |
external_client_id_in_use |
409 | No | Use the existing sub-account: GET /clients?externalClientId=.... |
external_identifier_in_use |
409 | No | Use a different externalIdentifier (it is unique across your account and sub-accounts). |
payload_too_large |
413 | No | Send a smaller body. |
unsupported_media_type |
415 | No | Send Content-Type: application/json. |
level_not_available |
422 | No | Pick a level from GET /clients/{clientRef}/products, or contact support. |
rate_limited |
429 | Yes, after Retry-After |
Wait the number of seconds in Retry-After, then send again. |
internal_error |
500 | Yes, with the same externalIdentifier |
Retry with backoff; contact support if it persists. |
upstream_unavailable |
502 | Usually; see the entry | Retry with backoff. For orders, read the entry first. |
request_failed |
other | Depends | Any other framework error. Read status and detail. |
validation_failed
400. The request is invalid: a required field is missing or malformed (an SSN that can't be issued, a date of birth
that isn't YYYY-MM-DD, an unknown state), a value is too long, or the certification is incomplete. errors lists each
problem by field path (applicant.address.postalCode, certification.authorizationObtained). Nothing was created or
billed. Retry: only after fixing the request.
invalid_cursor
400. On GET /clients/{clientRef}/checks, cursor is not a nextCursor we issued. Retry: no; start again from
the first page.
invalid_json
400. The body isn't valid JSON, is missing, or a value has the wrong type (for example "level": "two"), or a query
value can't be read. Nothing was created. Retry: after fixing the request.
invalid_api_key
401. The API key is missing, invalid or revoked, or it belongs to the other environment. Retry: only with a valid
key. Repeated invalid keys from one IP address lead to rate_limited.
not_available_for_account_type
403. The operation exists on this server but isn't part of the wholesale API (for example ordering by invitation, or the hosted connect page). Nothing was done. Retry: no.
client_not_found
404. {clientRef} isn't account or one of your sub-accounts. Other customers' accounts always look like this.
Retry: no.
check_not_found
404. No check with that id or externalIdentifier exists on that account. Retry: no.
not_found
404. No such route. Check the method, the path, and that you're calling the right environment (some routes exist only in the sandbox). Retry: no.
method_not_allowed
405. The path exists but not with this HTTP method. Retry: no.
duplicate_check
409. On POST /clients/{clientRef}/checks/direct: the applicant (same externalIdentifier, or same SSN on the same
account) already has a check that is in progress (PENDING, CREATED) or completed and not yet expired (CLEAR,
REVIEW). Nothing was ordered or billed. The body is not problem details: it is
{ code, message, currentStatus, instructions, order } with the existing check in order. If you were retrying after a
timeout, your first attempt worked: use order. Retry: no. forceReorder: true orders anyway and is billed as a new
check.
external_client_id_in_use
409. On POST /clients: another of your sub-accounts already has this externalClientId. Nothing was created.
Retry: no; use the existing sub-account.
external_identifier_in_use
409. The externalIdentifier is taken. On an order: it belongs to a check on another of your accounts; nothing was
ordered. On PATCH /clients/{clientRef}/checks/{checkRef}: the check already has one (it can be set once), or another
check uses the value; nothing changed. Retry: no; use a different value.
payload_too_large
413. The request body is larger than the server accepts. Retry: no.
unsupported_media_type
415. The body isn't sent as Content-Type: application/json. Retry: no; set the header.
level_not_available
422. The account has no product for that level. Nothing was ordered. Retry: no; pick a level from
GET /clients/{clientRef}/products, or contact support.
rate_limited
429. Too many requests with an invalid API key came from your IP address (20 a minute; valid keys are never
throttled this way). Retry-After gives the seconds to wait. Retry: yes, after waiting.
internal_error
500. Something failed on our side. The body has a traceId to quote to support and never contains error details.
For an order, the check may or may not exist: retry only with the same externalIdentifier, and expect either a normal
result or 409 duplicate_check. Retry: yes, with backoff.
upstream_unavailable
502. The screening provider didn't accept the request. As problem details, nothing was created or recorded and a retry is safe.
For an order the body can instead be the check itself (status PENDING, no code): the order was sent but its
answer was lost, so it may or may not exist upstream. Don't retry with forceReorder. Retry only with the same
externalIdentifier, or just wait: a PENDING check is looked up automatically and resolved within about an hour, and
you get check.updated either way.
If the body is a check with status ERROR, the screening provider refused that order outright (errorCode and
errorMessage say why). Nothing was created or billed; order again once the cause is fixed.
request_failed
Any other status the framework produces (rare). Read status and detail. Retry: depends on the status.