stage_filesturns a local file into a reference the API accepts.create_workflowbuilds the typed graph.upload_documentsputs the file into the workflow.run_document_packetstarts the extraction, retry-safe.get_runwaits for the result and reads it.
1. Stage a local file
An MCP tool call carries JSON, not bytes, so no tool takes a file directly.stage_files closes the gap: it returns an upload form for the bytes, plus a short object_id to refer to them by afterwards.
upload.fields entry verbatim, then the file.
{ "object_id": "06a953d9…", "filename": "single_invoice.pdf" }. Prefer the id over read_url everywhere inside the API. The id is a few characters where the presigned URL is kilobytes, and it does not expire mid-conversation. read_url exists for handing the bytes to something outside anyformat.
Staged bytes are scratch. They belong to no workflow, and storage deletes them within a day. Stage, then consume promptly. A file that must live on goes into a workflow, in step 3.
2. Create the workflow
create_workflow takes the same typed graph as POST /v3/workflows/: exactly one parse node, an extract node with the field schema, and here a validate node with two deterministic rules. A deterministic rule is a check that runs in code, instantly and for free.
persistent_id:
persistent_id unchanged, including across renames. That edit loop is get_workflow, change the graph, update_workflow. The id is the field’s identity. It keeps quality metrics, ground truth and analytics attached. A field sent without one is always treated as new, and silently detaches all of that.
If the graph is invalid, the error names every broken rule. This is a real rejection of a graph with no parse node:
error_code, and quote request_id in a support request.
3. Upload the document
upload_documents puts files into the workflow as one document packet. It accepts fetchable HTTPS urls, staged staged_files, or a mix. The staged file from step 1 goes in by id:
4. Run it, retry-safe
run_id with status: "processed", telling you the result is already there.
5. Read the result
get_run long-polls server-side, so one call waits instead of the agent polling. parse_output: "none" drops the parsed markdown from the response when only the extracted fields matter. On a real document the parse section is about 90% of the payload.
processed and results.extractions[0] carries every field with its confidence and the evidence it was read from:
Editing the workflow later
The edit loop is fetch, edit, replace.get_workflow returns the {name, description, nodes, edges} shape that update_workflow accepts. Renaming total_amount to grand_total while echoing its persistent_id keeps the field’s identity, so its metrics and history follow the rename:
list_workflow_versions, then get_workflow(workflow_id, version=...).
Quick parse, and what it is not
parse_document is the one-call shortcut when you need only a single document’s markdown. Pass {object_id, filename}, or an HTTPS url, then call get_run. The markdown is at results.parse.markdown. The invoice above parsed in about 13 seconds.
It is a quick one-off, not a production pipeline:
- Every call starts a new billed run. There is no idempotency key on this path.
- It runs against an auto-provisioned system parse workflow, not one you manage.
- Save the markdown yourself. anyformat does not retain quick-parse output. Treat the run as ephemeral.
upload_documents → run_document_packet → get_run, as above.
Asking questions across documents
A workflow with a Knowledge node indexes every parsed document into a navigable corpus.ask_knowledge then answers questions about the content, with citations resolved to a page and region of the source PDF. Mint a thread_id with the prefix kb- to keep follow-ups in context. Every question is billed and can take a few minutes. KNOWLEDGE_NOT_READY means the index is still building. Retry.
Related
- MCP server reference: endpoint, auth, client setup, the full tool table.
- Node schemas: every node type and field the typed graph accepts.
- Coding assistant: the same know-how as an installable skill package.

