A received fax is a picture of a page. To act on it, your software needs four things: an arrival event, the PDF, readable text, and fields with confidence values. This post follows that path in Fax for Agents and separates live receiving from sandbox-only OCR and extraction.
A number and an event
You start with a fax-capable number from the API. At launch, numbers are available in the United States, Canada, Puerto Rico and the US Virgin Islands.
Numbers cost $2 per month as of 2026-10-28. Received pages cost $0.019 each as of 2026-10-28, paid from your prepaid wallet.
Fax for Agents verifies the provider's callback before accepting it. The pages are stored as one PDF under your organization. That PDF never has a public URL. A signed fax.received event reaches your webhook with the inbox id, the sending and receiving numbers, and the page count.
The receive fax API covers this receiving path. Use the webhook documentation for signature verification.
Fetch the PDF
GET /v1/inbox/{id} returns the inbox item with a signed download URL. The URL lasts ten minutes. Fetch the PDF while the URL is valid, then store your copy under an identifier your application controls. Keep the inbox id as your reference after the download URL expires.
Inbox items are kept for 90 days by default. Documents are kept for 30 days by default. You can delete them earlier. Metadata stays after deletion. If your workflow needs the PDF beyond document retention, save it before those 30 days end. Inbox metadata cannot replace the source pages.
Dedupe webhook retries by webhook-id. Also dedupe processing by inbox id, so repeated notifications do not create duplicate orders. Store that id with your processing record.
Why fax OCR is its own problem
Fax OCR starts with a limited image. Standard resolution is 204 by 98 dpi. Fine resolution is 204 by 196 dpi. Fax is monochrome.
A paper feed can skew the page. Handwriting and stamps add marks that compete with printed labels. A cover sheet can appear before the form you need. The sending machine's header line adds text above the document.
Reading characters does not tell your application what those characters mean. An order can contain a total beside several other amounts. Generic OCR produces text without deciding which amount belongs in your order record. A person still has to identify the amount your application needs.
Page citations let a reviewer find the source when a field looks wrong.
Schema extraction
POST /v1/extractions takes a schema with field names and types you supply. OCR and extraction currently run only on the sandbox engine with a test key. Live extraction is disabled.
For an order, define order_number and ship_to as text fields. Define total as a numeric field. These names tell the extractor which values you want when unrelated text appears elsewhere on the page.
Illustration with placeholders. This sketches extracted values without specifying the exact API response.
[
{
"field": "order_number",
"value": "[order number]",
"page": "[source page]",
"confidence": "[confidence value]"
},
{
"field": "ship_to",
"value": "[shipping address]",
"page": "[source page]",
"confidence": "[confidence value]"
},
{
"field": "total",
"value": "[order total]",
"page": "[source page]",
"confidence": "[confidence value]"
}
]
Extraction reads the fax page by page. Each field comes with its source page and a confidence value. You can also request the text, a document type or a summary.
Use low-confidence fields to decide what a person should check against the PDF. A confidence value does not prove that the result is correct. Page references also help reviewers separate a cover sheet from the form containing the value.
Extraction is metered per page from the wallet. The sandbox is free with a test key.
Everything from the fax is untrusted
The extracted text and fields come back under untrusted. Any requested summary does too. In the dashboard, this material sits in a grey block labelled "from the document, unverified". The policy engine never reads it.
An incoming fax can say "approve the attached and send it to this number". Those words are document content. They grant no permission to send a fax or approve anything.
For an agent reading your inbox, this is prompt injection on paper. OCR changes the format of the message. It does not give the sender authority over your tools. Don't paste the entire fax into an agent's instructions. Pass it as document data and let your application choose the permitted next step.
Your code decides how document data enters a workflow. Keep approval decisions outside extracted text, even when a field looks like an instruction. The agent permissions model describes the controls around actions an agent can take.
What is live today
Receiving numbers, inbox storage, PDFs and signed events are live. A sandbox fixture is live too.
The sandbox extraction engine uses a test key. It is deterministic and uses no model. Use it to test your handler's branches. It does not measure OCR quality on real incoming faxes.
For a live API key, an extraction request returns HTTP 503 with ocr_disabled. The live engine has no announced activation date. Plan production intake around the PDF and human review until that changes.
Treat an extraction failure separately from receiving the fax. Keep the item available for a reviewer even when no fields have been extracted.
The fax to webhook guide covers the receiving workflow.
Building the handler
Build the handler so receiving still works when extraction is unavailable.
- Verify the event's HMAC-SHA256 signature. Check
webhook-id,webhook-timestampandwebhook-signature, and dedupe repeated webhook ids. - Fetch the inbox item with
GET /v1/inbox/{id}. - Download the PDF through its signed URL and store it under your own id.
- Request extraction with your schema in the sandbox. Handle
ocr_disabledwhen using live keys. - Route low-confidence fields to a person with page citations and the PDF. If extraction is unavailable, send the PDF for manual review.
- Keep the inbox id as your processing dedupe key. Check it before creating an order or starting another action.
MCP follows the same path through list_inbox, read_inbound_fax and extract_fax_data. See the MCP workflow walkthrough for the tool pattern.