Field catalogue¶
fields in the response is every field read off the
printed document, re-keyed to this API's own vocabulary. This page is that
vocabulary: the keys, their labels, their categories, and the rules that decide
what is in the list.
The table below is rendered from the code that resolves a field at run time. A key on this page is a key the service publishes.
The shape of an entry¶
| Key | Type | Meaning |
|---|---|---|
id |
string | Identity of this entry, unique across the array |
name |
string | The stable snake_case key catalogued below |
label |
string | The human label catalogued below |
category |
string | One of the six below |
value |
string or null | The value of this reading |
language |
string or null | The language this reading was made in |
confidence |
band | high, medium or low |
The identity rule¶
name repeats. id does not.
A document that prints a field in two scripts is returned as one entry per
script, and every one of those entries carries the same name. A consumer that
keys a list on name collides, and a keyed user interface built on it breaks
outright.
id is name@lcid: the key, an @, and the numeric language identifier the
reading was made under. The same key and language may legitimately appear
twice, on a second page or in a re-read of one zone. A repeat therefore takes
an occurrence counter.
[
{ "id": "given_names@0", "name": "given_names", "language": null },
{ "id": "given_names@1032", "name": "given_names", "language": "Greek" },
{ "id": "given_names@0#2", "name": "given_names", "language": null }
]Neither @ nor # can occur in a key. A curated key is snake_case, and a
passed-through key is slugged to [a-z0-9_], so a suffixed id can never
collide with a plain one.
The six categories¶
| Category | What belongs to it |
|---|---|
identity |
The holder: names, birth date, sex, nationality, personal numbers |
document |
The document itself: its number, series, class name, issuing authority and state |
dates |
Issue, expiry and the derived countdown |
address |
The address and its parts |
visa |
Visa class, type, validity and entries |
other |
Everything else, including every passed-through field |
The catalogue¶
These keys are curated. Each has a stable name, a label and a category that do not change with the document, the country or the engine's own naming.
| Key | Label | Category |
|---|---|---|
address |
Address | address |
address_area |
Address: area | address |
address_city |
Address: city | address |
address_postal_code |
Address: postal code | address |
address_state |
Address: state | address |
address_street |
Address: street | address |
authority |
Issuing authority | document |
birth_date |
Date of birth | identity |
birth_place |
Place of birth | identity |
dl_class |
Driving-licence class | document |
document_class_name |
Document class name | document |
document_number |
Document number | document |
document_series |
Document series | document |
expiry_date |
Date of expiry | dates |
eyes_color |
Eye colour | other |
full_name |
Full name | identity |
given_names |
Given names | identity |
height |
Height | other |
issue_date |
Date of issue | dates |
issue_place |
Place of issue | document |
issuing_state_code |
Issuing state code | document |
issuing_state_name |
Issuing state | document |
mothers_name |
Mother's name | identity |
nationality |
Nationality | identity |
nationality_code |
Nationality code | identity |
other |
Other | other |
passport_number |
Passport number | document |
permit_class |
Permit / licence class | document |
personal_number |
Personal number | identity |
race_ethnicity |
Race / ethnicity | other |
sex |
Sex | identity |
social_security_number |
Social security number | identity |
surname |
Surname | identity |
visa_class |
Visa class | visa |
visa_duration_of_stay |
Duration of stay | visa |
visa_id |
Visa ID | visa |
visa_number_of_entries |
Number of entries | visa |
visa_type |
Visa type | visa |
visa_valid_from |
Visa valid from | visa |
visa_valid_until |
Visa valid until | visa |
The set is open¶
The catalogue is not the whole of what can appear. A field the vocabulary does not name is still published, never dropped:
- the key is the engine's own field name, lower-cased with every run of non-alphanumeric characters collapsed to one underscore;
- the label is the engine's own name, unchanged;
- the category is
other.
A passed-through key that would collide with a curated one takes an x_
prefix. A curated key therefore always means what this page says it means. A
field with no usable name at all falls back to field_<n>.
The practical consequence: match on the keys below where a key matters, and
render the rest generically from label and category. A list that assumes
the catalogue is exhaustive drops data the recognition produced.
The two derived keys¶
Two entries are minted rather than read, and both come after the engine's own order.
| Key | Category | What it is |
|---|---|---|
days_to_expire |
dates |
The expiry countdown in days, as a string |
mrz |
document |
The whole machine-readable zone as one entry |
days_to_expire is negative once the document has expired and null when the
document carries no date of expiry. It is absent entirely when the scan
produced no validity data at all: a countdown derived from nothing is not a
countdown. Its confidence is that of the expiry-date reading it came from.
mrz carries the zone's whole text as its value, with language: null. The
zone is defined over a restricted Latin alphabet and has no language of its
own. The formats are on the MRZ reference.
What is left out of the list¶
Fields that belong to the machine-readable zone¶
Three kinds of entry are the zone's own plumbing rather than facts about the holder: its raw lines, its type designation, its check digits. Each is mapped so the zone's verdict can be derived from it, then left out of the published list. A field the engine only ever read out of that zone is left out for the same reason: the printed page already states it.
What the zone says is published as one verdict, mrz, and as its own entry in
fields.
Two field types withheld on purpose¶
Two of the engine's field types are withheld from every response. Each is a decision, and each has a reason a reader can check.
| Withheld | Why |
|---|---|
0, the document class code |
The one-letter class designation, P on a passport. document.kind publishes the same fact in words, so the letter would make a reader carry a code table to learn what the result already told them |
364, the remainder term |
A countdown to expiry in whole months, derived by the engine from the expiry date it already reports. Among a row of dates, a bare number reads as days — wrong by a factor of about thirty, with nothing to signal it. The same fact is published as days_to_expire, in the unit its label promises |
Neither exclusion loses a fact. Both replace a reading that would be read wrongly with one that says the same thing unambiguously.
Name normalization¶
A holder's name never contains a line break.
A document that runs the holder's names across two printed lines makes the engine report a value with a break inside it. A name is a name whether or not the page ran out of room. Consumers put these values straight into a field, a label or a CSV cell, where a break is a broken row.
The rule applies to surname, given_names and full_name, in every script:
- every line break becomes exactly one space, including the two Unicode line separators a national-script reading can carry;
- runs of spaces collapse to one;
- the ends are trimmed;
- a value with nothing left comes back
null, because an empty string is not a name.
A scan stored before this rule existed is repaired when it is read back.
The same normalization runs over a field list replayed out of storage, so
GET /v1/scans/{id} never returns a name the current rule would not have
produced.
Other values are not reflowed. Only the three name fields are, because only they are printed as a person's name across a line break.
What a reading's value is¶
value is the value of this reading, not of the field as a whole.
language |
value carries |
|---|---|
null |
The neutral reading: the transliterated Latin value the engine merged across sources |
| A language name | The national-script spelling, as the document prints it |
A document that prints the surname in two scripts yields two entries. They
share a name and carry two different values, one Latin and one not. Neither
is a translation of the other. Both are readings of the same printed page.
A value the engine produced nothing for is null rather than an empty string.
An entry with a null value is still published, because the absence of a value
is itself a fact about the document.
Which keys a document carries¶
No document carries every key, and nothing in the contract promises a particular key for a particular document. The recognition reports what it read. The groupings below are what the common documents print, not a guarantee.
| Document | Keys it usually carries |
|---|---|
| Passport | surname, given_names, document_number, passport_number, birth_date, sex, nationality, issuing_state_name, expiry_date, issue_date, birth_place, authority, mrz |
| ID card | The same identity and document keys, plus personal_number, address and its parts, and document_series where the country prints one |
| Driving licence | surname, given_names, birth_date, document_number, dl_class or permit_class, issue_date, expiry_date, address, authority |
| Visa | visa_id, visa_type, visa_class, visa_valid_from, visa_valid_until, visa_duration_of_stay, visa_number_of_entries |
A key that a document does not print is absent from fields altogether. It is
not published with a null value: the array carries readings, and a reading that
was never made is not one.
The safe shape for a consumer is a lookup over the array rather than a
positional read. Find the entry whose name matches; its absence means the
document did not print it.
Where a key appears twice¶
A value legitimately appears twice in one response: once in the curated block
(holder, document) and once in fields. They are not copies of one another.
The curated block carries the merged best reading in a fixed set of keys.
fields carries one entry per language, so a national-script spelling is
visible beside the transliterated one.
The language a reading was made under is on field languages and scripts.