Skip to content

Error codes

An error answers JSON with a machine-readable code and a human-readable message, plus details where they help. Act on code, not on the message, which may change.

{"code": "CASE_NOT_CANCELLABLE", "message": "…", "status": "DONE"}

A body that fails validation answers 400 with every problem found:

{
"message": "…",
"validationErrors": [
{"instancePath": "/body/participants/0/email", "keyword": "format", "params": {"format": "email"}, "message": "…"}
]
}

instancePath points at the field, keyword says which rule failed (required, format, maxLength, insidePage, …) and params carries the rule’s details, for example missingProperty for required.

Two kinds of answer carry only {message}: a 401 or 403 from the gateway when the token is missing or invalid, and a 429 when you are throttled. An unexpected failure answers 500 {"message": "Internal Server Error"}.

Status code Where Meaning
400 UNKNOWN_DEVICE POST /cases, POST .../open the deviceId is not a registered device of your tenant
400 INVALID_LIMIT GET /cases/{caseId}/events limit is not 1 to 100
400 INVALID_CURSOR GET /cases/{caseId}/events the cursor does not belong to this listing
400 OTP_INVALID POST .../otp/verify wrong code; attemptsLeft says how many tries remain
401 OTP_REQUIRED POST .../signature, GET .../signedDocument the case asks for a one-time code and the request has no valid Trustink-Otp-Session
404 DOCUMENT_NOT_FOUND POST /verify nothing was uploaded under the key, the upload expired, or it was verified already
409 CASE_NOT_CANCELLABLE DELETE /cases/{caseId} the case is past NEW and IN_PROGRESS; status says where it is
409 ALREADY_SIGNED POST .../signature, POST .../open the participant has signed already
409 NOT_QUICK_SIGN POST .../open the case was not created with quickSign
409 PARTICIPANT_NOT_READY POST .../open the document has not been uploaded yet
409 NOT_COMPLETED GET .../signedDocument the case is not DONE yet; status says where it is
409 OTP_NOT_REQUIRED POST .../otp, .../otp/verify the case has no multiFactorType
409 OTP_NO_DESTINATION POST .../otp the participant has no address or number for the channel
409 OTP_NOT_REQUESTED POST .../otp/verify no code was sent, or the last one was used
409 OTP_EXPIRED POST .../otp/verify the code is older than ten minutes, or a newer one replaced it
410 CASE_NOT_ACTIVE participant routes, POST .../open nobody can sign the case any more (EXPIRED, UPLOAD_REJECTED, CANCELLED or FAILED); status says which
410 LINK_EXPIRED participant routes the case is DONE and its validUntil has passed
413 DOCUMENT_TOO_LARGE POST /verify the PDF is larger than 25 MB
422 NOT_A_PDF POST /verify the upload is not a PDF
422 UNREADABLE_DOCUMENT POST /verify the PDF or its signatures cannot be read
423 OTP_LOCKED POST .../otp/verify five wrong codes; request a new one
429 OTP_RATE_LIMITED POST .../otp five codes in the last hour; retryAfterSeconds says when
501 OTP_CHANNEL_UNAVAILABLE POST .../otp the SMS channel is not available yet
503 EVENTS_UNAVAILABLE POST .../open the kiosk could not be told; try again
503 TIMEOUT any the request ran out of time; try again

A 410 on a participant route also carries senderName when the case has a sender name, so a signing page can say who sent the request.

POST /cases is not idempotent: retrying it after a timeout can create a second case. Store the case id as soon as you receive it, and cancel a case you do not need with DELETE /cases/{caseId}.

Status Meaning
NEW created, waiting for the document
IN_PROGRESS the document is uploaded; participants are signing
DONE everyone signed; the signed PDF and the evidence summary are ready
UPLOAD_REJECTED the upload was not a PDF of 1 KB to 25 MB; rejectReason says why
EXPIRED validUntil passed before everyone signed; expiredAt
CANCELLED you cancelled the case; cancelledAt, cancelReason
FAILED everyone signed, but the document could not be signed; failedAt, failureReason