Skip to main content

Run Results

Poll a /v1/run request's own structured rows as JSON with GET /v1/run/{id}/results: always scoped to your submitted documents, with cells/provenance/audit includes.

GET /v1/run/{id}/results returns this `/v1/run` request's own structured rows as poll-able JSON — the same governed read behind GET /v1/pipelines/{id}/results (review holdback, demoted-field projection, __ diagnostics filtering, assembly awareness), scoped to exactly the documents *this call* submitted. It answers "what did MY submitted documents produce," which is the question most /v1/run integrations actually have, without needing to track the compiled pipeline_id at all.

This route is ALWAYS the per-document view, scoped to the request's own documents[] echo, uniformly across new and append pipeline modes. This is a deliberate divergence from the per-run run.completed webhook: for an unscoped, non-append assembly run, that webhook actually delivers COMPOSED rows. Composed output for an assembly run lives at GET /v1/pipelines/{id}/results?view=composed instead — this response's links.composed_results points there once a pipeline exists, so the divergence is always discoverable from the response itself.

Only document_id and include filter the rows here. run_id, view, since, until, and status are pipeline-route-only parameters — supplying any of them 400s with unsupported_filter rather than silently ignoring it, since the run itself already IS the scope and its time window is already bounded. include=cells,provenance,audit behave exactly as on the pipeline route: cells for per-field value/status/confidence/source, provenance for a stable kind-tagged audit projection, audit for the bounded cell-version trail — see [Pipeline Results](get-pipeline-results) for the full shape and the held-value redaction rules (a held field's value is never exposed under any include).

Two zero-states return 200 with an empty page and a scope_note explaining why — never 404 — since pollers hit these windows constantly: no compiled pipeline exists yet for this run (still ingesting, or it failed before a pipeline was created), or the run predates per-request document tracking (an echo-less legacy row whose membership is unknowable, so an honest empty page beats a guess). The envelope's status folds the same three-state vocabulary as GET /v1/run/{id} (processing/completed/failed) and, unlike the pipeline route's own status, it DOES settle even when the underlying pipeline is shared under append mode — poll this route, not the pipeline route, for append integrations that need a status that eventually reaches completed.

Prefer this endpoint over GET /v1/pipelines/{id}/results whenever your integration thinks in terms of "my /v1/run call", not "the pipeline it landed on" — it needs no pipeline_id bookkeeping and its status always settles, even under append mode.
GET/v1/run/{id}/results

Query parameters

document_idstringComma-separated document UUIDs (1-100), intersected with this run's own documents echo.
includestringComma-separated subset of cells, provenance, audit.
limitintegerMaximum records per page (max 100). Default: 25
cursorstringPagination cursor from a previous response's pagination.next_cursor.

Request

Response

Response fields

run_idstringThe run request id.
pipeline_idstring | nullThe compiled pipeline, once it exists. Null while still ingesting.
spec_idstringThe Spec being run.
statusstringprocessing, completed, or failed — the same folded vocabulary as GET /v1/run/{id}. Settles even under append mode.
viewstringAlways documents on this route.
generated_atstringISO 8601 timestamp this page was generated.
columnsarrayDemotion-projected schema columns: { field_key, display_name, data_type }.
dataarrayThis request's own result records — same record shape as GET /v1/pipelines/{id}/results.
paginationobject{ total, limit, has_more, next_cursor } — cursor keyed on record_id.
pending_review_countintegerHeld cells in this page's records only.
scope_notestringPresent only for the two zero-states — no pipeline yet, or an echo-less legacy run.
linksobject{ self, run, composed_results? } — composed_results is present only once a pipeline exists, pointing at the pipeline's composed view.

Response

{
  "run_id": "a8716d18-978d-4d19-8ca5-8b3784ca857c",
  "pipeline_id": "1a0c681d-ea20-4bb4-8892-01a6d7f834da",
  "spec_id": "1fc7807e-e1aa-4504-b796-5709986e78ed",
  "status": "completed",
  "view": "documents",
  "generated_at": "2026-07-22T09:41:00.000Z",
  "columns": [
    { "field_key": "rechnungsnummer", "display_name": "Rechnungsnummer", "data_type": "string" },
    { "field_key": "bruttobetrag", "display_name": "Bruttobetrag (EUR)", "data_type": "number" }
  ],
  "data": [
    {
      "document_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "filename": "invoice-0847.pdf",
      "run_id": "a8716d18-978d-4d19-8ca5-8b3784ca857c",
      "pipeline_id": "1a0c681d-ea20-4bb4-8892-01a6d7f834da",
      "record_id": "pd_c3d4e5f6",
      "status": "complete",
      "completed_at": "2026-07-22T09:40:12.000Z",
      "fields": {
        "rechnungsnummer": "RE-2026-0847",
        "bruttobetrag": 1249.90
      },
      "cells": {
        "rechnungsnummer": { "value": "RE-2026-0847", "status": "filled", "confidence": 0.98, "source": "llm_extraction", "document_id": "c3d4e5f6-a7b8-9012-cdef-123456789012", "filename": "invoice-0847.pdf" },
        "bruttobetrag": { "value": 1249.90, "status": "filled", "confidence": 0.95, "source": "llm_extraction", "document_id": "c3d4e5f6-a7b8-9012-cdef-123456789012", "filename": "invoice-0847.pdf" }
      }
    }
  ],
  "pagination": { "total": 1, "limit": 25, "has_more": false, "next_cursor": null },
  "pending_review_count": 0,
  "links": {
    "self": "/v1/run/a8716d18-978d-4d19-8ca5-8b3784ca857c/results",
    "run": "/v1/run/a8716d18-978d-4d19-8ca5-8b3784ca857c",
    "composed_results": "/v1/pipelines/1a0c681d-ea20-4bb4-8892-01a6d7f834da/results"
  }
}

Errors

Error responses

400bad_requestcode is one of invalid_document_ids, invalid_include, unsupported_filter (a pipeline-route-only filter was supplied), audit_include_too_broad.
401unauthorizedMissing or invalid API key.
404not_foundNo run with this id exists for your organization.
429rate_limitedToo many requests. Retry after the period indicated in the Retry-After header.