Error catalog (Problems)
Every error comes as application/problem+json (RFC 9457), with type, title, status,
retryable and, when present, correlation_id.
Download the exact Problem schema and v1 OpenAPI contract for validation.
Problem type identifiers
Section titled “Problem type identifiers”The type is a full URI under https://fingertrackid.dev/problems/, for example
https://fingertrackid.dev/problems/rate-limited.
- It is a stable identifier. Do not fetch it at runtime and do not treat a failed lookup as
a problem. Compare the full
typestring. - This page is the documentation for every type. Each one has its own section below, at
https://docs.fingertrackid.com/api/errors/#<suffix>(for example#rate-limited), and opening atypeURI in a browser redirects to that section. - Code against
typeandstatus. Thetitleis human-readable text; it is only fixed forauthentication-failed(Autenticação falhou, in Portuguese as the contract defines) andassessment-result-expired(Assessment result expired). Do not branch ontitle. - The contract allows
errors[](withpointerandcode) only invalidation-failed, as an optional field. Do not rely on it to find the wrong field.
Summary
Section titled “Summary”type suffix |
HTTP | retryable |
Routes |
|---|---|---|---|
validation-failed |
400 | false |
Assessment, feedback |
event-context-invalid |
400 | false |
Assessment |
occurred-at-out-of-window |
400 | false |
Assessment |
authentication-failed |
401 | false |
Assessment, feedback |
timestamp-out-of-window |
401 | true |
Assessment, feedback |
request-replayed |
401 | true |
Assessment, feedback |
forbidden |
403 | false |
Assessment, feedback |
not-found |
404 | false |
Feedback |
idempotency-conflict |
409 | false |
Assessment, feedback |
binding-conflict |
409 | false |
Assessment, feedback |
assessment-result-expired |
410 | false |
Assessment |
payload-too-large |
413 | false |
Assessment, feedback |
unsupported-media-type |
415 | false |
Assessment, feedback |
rate-limited |
429 | true |
Assessment, feedback |
internal |
500 | false |
Assessment, feedback |
assessment-unavailable |
503 | true |
Assessment, feedback |
The feedback routes have their own closed Problem catalog in the feedback OpenAPI, with English titles. The Web SDK’s collection endpoint uses a few more types, listed in seen in the browser, and the types the API does not send are listed after them.
Assessment and feedback types
Section titled “Assessment and feedback types”validation-failed
Section titled “validation-failed”400, not retryable. The request does not match the schema, or the route is a variation of
/v1/assessments (query string, trailing slash, method other than POST), or the request
carries Expect/Trailer or a duplicated framing header. Fix the request against the schema.
For a v1.1 request this includes a tag outside the grammar (uppercase, hyphen, space, more than
64 characters, 11 or more digits in total) and a v1-only field (journey, action,
journey_context). There is no separate Problem type for the tag.
{ "type": "https://fingertrackid.dev/problems/validation-failed", "title": "Request inválido", "status": 400, "correlation_id": "corr-problem-validation-0001", "retryable": false, "errors": [ { "pointer": "/journey", "code": "INVALID_ENUM" } ]}event-context-invalid
Section titled “event-context-invalid”400, not retryable. The event_context_token is present but invalid, expired, already used or
from another scope. Nothing is stored. Under the managed production profile a token expires no
later than your application’s evidence window (60 or 300 seconds) after its collection reached
FingerTrackID (the evidence window). Do not retry: the
same body gets the same answer, and a different body under the same operation IDs is an
idempotency-conflict. To still assess the event, send it once as a new operation (new
external_event_id and idempotency_key) with event_context_token: null. When the browser
has no token, send null from the start
(integration guidance).
{ "type": "https://fingertrackid.dev/problems/event-context-invalid", "title": "Contexto do evento inválido", "status": 400, "correlation_id": "corr-problem-context-invalid-0001", "retryable": false}occurred-at-out-of-window
Section titled “occurred-at-out-of-window”400, not retryable. The occurred_at of a new operation is outside ±300 s of the server
clock. Check the clock and where the timestamp comes from; this route is not for backfill.
{ "type": "https://fingertrackid.dev/problems/occurred-at-out-of-window", "title": "Evento fora da janela online", "status": 400, "correlation_id": "corr-problem-occurred-at-0001", "retryable": false}authentication-failed
Section titled “authentication-failed”401, not retryable. The uniform authentication failure
(see authentication): wrong bytes, headers, key_id, secret decoding,
or a revoked, suspended or blocked credential. Treat it as a configuration error and alert.
{ "type": "https://fingertrackid.dev/problems/authentication-failed", "title": "Autenticação falhou", "status": 401, "correlation_id": "corr-problem-authentication-0001", "retryable": false}timestamp-out-of-window
Section titled “timestamp-out-of-window”401, retryable. Your clock is outside ±300 s of the server clock. Synchronize and send a new
attempt.
{ "type": "https://fingertrackid.dev/problems/timestamp-out-of-window", "title": "Timestamp da assinatura fora da janela", "status": 401, "correlation_id": "corr-problem-timestamp-0001", "retryable": true}request-replayed
Section titled “request-replayed”401, retryable. A request_id was reused. Send a new attempt, and fix the ID generator.
{ "type": "https://fingertrackid.dev/problems/request-replayed", "title": "Identificador da tentativa já consumido", "status": 401, "correlation_id": "corr-problem-replay-0001", "retryable": true}forbidden
Section titled “forbidden”403, not retryable. The credential is valid but lacks the route’s capability. Create a server
credential with that permission in the console.
{ "type": "https://fingertrackid.dev/problems/forbidden", "title": "Capability de assessment ausente", "status": 403, "correlation_id": "corr-problem-forbidden-0001", "retryable": false}not-found
Section titled “not-found”404, not retryable, feedback routes only. The target assessment does not exist or is outside
the authenticated scope; both cases share this response. Check the assessment_id in the path.
idempotency-conflict
Section titled “idempotency-conflict”409, not retryable. The idempotency key or external ID was reused with different content.
Reconcile; do not invent new IDs automatically.
The tag is content: a retry with the same IDs and another tag is a conflict. So is an ID of a
v1 operation sent again in a v1.1 body, or the reverse: v1 and v1.1 operations never share IDs.
{ "type": "https://fingertrackid.dev/problems/idempotency-conflict", "title": "Chave de idempotência já usada com outro conteúdo", "status": 409, "correlation_id": "corr-problem-idempotency-0001", "retryable": false}binding-conflict
Section titled “binding-conflict”409, not retryable. Person, account or session references are incompatible with bindings
already stored. On the assessment route the usual cause is an account_ref that is already
bound to another subject_ref: an account never changes person. No event or assessment is
stored, and the same body gets the same answer, so do not retry it. Fix the mapping in your
backend (keep each reference’s key and prefix unchanged over time, see
person and account references), and continue
your normal flow: for a login, the login goes on.
{ "type": "https://fingertrackid.dev/problems/binding-conflict", "title": "Vínculo de identidade ou sessão incompatível", "status": 409, "correlation_id": "corr-problem-binding-conflict-0001", "retryable": false}assessment-result-expired
Section titled “assessment-result-expired”410, not retryable, assessment route only. The authenticated logical operation exists, but its
result is outside the approved history window. Stop retrying; do not create new IDs to
regenerate the old operation.
{ "type": "https://fingertrackid.dev/problems/assessment-result-expired", "title": "Assessment result expired", "status": 410, "retryable": false}payload-too-large
Section titled “payload-too-large”413, not retryable. The body is above 16384 bytes. Reduce it and sign again.
{ "type": "https://fingertrackid.dev/problems/payload-too-large", "title": "Payload excede o limite", "status": 413, "correlation_id": "corr-problem-payload-0001", "retryable": false}unsupported-media-type
Section titled “unsupported-media-type”415, not retryable. Content-Type is not exactly application/json, or Content-Encoding is
present.
{ "type": "https://fingertrackid.dev/problems/unsupported-media-type", "title": "Representação do request não suportada", "status": 415, "correlation_id": "corr-problem-media-type-0001", "retryable": false}rate-limited
Section titled “rate-limited”429, retryable. Above your server client’s rate. Wait for Retry-After, then send a new
attempt with the same body (limits).
{ "type": "https://fingertrackid.dev/problems/rate-limited", "title": "Limite de assessments atingido", "status": 429, "correlation_id": "corr-problem-rate-limit-0001", "retryable": true}internal
Section titled “internal”500, not retryable. A known internal failure before anything was stored. Do not retry
automatically; open a support request with the correlation_id.
{ "type": "https://fingertrackid.dev/problems/internal", "title": "Falha interna não retentável", "status": 500, "correlation_id": "corr-problem-internal-0001", "retryable": false}assessment-unavailable
Section titled “assessment-unavailable”503, retryable. Unavailable or unknown state. Wait for Retry-After (today always 1 second;
wait at least 1 second if the header is ever missing), then send a new attempt with the same body:
a new request_id, current timestamp and new signature, because the request_id of the
answered attempt may already be consumed. A retained assessment returns 200, an expired result
returns definitive 410. Retry a bounded number of times inside your business deadline, never in
a loop.
{ "type": "https://fingertrackid.dev/problems/assessment-unavailable", "title": "Assessment temporariamente indisponível", "status": 503, "detail": "Repita a mesma operação lógica com novo request_id; o commit pode ter ocorrido.", "correlation_id": "corr-assessment-timeout-0001", "retryable": true}Seen in the browser (Web SDK)
Section titled “Seen in the browser (Web SDK)”The Web SDK talks to your collection domain and handles these responses itself, returning a
status such as UNAVAILABLE to your code. You never parse them, but they can appear in the
browser’s network panel.
type suffix |
HTTP | Meaning |
|---|---|---|
origin-not-allowed |
403 | The page origin is not one of the application’s allowed origins under this collection domain. The response carries no CORS approval, so the browser hides it and the SDK reports TRANSPORT_ERROR |
sdk-session-conflict |
409 | A conflict with the SDK session’s current state; the SDK handles it |
event-context-conflict |
409 | A conflicting event context request for the same SDK event; the SDK handles it |
| 503 | Collection is temporarily unavailable; continue with a null context |
The collection endpoint also uses validation-failed, authentication-failed, not-found,
idempotency-conflict, payload-too-large, unsupported-media-type, rate-limited and
internal with the same meaning as above; there, internal is retryable by the SDK.
Types the API does not send
Section titled “Types the API does not send”FingerTrackID’s catalog reserves a few more types. A type URI with one of these suffixes still
lands here, but the assessment, feedback and collection routes never return them: code that
handles the types above handles every response.
type suffix |
What you receive instead |
|---|---|
signature-invalid, unknown-client, client-suspended |
authentication-failed. Authentication failures are uniform, so a refusal never tells a caller whether the signature, the key or the credential’s state was wrong |
nonce-replayed |
request-replayed |
external-event-conflict |
idempotency-conflict |
assessment-timeout, assessment-state-unknown |
assessment-unavailable: a deadline that ran out or a state that could not be confirmed is retried with the same body |
journey-key-cardinality-exceeded, assessment-profile-not-activated |
Nothing: they are reserved for a future request profile that is not accepted today. The v1 and v1.1 requests never return them |
401, 403, 429 and 503 in one sentence each
Section titled “401, 403, 429 and 503 in one sentence each”- 401 — authentication of the attempt failed.
authentication-failedis uniform and is not retried;timestamp-out-of-windowandrequest-replayedare retried with a new attempt. - 403 — you are authenticated, but the credential lacks the route’s capability.
- 429 — above the server client’s rate. Wait for
Retry-After, then retry with a newrequest_id, timestamp and signature; retrying without waiting can block the credential for 10 minutes (limits). - 503 — unavailable or unknown state. Wait for
Retry-After, then retry with the same body and a newrequest_id, timestamp and signature, a bounded number of times; a retained assessment returns200; an expired result returns definitive410.
Useful headers
Section titled “Useful headers”- On the server-to-server API (assessment and feedback),
429and503carryRetry-Afterin whole seconds, at least 1; today they always send1. Read the header instead of hard-coding a value, and wait at least 1 second if it is ever missing. The collection endpoint’s429computes its value: at the new-session rate, the time until the next session open fits; at the application’s concurrent-session limit, up to 1800 seconds. The Web SDK honours it for you. - Every response carries
X-Correlation-Id, opaque and free of personal data. Keep it for support. - A
POSTto a path that does not start with/v1/assessmentsreceives404. Variations of/v1/assessments(query, trailing slash) and any method other thanPOSTreceive400 validation-failed.