The one-sentence version
Where v2 had a file or a collection, v3 has a document packet; where v2 polled a nested/results/ path, v3 reads a flat run that returns status and results in one 200.
Path-by-path mapping
Workflows
Uploading documents
v2’s
text form field accepted plain text instead of a file. v3 has no counterpart: upload the text as a small .txt file in the multipart files field.Reading packets and results
Standalone parse
Identifier renames
v2’sfile_id / collection_id / file_collection_id all collapse into one identifier:
A v2 collection is a v3 document packet: the same underlying object under one name. Per-file ids still exist inside a packet, as
files[].id on packet responses, for the rare case where you address one file of a packet with several files. Path parameters are always snake_case: workflow_id, document_packet_id, run_id.
Semantic changes
Results polling: 412 to inline status
v2’s results read returned412 Precondition Failed while the extraction was in flight, so clients had to treat an error status as “not yet”. In v3, GET /v3/runs/{run_id}/ always returns 200 while the run exists:
statustells you where the run is:queued,in_progress,processed,error, orcancelled.resultsisnulluntilstatusreachesprocessed, then carries the results envelope inline.- A run that ended in
errororcancelledstays readable withresults: null.
parse, classifications, splits and extractions sections. See Get run. Only the read path moved.
PUT to PATCH: field identity round-trips
v2 edited workflows withPUT /v2/workflows/{id}/, and the round-trippable graph lived on a separate GET .../definition/. v3 folds both into the workflow resource:
GET /v3/workflows/{workflow_id}/returns the workflow with its graph inline. Every field carries its server-assignedpersistent_id.- Mutate the graph and keep only
{name, description, nodes, edges}, then send it back viaPATCH /v3/workflows/{workflow_id}/. The read-onlyid,created_atandupdated_atare rejected with400VALIDATION_ERROR. - Echo each field’s
persistent_idunchanged, including across renames. The field then keeps its identity: analytics history, ground truth, and quality metrics stay attached. - The PATCH response echoes the stored graph back in the exact GET shape, including new fields with their freshly assigned
persistent_ids. Edit that and PATCH again.
persistent_id only for a genuinely new field, and the server assigns one. A field without persistent_id is always new. Omitting it on an existing field replaces that field and detaches its history. An echoed persistent_id that matches no field in the current version is rejected with 400. v3 has no PUT.
Pagination: offset to keyset
v2 lists used?page= / ?page_size= with a count total. v3 lists return {items, next_cursor}:
- Pass
?cursor=<next_cursor>to fetch the next page; stop whennext_cursorisnull. ?limit=caps at 100. A larger value returns400; the API does not clamp it.- v3 returns no totals or page numbers. If you rendered
countin a UI, switch to cursor-driven “load more” semantics.
Idempotency (new)
The packet-creating and run-triggering POSTs accept anIdempotency-Key header. Retrying with the same key replays the original response instead of creating a duplicate packet or billing a second extraction. v2 had no equivalent. Delete any retry-dedup logic you built client-side. See Idempotency.
Version header
Every/v3/ response is stamped X-API-Version: 3.0.0. If you tag metrics by API version, this header is the reliable source.
What did not change
- Authentication: the same API keys and the same
Authorization: Bearerheader. - Error envelope: the same
{error, detail, error_code, retryable, request_id}shape. See Errors. - Results envelope: the same
parse,classifications,splitsandextractionssections. See Get run. - Rate limiting: the same two-tier limits and
x-ratelimit-*headers. - The typed-graph workflow body:
POST /v3/workflows/accepts the same{name, description, nodes, edges}shape asPOST /v2/workflows/.
Migration checklist
- Swap base paths
/v2/→/v3/per the tables above; renamefile_id/collection_idvariables todocument_packet_id. - Replace
/results/polling (412-tolerant) withGET /v3/runs/{run_id}/polling onstatus. - Replace
PUTworkflow edits with GET → mutate →PATCH, preservingpersistent_ids. - Replace
page/page_sizepagination withcursor/limit; drop any use ofcount. - Add an
Idempotency-Keyto upload and run-trigger POSTs if you retry on timeouts.

