Skip to main content
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 accepted
  • REJECT — every supported document is accepted except the listed ones
array
The list filter_mode operates on.
Omit document_eligibility entirely to accept every document chmod supports.
filter_mode: "ALLOW" with an empty target_documents accepts nothing — every transaction is rejected. chmod flags this with a CONFIG_TARGET_DOCUMENTS_EMPTY warning, but it will not fix it for you.

Expiry

allow_expired is set per entry, not globally, so you can accept an expired national ID while still requiring a valid passport:
An expired document with 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 carry details — 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 reusing customer_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 in result_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.