Responses
The response envelope, entries, statuses and validation errors, field by field.
The envelope
Every JSON response from the API has the same four keys:
{
"status": "success",
"code": "document_processed",
"message": "Document processed successfully",
"data": { }
}Prop
Type
Check status, not only the HTTP code
Several errors, such as parser_not_found and document_not_found, are returned with HTTP 200 and "status": "error". Treat a response as successful only when the HTTP status is 2xx and status is success. Authentication failures are the exception: they use HTTP 401 and a {"detail": "..."} body. See Errors and retries.
Result codes
| Endpoint | Success code | data |
|---|---|---|
| Parse (sync) | document_processed | List of entries |
| Parse (async) | document_queued | { document_id, job_id } |
| Get a document | document_retrieved | Document with entries |
| Get a document, still in progress | no_parsed_data | Document with entries: [] |
| Correct parsed values | entry_updated | The updated entry |
Documents
Returned by Get a document:
{
"document_id": "3c59dc04-8a4e-4d6b-9f3e-7a1f0e2b5c66",
"status": "completed",
"url": "https://files.simplyparse.com/api/invoice-20418.pdf",
"metadata": {
"filename": "invoice-20418.pdf",
"content_type": "application/pdf",
"size_bytes": 184220,
"page_count": 2
},
"entries": [ ]
}| Field | Description |
|---|---|
document_id | The document's ID. |
status | pending, processing, completed or failed. The last two are final. |
url | Where the source file is stored. |
metadata | File details captured on upload: filename, content_type, size_bytes, page_count. |
entries | The entries extracted from this document, newest first. |
Entries
An entry is one extracted record. In Get a document each entry looks like this:
{
"id": "8f14e45f-ceea-467f-a8e6-3c1d2f0b9a51",
"status": "completed",
"cost": 2,
"cost_currency": "INR",
"processing_time_seconds": 7.42,
"created_at": "2026-03-12T09:41:07.120Z",
"updated_at": "2026-03-12T09:41:14.540Z",
"is_deduplicated": false,
"is_valid": true,
"parsed_data": { "invoice_number": "INV-20418", "total_amount": 48250 },
"validation_errors": []
}The sync parse response and webhooks carry a smaller version of the same entry:
| Field | Get a document | Sync parse | Webhook |
|---|---|---|---|
| Entry ID | id | document_id | entry_id |
| Document ID | top-level document_id | not included | document_id |
status, is_valid, parsed_data, validation_errors | ✓ | ✓ | ✓ |
cost, cost_currency, processing_time_seconds, timestamps, is_deduplicated | ✓ |
Entry status
status | Meaning |
|---|---|
completed | Extracted and stored. |
duplicate | Another entry in this parser already has the same value in a unique field. That existing entry was updated with this data, and this one was marked duplicate. |
pending, processing | Still in progress (rare on entries; the document status is the one to watch). |
failed | Processing failed for this entry. |
parsed_data
parsed_data follows your parser's fields exactly. Keys are field names, nested objects stay nested, and list fields (such as line items) are arrays of objects:
{
"invoice_number": "INV-20418",
"invoice_date": "2026-03-12",
"vendor": { "name": "Northwind Supplies", "gstin": "27AAEPM1234C1Z5" },
"total_amount": 48250,
"line_items": [
{ "description": "Steel brackets", "quantity": 50, "unit_price": 610.5 },
{ "description": "Anchor bolts", "quantity": 200, "unit_price": 89.9 }
]
}A field that wasn't found in the document comes back as null (or is left out). Treat every field as optional in your code and use validation rules such as required to flag the ones that must be present.
If you need a different shape, such as other key names, string amounts or padded codes, use data mapping on your webhook rather than reshaping in every consumer.
Validation errors
is_valid is true only when every rule on the parser passed. Otherwise validation_errors lists one item per failing field (the first rule that failed for that field):
{
"field": "total_amount",
"value": -120,
"rule": "min_value",
"message": "Must be at least 0",
"is_valid": false,
"parser_field_id": "1f0e3dad-9990-4cb7-a1c8-3a7c3fa0e1b2",
"path": { "key": "total_amount", "depth": 0, "index": 3 }
}| Field | Description |
|---|---|
field | The field name that failed. |
value | The extracted value that failed the rule. |
rule | The rule type, such as required, min_value, pattern, date_format or lookup. See Validation rules. |
message | Why it failed. This is your custom message if you set one on the rule. |
path | Where the value sits: its key, nesting depth, and index. |
A common pattern is to accept valid entries automatically and send invalid ones to a person with the messages shown next to each field. See Build a review queue.