Run a Spec
Upload documents and run a Spec pipeline in a single call with POST /v1/run: mixed file and URL inputs, optional batch_id and metadata tagging, 202 with a poll URL.
The Run endpoint, POST /v1/run, is the one-call front door for Spec pipelines: send one or more documents together with a spec_id, and the platform ingests every input, waits for OCR, compiles the Spec's saved rail into a pipeline, and starts it — extraction, resolution, validation, and delivery exactly as composed in the Spec editor. It replaces the two-step "upload documents, then POST /v1/pipelines" flow for integrations that push files as they arrive.
Inputs are flexible: attach up to 20 files as multipart parts, pass remote file_urls for documents the platform should download, or mix both in one call. At least one input is required. The endpoint always answers 202 Accepted immediately with a run_id and a poll_url — ingestion and the pipeline run continue asynchronously, so the caller never blocks on OCR or LLM work.
Two optional tagging fields ride along and are stamped on every document the call ingests: batch_id, an opaque grouping key for correlating the run with an external job or batch, and metadata, a flat key-value object for anything else the caller wants to carry through. Both are echoed back by GET /v1/run/:id, and both surface on the ingested documents (batch_id / metadata on the document reads).
For a multi-file call, file_metadata tags individual inputs instead of stamping the same bag on every document: a JSON string keyed by each file's uploaded filename (or the exact file_urls entry), each value a flat object with the same shape and limits as metadata. Per file, its bag is merged over the call-level metadata — per-file wins on a shared key — and the resolved, per-input EFFECTIVE bag is what actually lands on the document and is echoed back in documents[].metadata on both this response and GET /v1/run/:id.
The 202 response carries a documents[] array — one entry per input, in the order you sent them — so you always know which platform document each upload became. Each entry has document_id, filename, size_bytes, and source (file or file_url). document_id is the canonical document: for a byte-identical re-upload it resolves to the existing document already on the platform rather than minting a new one, and the entry additionally carries deduplicated: true plus linked_document_id, the id of the thin per-upload link row created for this call. A first-time upload carries deduplicated: false and no linked_document_id.
The ingestion_target field controls how deep ingestion goes after OCR. The default, ingest, makes every document askable: once a document's OCR markdown is ready, Stage-2 field capture runs asynchronously in the background, extracting every field into the workspace corpus that [POST /v1/ask](post-ask) answers over and feeding the field registry. Capture follows the answers, it never delays them: the Spec pipeline starts the moment OCR markdown is ready, without waiting for capture. Pass extract to restore markdown-only ingestion: no background capture runs, and the documents do not join the askable corpus.
/v1/runMultipart form fields
ingestAppend mode
By default every /v1/run call creates its own pipeline. When the Spec's Source stage sets pipeline mode: append (or the call passes pipeline_mode=append), the platform instead appends the call's documents to the newest eligible existing pipeline for the Spec — so pushing 1,000 documents over many calls produces one growing table instead of one pipeline per call. A pipeline is eligible while its configuration still matches the Spec (schema fields, policies, validation gates, assembly and review config) and it is under the append size cap; a config edit or a full pipeline simply rotates to a fresh pipeline, which becomes the next calls' append target. No call ever fails because appending was not possible.
Under append mode, completion is per request, not per pipeline: the run.completed webhook fires when *this request's own documents* finish (its structured_data and records[] are scoped to them, and the payload carries the request's run_id), and GET /v1/run/:id reports status and progress for the request's documents only. The shared pipeline fires no pipeline-level run.* webhook of its own. Per-document document.structured deliveries are unaffected.
curl
Response
Response fields (202)
Response (202)
{
"run_id": "a8716d18-978d-4d19-8ca5-8b3784ca857c",
"spec_id": "1fc7807e-e1aa-4504-b796-5709986e78ed",
"status": "processing",
"input_count": 2,
"poll_url": "/v1/run/a8716d18-978d-4d19-8ca5-8b3784ca857c",
"documents": [
{
"document_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"filename": "invoice-0847.pdf",
"size_bytes": 184320,
"source": "file",
"deduplicated": false,
"metadata": { "source_system": "sap", "priority": 1, "cost_center": "AP-14" }
},
{
"document_id": "9f1e2d3c-4b5a-6789-0123-456789abcdef",
"filename": "msa-2026.pdf",
"size_bytes": 92160,
"source": "file_url",
"deduplicated": true,
"linked_document_id": "b7a6c5d4-e3f2-1098-7654-3210fedcba98"
}
]
}Errors
Error responses