Receipt Parse
About this benchmark
Reads a short, clean PDF receipt and fills a fixed JSON schema: invoice and receipt numbers, date paid, vendor, bill-to name and email, currency, subtotal, discount, total, amount paid, payment method and the line-item table. The model is told to use only values printed on the page.
This is the floor of the document suite: it asks nothing of long-context reading, only whether a model can hold a whole schema at once without dropping or inventing a field. Grading is per field: exact match on identifiers and dates, case-insensitive containment on names, a numeric tolerance on money, and absolute value on the discount so a sign convention does not decide the score.
Cases
receipt-a: One synthetic single-page receipt from Northwind Labs billed to Jane Doe, in USD. A 50% discount line takes a $22.00 subtotal down to an $11.00 total, so a model that reads the discount as positive, or reports the subtotal as the total, is caught.
Results
| Target | Score ↓ | Stddev | Latency | Tok/s | Cost | Errors |
|---|---|---|---|---|---|---|
| gpt-5.6-luna@openai | 100.0 | 0.0 | 3.9s | 54.5 | $0.0011 | 0/3 |
| gemini-3.5-flash-lite@google-ai-studio | 100.0 | 0.0 | 1.6s | 132.2 | $0.0021 | 0/3 |
| gpt-5.6-terra@openai | 100.0 | 0.0 | 2.4s | 58.5 | $0.0079 | 0/3 |
| ⚠qwen3.7-plus@alibabaerrorPOST "https://openrouter.ai/api/v1/chat/completions": 400 Bad Request {"message":"Failed to parse the file: The document parsing engine is currently rate limited. Please retry shortly.","code":400,"metadata":{"provider_name":null}} | 100.0 | 0.0 | 36.9s | 55.9 | $0.0095 | 1/3 |
| claude-haiku-4.5@anthropic | 100.0 | 0.0 | 5.2s | 37.9 | $0.0105 | 0/3 |
| gemini-3.7-flash | 100.0 | 0.0 | 11s | 69.3 | $0.0110 | 0/3 |
| gemini-3.8-flash | 100.0 | 0.0 | 6.9s | 149.7 | $0.0140 | 0/3 |
| gemini-3.6-flash@google-ai-studio | 100.0 | 0.0 | 8.1s | 187.2 | $0.0183 | 0/3 |
| grok-4.5@xai | 100.0 | 0.0 | 8.5s | 68.8 | $0.0208 | 0/3 |
| grok-4.6@xai | 100.0 | 0.0 | 15.2s | 67.5 | $0.0289 | 0/3 |
| ⚠muse-glimmer-30b2 field missesreceipt-a: date_paid (2/2)errorPOST "https://openrouter.ai/api/v1/chat/completions": 400 Bad Request {"message":"Failed to parse the file: The document parsing engine is currently rate limited. Please retry shortly.","code":400,"metadata":{"provider_name":null,"previous_errors":[{"code":400,"message":"Failed to parse the file: The document parsing engine is currently rate limited. Please retry shortly."},{"code":400,"message":"Failed to parse the file: The document parsing engine is currently rate limited. Please retry shortly."},{"code":400,"message":"Failed to parse the file: The document parsing engine is currently rate limited. Please retry shortly."}]}} | 93.8 | 0.0 | 14.6s | 92.8 | $0.0083 | 1/3 |
| ⚠glm-5v-turbo@z-ai16 field missesreceipt-a: amount_paid (1/1)receipt-a: bill_to_email (1/1)receipt-a: bill_to_name (1/1)receipt-a: currency (1/1)receipt-a: date_paid (1/1)receipt-a: discount (1/1)receipt-a: invoice_number (1/1)receipt-a: line_items.0.amount (1/1)receipt-a: line_items.0.description (1/1)receipt-a: line_items.0.quantity (1/1)receipt-a: line_items.0.unit_price (1/1)receipt-a: payment_method (1/1)receipt-a: receipt_number (1/1)receipt-a: subtotal (1/1)receipt-a: total (1/1)receipt-a: vendor_name (1/1)errorPOST "https://openrouter.ai/api/v1/chat/completions": 400 Bad Request {"message":"Failed to parse the file: The document parsing engine is currently rate limited. Please retry shortly.","code":400,"metadata":{"provider_name":null}} | 0.0 | 0.0 | 10.1s | 53.1 | $0.0046 | 2/3 |
| ⚠glm-4.6v@z-ai32 field missesreceipt-a: amount_paid (2/2)receipt-a: bill_to_email (2/2)receipt-a: bill_to_name (2/2)receipt-a: currency (2/2)receipt-a: date_paid (2/2)receipt-a: discount (2/2)receipt-a: invoice_number (2/2)receipt-a: line_items.0.amount (2/2)receipt-a: line_items.0.description (2/2)receipt-a: line_items.0.quantity (2/2)receipt-a: line_items.0.unit_price (2/2)receipt-a: payment_method (2/2)receipt-a: receipt_number (2/2)receipt-a: subtotal (2/2)receipt-a: total (2/2)receipt-a: vendor_name (2/2)errorPOST "https://openrouter.ai/api/v1/chat/completions": 400 Bad Request {"message":"Failed to parse the file: The document parsing engine is currently rate limited. Please retry shortly.","code":400,"metadata":{"provider_name":null}} | 0.0 | 0.0 | 21.8s | 41.9 | $0.0058 | 1/3 |
| ⚠qwen3.8-flasherrorPOST "https://openrouter.ai/api/v1/chat/completions": 400 Bad Request {"message":"Failed to parse the file: The document parsing engine is currently rate limited. Please retry shortly.","code":400,"metadata":{"provider_name":null}} | n/a | n/a | n/a | n/a | $0.0000 | 3/3 |
Note
- OpenRouter's document parsing engine was rate limited during the run and
returned
400 Failed to parse the filebefore any target saw the PDF. Five rows lost trials to it:qwen/qwen3.8-flashall three,z-ai/glm-5v-turbotwo, andqwen/qwen3.7-plus,z-ai/glm-4.6vandmeta/muse-glimmer-30bone each. Retries did not clear it. Every error on this page is that one upstream fault, not a model refusing or timing out. qwen/qwen3.8-flashhas no gradable output at all. Its 0.0 is three errored trials, not three wrong answers, and nothing on this page measures the model. A single call on the same slug immediately before the run parsed the document and scored every field, so read the row as unmeasured.- The two Z.AI zeros are schema breaks, not reading failures.
glm-4.6vandglm-5v-turboboth recovered the receipt correctly and then returned it under their own key layout:bill_to.nameandcustomer.namewherebill_to_namewas asked for,from.companyandvendor.namewherevendor_namewas,itemsanddiscountswhereline_itemsanddiscountwere. The values in those objects are right, including the receipt and invoice numbers, the email and every amount. All 16 fields miss on path, so the row reads as a model that cannot see the document when it is a model that will not fill the shape. meta/muse-glimmer-30b's only miss isdate_paid, on both trials that landed. It returnedJune 3, 2026where2026-06-03was required. The date is correct; the format is not.x-ai/grok-4.5,x-ai/grok-4.6,meta/muse-glimmer-30b,z-ai/glm-4.6vandz-ai/glm-5v-turbowere served cached prompt tokens despite cache busting, 256 and 256 for the two grok rows and 96, 11 and 2 for the rest, so read those latencies and costs as slightly flattered.git_shais0e9e555-dirty. Untracked run files were in the tree when the binary was built, so the stamp records the commit but the tree does not match it. No source undercmd/orinternal/differs from0e9e555.
Conclusion
Ten of the fourteen targets swept every trial, so the pick falls to cost and
speed. google/gemini-3.5-flash-lite takes both ends of it at 1,612ms and
$0.0021, the fastest row on the page and within a fifth of a cent of the
cheapest. openai/gpt-5.6-luna is cheaper still at $0.0011 but takes 3,929ms,
so it is the choice only where nobody is waiting on the reply. Everything above
$0.01 for the same clean sweep, including both grok rows at $0.0208 and $0.0289,
is paying for nothing this scenario can detect.
The failures split three ways and only one of them is about capability.
muse-glimmer's date is fixable in the prompt: the model read the receipt and
formatted the answer its own way. The Z.AI rows are the unsafe kind, and their
zeros understate rather than overstate them, because a consumer that keys off
the requested field names gets nothing back from a response that actually
contains every correct value. The rate-limited trials are not a model signal at
all, and qwen/qwen3.8-flash needs a re-run before anyone reads a number next
to it.