---
title: "Ingest documents and run a Spec's pipeline in one call"
method: POST
path: "/v1/run"
tags: ["Run"]
---

# Ingest documents and run a Spec's pipeline in one call

`POST /v1/run`

## Request

- Base URL: `https://api.talonic.com`
- URL: `https://api.talonic.com/v1/run`
- Auth: HTTP bearer

Accepts one or more files, one or more `file_urls`, or a mix of both — at least one input is required. Ingests every input (metering each ingest leg), waits for OCR to finish, then compiles the named Spec's saved rail into a pipeline and starts it — the same compile step `POST /v1/pipelines` uses, minus the separate "upload documents first" step. Always returns 202; poll `GET /v1/run/{id}` or listen for the `run.completed` / `run.failed` webhook (`POST /v1/webhooks`). Requires write scope. Unlike `POST /v1/process`, this endpoint does not dedup — every call starts a fresh run. Content-based document dedup still applies per input within the call — see the `documents` response field.

## Response `202`

Ingest + run accepted.

- object
  - `run_id` string, uuid
  - `spec_id` string, uuid
  - `status` 'processing'
  - `input_count` integer: Total files + file_urls accepted.
  - `poll_url` string
  - `documents` object[]: One entry per input, in input order — multipart files (in request order) first, then file_urls; documents.length === input_count. Byte-identical inputs in the same request share one processing identity, so GET /v1/run/{id}'s progress.total_documents can be lower than input_count. A byte-identical re-upload from a later request gets its own occurrence id and carries duplicate_of.
    - `document_id` string, uuid, required: The id result rows and run.completed records[] carry. Every upload gets its own occurrence id; a byte-identical re-upload from a later request gets a new occurrence (its link row). When that link row cannot be created or read, the re-upload carries the canonical id. A repeat of a file within one request carries the first copy's id.
    - `filename` string, nullable, required: For file inputs, the caller's uploaded filename (even when deduplicated). For file_url inputs, the filename derived at download.
    - `size_bytes` integer, nullable, required
    - `source` 'file' | 'file_url', required
    - `deduplicated` boolean, required: True when this occurrence reused a pre-existing document's bytes and OCR.
    - `existing_document_id` string, uuid: Present only when deduplicated is true — the canonical, i.e. the first upload of these bytes, whose file bytes and OCR are reused (equals duplicate_of.id when that is present).
    - `duplicate_of` object: Present on a duplicate occurrence — the first upload of these bytes, whose file bytes and OCR this occurrence reuses.
      - `id` string, uuid, required
      - `filename` string, nullable, required
    - `linked_document_id` string, uuid: Present only when deduplicated is true — the link row minted for this input. Deprecated alias of document_id: it equals document_id when this input is the first copy of its bytes in the request and the link row resolves. Otherwise document_id is the canonical id, or the first copy's id for a repeat within the request.
    - `metadata` object: This input's EFFECTIVE metadata for THIS request — the call-level `metadata` merged with its `file_metadata` entry (per-file wins), captured at submit. Present only when set. It is stored on this occurrence and is the authoritative request tag source.
  - `warnings` object[]: Present only when the accepted request carries a non-fatal note: `no_binding_for_node` (a `bindings` override names a Dispatch node that has no active binding, so nothing will be delivered for it); `node_not_in_live_pipeline` (the node is on the published version but not on the newest pipeline's frozen rail — if this request appends onto that pipeline, its on_run_completed trigger cannot see the node; the early trigger modes can); `node_not_on_published_version` (the node exists only on that pipeline's frozen rail — it governs on_run_completed there and nothing else).
    - `code` 'no_binding_for_node' | 'node_not_in_live_pipeline' | 'node_not_on_published_version', required
    - `message` string, required

## Other responses

- `400`: Missing spec_id, no input provided (both files and file_urls empty), metadata is not a valid flat JSON object (`invalid_metadata`), or `dispatch` / `bindings` are malformed or name an unknown Dispatch node, an inactive or foreign destination, or a destination the node's bindings cannot deliver to (`invalid_delivery_controls`).
- `402`: Insufficient credits for an ingest leg.
- `413`: A file exceeds the tier's per-file size cap.
- `429`: API rate limit or pipeline-queue admission limit reached; retry after the advised delay.
- `503`: Pipeline queue headroom could not be verified before ingest.

---

[API](https://skmtc.dev/talonic/apis/talonic-api.md) · [All operations](https://skmtc.dev/talonic/apis/talonic-api/llms.txt) · [OpenAPI document](https://skmtc.dev/talonic/apis/talonic-api/revisions/678fe5f8c9c3?raw)
