document_policy controls two separate things: which documents are eligible at all, and
whether the data extracted from an eligible document matches values you already hold.
Applies to DOCUMENT_AND_BIOMETRIC and DOCUMENT_ONLY. Ignored for BIOMETRIC_ONLY.
Document eligibility
string
How to read
target_documents.ALLOW— only the listed documents are acceptedREJECT— every supported document is accepted except the listed ones
array
The list
filter_mode operates on.document_eligibility entirely to accept every document chmod supports.
Expiry
allow_expired is set per entry, not globally, so you can accept an expired national ID
while still requiring a valid passport:
allow_expired: false emits EXPIRED_DOCUMENT. A document whose
issue date is in the future emits DOCUMENT_NOT_YET_VALID regardless of this setting.
Supported documents
A document outside this matrix emits
DOCUMENT_TYPE_NOT_SUPPORTED. One that is supported
but not permitted by your document_eligibility emits DOCUMENT_NOT_ELIGIBLE — two
different problems worth distinguishing when you handle them.
Data matching
data_matching compares what the document says against values you supply. Every field is
optional — include only what you actually hold and actually want enforced.
All mismatches are REJECT. There is no policy action to soften them: if you supply a
value, you are asserting it must match.
Fuzzy fields
Names are compared by text similarity, because transliteration, accents, middle names and compound surnames all make exact matching useless in practice.object
{ "value": "Ana Maria", "similarity_min_score": 0.85 }Rejects with NAME_MISMATCH when similarity falls below the threshold. The issue
carries { score, threshold } so you can see how close it was.object
{ "value": "Perez", "similarity_min_score": 0.85 }Rejects with SURNAME_MISMATCH, also carrying { score, threshold }.similarity_min_score ranges from 0.1 to 1.0, where 1.0 demands a character-for-character
match.
Names on documents are usually printed uppercase and unaccented, while your database
probably holds them as the user typed them.
0.85 absorbs that difference; 1.0 will
reject a large share of legitimate users.Exact fields
These must match exactly. None of them carrydetails — you already know the value you
sent, and the extracted value is in result_data.document.data.
string
M, F or X. Rejects with GENDER_MISMATCH.string
NATIONAL_ID, PASSPORT, DRIVER_LICENSE, RESIDENT_PERMIT or TEMP_PERMIT_ID.
Rejects with EXPECTED_DOCUMENT_TYPE_MISMATCH.string
ISO 3166-1 alpha-2. Rejects with
DOCUMENT_ISSUING_COUNTRY_MISMATCH.string
Alphanumeric only — no dots, hyphens or spaces. chmod normalises the extracted number
the same way before comparing, so send
20123456 rather than 20.123.456.
Rejects with DOCUMENT_NUMBER_MISMATCH.string
ISO-8601 date,
YYYY-MM-DD. Rejects with DATE_OF_BIRTH_MISMATCH.Consistency with the customer’s history
These checks need no configuration — they run whenever the customer has earlier transactions, and they are a large part of why reusingcustomer_id matters:
All three carry
reference_transaction_id, pointing at the earlier transaction they
disagree with, plus the recorded value — information you cannot reconstruct from the
result alone.
What comes back
Everything extracted from the document lands inresult_data.document.data: the printed
fields, the parsed MRZ with its check digits, the decoded barcode, and the address when
the document carries one. See Reading a result.
