Skip to main content

Chart Extraction Overview

Read the data points of charts on a PDF page into a table of values with the /v1/chart-to-data API: stored inputs, queued runs, and sealed, verified results.

Every endpoint on this page answers 404 in a workspace that has not added the Chart Extraction app (catalog slug chart-to-data). Add it from the Apps catalog or with POST /v1/apps and slug chart-to-data; GET /v1/apps lists the apps a workspace has added.

The Chart Extraction API reads the data points of the charts on one PDF page into a table of values. A deterministic engine turns stored, source-bound inputs (the request, delivery metadata, printed ticks, companion scales and curve expectations) into one result per requested chart: the customer-facing values, the chart contract, and a coverage report. No model is called, so the same file, page, inputs and engine version produce the same result. The endpoints belong to the Chart Extraction app (catalog slug chart-to-data); a workspace uses them after adding the app, and GET /v1/apps lists a workspace's apps by slug.

Inputs are bound to a file by the SHA-256 of its bytes, not by document id: the same PDF uploaded as two documents shares its inputs, and a changed file needs new inputs. Inputs are append-only. Each store for the same file page creates the next version, and a run keeps the inputs version it was queued with, so rerunning a row is reproducible. A page that has no stored inputs gets inputs derived from the page's own bars and category axes when the run executes; if none can be derived, the run fails with the code INPUTS_MISSING.

Work is queued and processed by a worker. GET /v1/chart-to-data/pdfs/{documentId}/charts queues a scan of a file the first time it is requested, and POST /v1/chart-to-data/runs queues a run; both answer at once with stored state, and the client polls until the status is done or failed. Statuses are queued, running, done and failed. A run that has to wait for a worker stays queued, and a lost job is picked up again by a recovery sweep.

Every stored result carries an integrity seal, a SHA-256 over the content and the identity of the run (workspace, document, chart, inputs and their digest, engine version). GET /v1/chart-to-data/runs/{id} verifies each record against its seal, its run and its bound inputs, and withholds values, chart and coverage from any record that fails, with a withheld_reason. A result is therefore either verified evidence of what the engine read from exactly those bytes, or visibly marked as not.

Authentication and Scopes

Authenticate with Authorization: Bearer $TALONIC_API_KEY. The GET routes need the read scope. The two writes, POST /v1/chart-to-data/inputs and POST /v1/chart-to-data/runs, need the write scope and the key's person to be a member or above in the workspace; a key minted by a viewer, or a key that belongs to no person, is refused with 403. The surface needs a workspace-scoped credential.

Worked Example: From PDF to Verified Values

cURL: 1. Find the file and its charts

curl "https://api.talonic.com/v1/chart-to-data/pdfs" \
  -H "Authorization: Bearer $TALONIC_API_KEY"

curl "https://api.talonic.com/v1/chart-to-data/pdfs/$DOCUMENT_ID/charts" \
  -H "Authorization: Bearer $TALONIC_API_KEY"

Poll the charts route until its status is done. Then queue a run for a page that holds charts, and poll the run. The run returns in status queued; the results appear when it is done.

cURL: 2. Queue a run and read the result

curl -X POST "https://api.talonic.com/v1/chart-to-data/runs" \
  -H "Authorization: Bearer $TALONIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"document_id": "'$DOCUMENT_ID'", "page_number": 4}'

curl "https://api.talonic.com/v1/chart-to-data/runs/$RUN_ID" \
  -H "Authorization: Bearer $TALONIC_API_KEY"
Do not use a record's values unless its integrity is VERIFIED and withheld_reason is absent. The API already removes values, chart and coverage from a record that fails verification, but a client that caches an earlier response should re-read the run before relying on it.

Frequently asked questions

Does Chart Extraction call a language model?+
No. A deterministic engine reads the PDF page with the stored inputs and produces the values, the chart contract and the coverage report. The same bytes, inputs and engine version give the same result, which is why a result can be sealed and verified on read.
Why are inputs keyed by file hash and not by document id?+
The same PDF uploaded twice is the same evidence. Binding inputs to the SHA-256 of the bytes lets both documents share them, and it makes a changed file visible: a run recomputes the hash of the bytes it reads and fails with SOURCE_CHANGED if it differs from the run's and the inputs' hash.
Why does my POST /runs return before any values exist?+
Queuing never opens the file. The run is stored as queued and a worker processes it, so whether the page yields inputs is known only at execution. Poll GET /v1/chart-to-data/runs/{id} until the status is done or failed.
What happens when one chart on a page cannot be read?+
Per-chart failures do not fail the run. The record for that chart comes back with an engine status such as EXECUTION_FAILURE and a message, and the other charts of the page are returned normally.