Anyformat, Schema, WorkflowBuilder and Result.
Installation
Requires Node 18+.Authentication
Pass the API key to theAnyformat constructor, or read it from the environment.
baseUrl to run against a non-production deploy. See Authentication to mint an API key.
Basic usage
The full flow builds a workflow with the fluent builder, submits a document, and awaits the typed result.create() returns a Workflow handle whose run(file) reuses the existing workflow id. Processing N documents through one workflow therefore costs one POST /v2/workflows/ plus N POST /v2/workflows/{id}/run/, not N create-and-run pairs.
wait options
wait defaults to a 300-second overall timeout and a 3-second poll interval. Override either one:
wait throws SDKTimeout when the overall deadline expires before the run completes. The internal poll handles a 412, meaning still processing, on its own.
Builder methods
Every node type in the typed graph has a fluent method.parse is required. The rest are optional, and chain into any topology the API allows.
The
Workflow handle returned by .create() has one method:
Workflow.run returns a Run. Run.wait(opts?) returns a Result once processing finishes.
Filenames are unique within a workflow. By default, an upload whose filename already exists is rejected with
409 and the error code FILENAME_CONFLICT. Pass { onConflict: "rename" } to .run(...), .upload(...) or .uploadFromUrls(...) to rename instead, so invoice.pdf becomes invoice (1).pdf.Smart lookup
A smart-lookup field is resolved by matching the document against a reference file, a CSV catalog, instead of being read off the page. Flag the field with{ source: "smart_lookup" }, and pass the reference file to .extract(..., { lookupFiles: [...] }). The SDK reads each path and uploads it with the workflow. See Smart Lookup for how matching works and for the Studio equivalent. In the example below, the model reads vendor_name, then resolves the canonical vendor_id from a vendor catalog.
Schema.* factory accepts { source: "smart_lookup" }. The looked-up field comes back through result.field(...) alongside the others, with no separate section. An extract carrying a lookup field but no lookupFiles is rejected with 400. The lookup overwrites a smart-lookup field. Use { source: "lookup_if_missing" } to extract the field from the document too, and let the lookup fill only what extraction missed.
Managing workflows
The client also lists and deletes workflows:Reading results
Error handling
The SDK exports typed error classes:EXTRACTION_FAILED and RATE_LIMITED. The APIError.body field holds the parsed JSON body the server returned.
Webhooks
Anyformat does not expose the webhook endpoints yet. Until it does, register and delete webhooks with fetch or with the generated low-level client:
Links
- npm:
npm install @anyformat/sdk - Python SDK: the same fluent shape in Python
- Coding assistant: drive anyformat from your editor with Claude

