Skip to main content
Get transaction returns the transaction envelope — identifiers, timestamps and status — and, once analysis has finished, a result_data object carrying the decision, every reason behind it, and everything chmod extracted along the way.

Envelope

string (UUID)
The transaction id.
string (UUID)
The customer this transaction belongs to.
string (ISO-8601)
When your backend opened the transaction. Format YYYY-MM-DDTHH:mm:ss.SSSZ, UTC.
string (ISO-8601) | null
When the SDK started the session on the device.
string (ISO-8601) | null
When the user finished capture.
string (ISO-8601) | null
When analysis started.
string (ISO-8601) | null
When analysis ended.
string
CREATED, INITIATED, COMPLETED, PROCESSING, FINISHED, EXPIRED or FAILED. result_data is present only for FINISHED and FAILED.

Decision

string
APPROVED, REJECTED or UNDETERMINED.
The rule is mechanical: if any issue has type: "REJECT", the decision is REJECTED. If the analysis could not run at all, it is UNDETERMINED. Otherwise it is APPROVED. WARN and INFO issues never change the decision. An APPROVED transaction can — and often does — carry warnings worth reviewing.
UNDETERMINED is not a middle ground between approved and rejected. It means the analysis did not complete: a malformed request, an invalid configuration, or a provider failure. Treat it as a system error to retry or escalate, never as a soft rejection of the user.

Issues

array
Every finding from the analysis. Always present; empty on a clean approval.
All applicable checks run to completion, so issues[] lists every problem at once rather than surfacing them one resubmission at a time.
See Issue codes for the full catalogue.

Block statuses

Alongside the overall decision, each area reports its own status:
string
PASSED or REJECTED. REJECTED when any document-related check rejected.
string
PASSED or REJECTED.
string | null
PASSED or REJECTED, or null when no comparison ran.
Which blocks are present depends on the transaction type: Device, customer and configuration issues belong to no block — they live in issues[] and affect the decision directly.

Document data

document.data holds everything read off the document. The printed fields:
document_number is normalised — alphanumeric only. document_number_raw is what was actually printed, dots and hyphens included. Store the raw value if you ever display it back to the user; compare on the normalised one.
When the document carries them, three more objects appear:
object | null
Structured address — street, city, administrative areas, postal code, country — plus the raw string as printed. null when the document has no address.
object | null
The machine-readable zone: type (TD1, TD2, TD3), the raw lines, and every parsed field with its check digit and a valid_* boolean. null when the document has no MRZ.
object | null
The decoded barcode: format (PDF417, QR, …), standard (AAMVA, ICAO, …), the raw payload, and parsed fields including address and document-specific extras such as licence class and restrictions. null when the document has no barcode.
chmod cross-checks the printed data, the MRZ and the barcode against each other. When they disagree it emits DOCUMENT_DATA_MISMATCH with the offending field — a strong tampering signal, since altering a printed field without recomputing the MRZ check digits is the most common forgery.

Liveness data

Age comes back as a range, not a number. Every attribute carries its own confidence, which is what lets you tell a confident rejection from a marginal one.

Face comparison data

Metadata

metadata carries the device, network and geolocation signals reported during capture — always, whatever the decision. See Device policy for the full shape.

Handling the result

Branch on code, never on message. Messages are prose and may be reworded; codes are a stable contract.