Let's Build: AI invoice parser with Transloadit
Turn a PDF invoice into a local JSON file containing its vendor, invoice number, currency, and amounts. This example uploads your document to Transloadit and an AI provider, validates the returned field types, and saves the result for you to review against the original invoice.
What we’re building
The example script accepts a nonempty PDF or DOCX file of up to 20 MiB. PDFs go directly to 🤖 /ai/chat; DOCX files first pass through 🤖 /document/convert to become PDFs. Other input extensions are rejected by this example.
This is a local extraction tutorial. A completed Assembly and schema-valid JSON do not establish that an amount was read correctly. Review the output before using it for accounting or payments; the schema does not return confidence scores.
Schema first (zod)
The downloadable program exports its Zod schema. After following the download layout below, you can import it in your own TypeScript code instead of maintaining a second field list:
import { zodToJsonSchema } from 'zod-to-json-schema'
import { invoiceSchema } from './invoice-parser/run.ts'
const invoiceJsonSchema = zodToJsonSchema(invoiceSchema)
Fields include vendor details, invoice and due dates, currency, subtotal, tax, total, line items, payment terms, and a purchase order. They are optional so the model can omit unknown values. The runner rejects malformed JSON, invalid field types, and an object with no recognized fields. A plausible but incorrect total can still pass those checks.
Pipeline overview
PDF → /ai/chat → JSON download → local validation → result.json
DOCX → /document/convert (PDF) → /ai/chat → JSON download → local validation → result.json
The program explicitly selects anthropic/claude-sonnet-4-6, a PDF-capable model supported by
/ai/chat. It downloads the answer from the result URL and saves the validated data locally, so you
can inspect the file after that temporary URL expires.
Assembly snippet
The exported recipe supplies the complete Assembly Instructions. This snippet builds the instructions without submitting a request:
import { example } from './invoice-parser/run.ts'
const instructions = {
steps: example.steps({ test_credentials: true }),
}
The extraction Step uses format: 'json', a serialized JSON Schema, and result: true. The CLI
handles the upload, completion check, result download, and local validation. Selecting
test_credentials: true uses billed Transloadit-provided AI credentials; it does not make
processing free.
Try the example app
Use an empty directory outside an existing Node project. Install Node.js and cURL, and install
Corepack separately. The tested runtime is
Node.js 26.12.1; use a maintained Node 26 release
when adapting the example. The setup instructions use
Yarn 4.12.0 to install @transloadit/node 4.14.0, Zod 3.25.76, and zod-to-json-schema 3.25.2. These pins
reproduce the downloadable example’s SDK and schema-converter combination; they are not
latest-version claims or a requirement to downgrade an existing application.
Follow that README’s installation and access configuration first, running its commands one at a time.
Download both invoice-parser/run.ts and shared/runtime.ts, keeping their relative layout. Run the documented
--help check before uploading anything. If installation or a download fails, stop and resolve it
before running the parser.
Export your Workspace Auth Key and Secret as TRANSLOADIT_AUTH_KEY and TRANSLOADIT_AUTH_SECRET in
the same shell. The script reads those environment variables; it does not load an environment file
or create credentials. Keep secrets out of source control and browser code.
With TRANSLOADIT_AI_CREDENTIALS unset, place an invoice you are allowed to upload at invoice.pdf.
Choose a destination that does not exist, then run:
node invoice-parser/run.ts --input ./invoice.pdf --output ./result.json --test-credentials
This command explicitly authorizes billed AI test credentials as well as Transloadit processing.
To use your own Anthropic key instead, configure an AI Credential in the Console, export its existing
name as TRANSLOADIT_AI_CREDENTIALS, and omit --test-credentials. Select exactly one provider
credential mode. Check pricing before processing a collection of invoices.
The runner leaves the input unchanged and refuses an existing output before submitting an Assembly. Use a new filename for another run. Its tutorial limits are 20 MiB for input and downloaded output, five minutes for processing, and 30 seconds for the result download. These are not product limits. If it fails after printing an Assembly ID, inspect that Assembly in the Console before retrying: a timeout or interruption does not prove remote processing stopped, and a failed run can still be billed. The runner does not automatically retry an Assembly.
Example inputs
Start with a synthetic invoice whose fields you can check independently. For example, an invoice
from Sample Workshop Ltd numbered INV-2026-0042, with two bicycle repairs at USD 100 each and
USD 20 tax, should yield at least these values:
{
"vendor_name": "Sample Workshop Ltd",
"invoice_number": "INV-2026-0042",
"currency": "USD",
"subtotal": 200,
"tax": 20,
"total": 220
}
After a successful run, open result.json in a text editor. Compare its vendor, invoice number,
currency, line items, and amounts with your actual input; different invoices should produce different
data. A missing field needs review even when the file was saved successfully. Keep the result private
when it contains business or personal information.
Next steps
Before storing results in your database, decide which fields your application requires and route missing or mismatched values to human review. Keep currency conversion separate from extraction: the returned currency and amounts describe the source invoice, not normalized accounting entries.

