GET /extractions/{id}: the result
Every field this endpoint returns, in every state · processing version 9
The five possible responses
| Job state | Status | Body | Headers |
|---|---|---|---|
| queued | 200 | {"id", "status": "queued", "version", "created", "queue_position"} | Retry-After: 30 |
| running | 200 | {"id", "status": "running", "version", "created", "started"} | Retry-After: 30 |
| done | 200 | The result, explained below. | Expires-At |
| failed | 500 | problem+json: {"type", "title": "Extraction Failed", "status": 500, "detail", "instance", "id", "version", "created", "started", "finished", "expires_at"}. detail says what broke. | Expires-At |
| unknown or expired | 404 | problem+json, "title": "Not Found" |
queue_position counts from 1 and excludes the job that is running: 1 means next. Poll every Retry-After seconds.
A complete done result
A shortened example: one performer with one ID copy and one document. The people and numbers are invented. Real results list every performer, copy, document and page.
{
"status": "done",
"version": 9,
"created": "2026-10-18T16:28:39+00:00",
"started": "2026-10-18T16:37:55+00:00",
"finished": "2026-10-18T16:44:12+00:00",
"expires_at": "2026-10-18T19:44:12+00:00",
"packet_sha256": "ec3ff078b2bdf0d7a76adfd38f2e0ea9326cd062b2e4cd35f0ee3dd95babb3ef",
"pages": 6,
"page_map": [
{"file": "Scene 1/release.pdf", "pages": [1, 2, 3, 4]},
{"file": "Scene 1/Jane ID.heic", "pages": [5]},
{"file": "Scene 2/Jane ID.heic", "pages": [5], "duplicate_of": "Scene 1/Jane ID.heic"},
{"file": "cast list.xlsx", "pages": [6]}
],
"metadata": {"title": "Example Movie 5", "scene": ["1", "2"]},
"answer": {
"pages": [
{"page": 1, "what": "model release, page 1"},
{"page": 5, "what": "passport photo page"},
{"page": 6, "what": "cast list"}
],
"performers": [
{
"stage_names": ["Jane Dynamite"],
"legal_name": "DOE, JANE A",
"date_of_birth": "15 MAR /MARS 99",
"date_of_birth_parsed": "1999-03-15",
"id_type": "passport",
"id_number": "AB123456",
"id_expiration": "2027 08",
"id_expiration_parsed": "2027-08-01",
"production_date": "May 4, 2021",
"production_date_parsed": "2021-05-04",
"id_copies": [
{
"page": 5, "box_2d": [112, 86, 878, 561],
"id_type": "passport", "legal_name": "DOE JANE A", "id_number": "AB123456",
"date_of_birth": "15 MAR /MARS 99", "date_of_birth_parsed": "1999-03-15",
"expiration_date": "04 AUG /AOÛT 27", "expiration_date_parsed": "2027-08-04",
"unreadable_fields": []
}
],
"documents": [
{
"pages": [1, 2, 3, 4], "kind": "model release",
"stage_name": "Jane Dynamite", "legal_name": "Jane A. Doe", "id_number": "AB123456",
"date_of_birth": "03/15/1999", "date_of_birth_parsed": "1999-03-15",
"production_date": "May 4, 2021", "production_date_parsed": "2021-05-04",
"form_date": "5/4/21", "form_date_parsed": "2021-05-04"
}
],
"notes": null
}
],
"unassigned": [],
"production_date": null,
"production_date_parsed": null
},
"id_crops": [
{"performer": 1, "copy": 1, "page": 5, "status": "verified",
"note": "passport; DOE JANE A", "jpeg_base64": "/9j/4AAQSkZJRgABAQAA…"}
],
"pdf": "/extractions/ec3ff078b2bdf0d7a76adfd38f2e0ea9326cd062b2e4cd35f0ee3dd95babb3ef/pdf"
}
Top level
| Field | Type | Meaning |
|---|---|---|
status | string | Always "done" in a result. |
version | integer | The processing version that produced this result: one number for the whole of the processing (assembly, model, prompt, crop checks, date parsing, response shape). null for jobs from before versioning. |
created | string | When the job was submitted. All timestamps are ISO 8601 UTC. |
started | string | When the extraction began (after waiting in the queue). |
finished | string | When the extraction ended. |
expires_at | string | When the job, this result and its PDF are deleted (3 hours after finished); same as the Expires-At header. |
packet_sha256 | string | SHA-256 of the combined PDF. Equals the job id when no metadata was sent and no file was excluded. |
pages | integer | Pages in the combined PDF. |
page_map | array | One entry per uploaded file, in upload order: where its pages went in the combined PDF. |
page_map[].file | string | The uploaded filename, as sent. |
page_map[].pages | array of integers | Its page numbers in the combined PDF; empty when the file was excluded. |
page_map[].duplicate_of sometimes | string | Present when this file has the same bytes as an earlier upload: it was included once, and pages points at that copy. |
page_map[].render_notes sometimes | array of strings | Present when the file wasn't read or rendered the way its name suggests: its content is another type than its extension says (it is read as what it really is), an image had several frames and only the first was included, or an office file could not be rendered as intended (for example, a spreadsheet that could not be set to landscape, so wide rows may split). |
page_map[].excluded sometimes | string | Present when the file was left out of the combined PDF, with the reason: its content is no accepted type, or it couldn't be read in full (for example unreadable image (JPEG): Premature end of JPEG file). The model never saw it; pages is empty. On a duplicate of an excluded file it is repeated alongside duplicate_of. |
metadata | object | The metadata fields you sent, unchanged; {} if none. A key sent more than once has a list of values. |
answer | object | What the model found in the packet: below. |
id_crops | array | Every ID copy cut out of the PDF as a JPEG, with its check: below. |
pdf | string | Where to fetch the combined PDF: /extractions/{id}/pdf. |
answer
The model's answer, plus a …_parsed field beside every date (how). Names, numbers and dates are
copied as printed on the documents; null means not shown or not legible. An answer with no performers is a valid
result, not an error. Every page number refers to the combined PDF.
| Field | Type | Meaning |
|---|---|---|
pages | array | The model's inventory of the packet, written before anything else: one entry per page. |
pages[].page | integer | The page. |
pages[].what | string | What the page shows, in a few words ("driver's license, front", "model release, page 2"). |
performers | array | One entry per real person, with everything about them from every page: below. |
unassigned | array | IDs, releases or forms the model could not tie to a performer. |
unassigned[].page | integer | Where it is. |
unassigned[].what | string | What it is. |
production_date, production_date_parsed | string or null | A production or shoot date the paperwork states for the movie as a whole. |
answer.performers[]
| Field | Type | Meaning |
|---|---|---|
stage_names | array of strings | Every stage name or alias given for this person anywhere, each once. |
legal_name | string or null | As printed on their government photo ID; from their documents if no ID was found. |
date_of_birth, date_of_birth_parsed | string or null | From the ID (else their documents). |
id_type | string or null | Driver's license, passport, national ID card, … |
id_number | string or null | The ID document's own number, character for character. |
id_expiration, id_expiration_parsed | string or null | The ID's expiration date (not its issue date). |
production_date, production_date_parsed | string or null | When this person's content was produced: the production or shoot date on their own release or form, else the date the form is dated. |
id_copies | array | Every copy of their government photo ID in the packet: below. |
documents | array | Every release, form, statement or cast-list entry about them: below. |
notes | string or null | Anything a reviewer must know (documents that disagree, an ID that looks expired). |
performers[].id_copies[]
One entry per copy of a government photo ID: the front (photo and name), plus the back when the front shows no date of birth.
| Field | Type | Meaning |
|---|---|---|
page | integer | Where the model says the copy is. See which page number to trust. |
box_2d | array of 4 integers | The ID's outline on that page, [x1, y1, x2, y2] on a 0–1000 scale from the top-left corner. |
id_type | string | The document type on this copy. |
legal_name, id_number | string or null | As printed on this copy. |
date_of_birth, date_of_birth_parsed | string or null | As printed on this copy. |
expiration_date, expiration_date_parsed | string or null | As printed on this copy. |
unreadable_fields | array of strings | Which of legal_name, id_number, date_of_birth, expiration_date are on the copy but not fully legible. |
performers[].documents[]
| Field | Type | Meaning |
|---|---|---|
pages | array of integers | Where the document is. |
kind | string | "model release", "2257 form", "cast list", … |
stage_name, legal_name, id_number | string or null | As the document gives them for this person. |
date_of_birth, date_of_birth_parsed | string or null | As the document gives it. |
production_date, production_date_parsed | string or null | Production or shoot date on the document. |
form_date, form_date_parsed | string or null | The date the form itself is dated or signed. |
id_crops[]
After the answer, each ID copy is cut out of the PDF (with a 20% margin around its outline, at 300 dpi) and shown to the model again on its own: is this an ID, and does it show the copy's recorded date of birth? A crop that fails is re-cut from the neighbouring pages and checked again. The checks never change the answer; they tell you whether the image can be trusted as evidence. Keep the images: they disappear with the job.
| Field | Type | Meaning |
|---|---|---|
performer, copy | integer | Which ID copy: answer.performers[performer-1].id_copies[copy-1]. |
page | integer | The page the crop was cut from: for a repaired crop, the corrected page. |
status | string or null | verified: an ID, showing the recorded date of birth. repaired: the first cut wasn't, but a neighbouring page was, and the crop was taken from there. failed: nothing could be vouched for. null: not checked. |
note | string or null | One line for a reviewer: the ID type and name read off the crop ("passport; DOE JANE A"), where a repaired crop moved to, back side for the back of a card, or what a failed check saw instead ("signed code of conduct page"). |
jpeg_base64 | string | The crop, a base64-encoded JPEG. |
How dates are parsed
Every date field in answer appears twice: as printed, and as …_parsed, an ISO YYYY-MM-DD date, or null when
the printed text can't be read as one date. Use the printed value as the evidence and the parsed one for arithmetic.
| Printed | Parsed | Rule |
|---|---|---|
5/4/21 | 2021-05-04 | Numeric dates are read month first... |
21/11/1986 | 1986-11-21 | ...unless the first number can't be a month: then day first. |
2019-05-04 | 2019-05-04 | Year-first dates are read as written. |
15 MAR /MARS 99 | 1999-03-15 | A second-language month (Canadian IDs) is ignored. Two-digit years 50–99 are 1900s, 00–49 are 2000s. |
01/02/49 as a birth date | 1949-02-01 | A birth date is never in the future: one that would be is moved back a century. |
2027 08 | 2027-08-01 (expiration) / 2027-08-31 (birth date) | A date without a day rounds the cautious way: birth dates to the month's last day, expiration and production dates to its first. |
08171990 | 1990-08-17 | Eight digits: month-day-year, else day-month-year. |
May 4, 2021 & May 5 2021 | 2021-05-04 | A production date listing several shoot days gives the earliest: the performer must be 18 on every one. If any listed day can't be read, the parsed value is null. |
Which page number to trust
All page numbers refer to the combined PDF. The model's own page numbers, in id_copies[].page and
documents[].pages, can be off by one on long packets. For an ID, prefer id_crops[].page: it is where a crop was
actually checked. To trace a page back to the file you uploaded, look it up in page_map.