Quickstart
Run your first invoice.
Start with a synthetic invoice, inspect its structured result, then try one of your own. Use the CLI below, or choose the integration that fits your workflow.
On this page
Choose your tools
The server-side TypeScript path and one-shot CLI.
Raw HTTPThe explicit direct-upload lifecycle for any language.
n8nThe official replay-safe workflow and adaptation guide.
Using n8n? Use the published n8n template to connect your invoice source, then follow the setup guide.
Before you start
- Start a trial. After signup, create an API key in your account console.
- For the CLI, install Node.js 22 or later (includes npm).
- Replace
inv_live_your_keyin the command with your key. Keep it on a server or in your automation runtime. - One upload is one invoice; supporting material is allowed, but multiple distinct invoices are not.
- Supported sources are PDF, JPEG, and PNG through 20 MiB and 20 pages.
- Trial provides 100 processed pages for 30 days with no card.
Run a sample invoice
Choose a scenario and your shell. Each command downloads its synthetic PDF, submits it, and waits for the result. Replace inv_live_your_key with your API key before running. Requires Node.js 22 or later.
clean-us.pdf · Expected sample outcome: completed
curl -fsSL --proto '=https' --proto-redir '=https' \
-o ./clean-us.pdf \
https://temlavo.com/fixtures/v1/clean-us.pdf &&
INVOICE_API_KEY='inv_live_your_key' \
npm exec --yes --package=@temlavo/sdk@1 -- \
temlavo process ./clean-us.pdf \
--idempotency-key temlavo-fixture-v1-cleanThe expected outcomes assume a fresh duplicate namespace with no prior matching document. These are precomputed examples; a live run may differ.
Rerunning a sample and using your own invoices
Exact reruns reuse the fixture-specific key and replay the same logical document while the seven-day idempotency record exists. After that window, identical bytes may become a new document and surface duplicate review. Use a new stable key per real logical invoice; never reuse the demo identity in production.
Understand your result
The command waits for one of the three outcomes below. Read extracted invoice fields and line items under data, and the declared checks under validation.checks.
- completed
- No blocking declared check. Review any warnings, then apply your business rules.
- needs_review
- Invoice data is available. Use the checks to find what needs attention in your review step.
- failed
- No usable invoice data. Read the document's error code to choose your next step.
For a result that needs review, use each check's message and paths to find the affected data. Completed means no blocking declared check was found; it does not independently verify the extracted values.
Understand errors and recoveryTry your own invoice
Choose one PDF, JPEG or PNG containing a single invoice. Use a new, stable idempotency key for that invoice and reuse it only for exact retries. Do not reuse a sample's key for your own document.
- Process a local file with the CLI.
- Add processing to your TypeScript app.
- Connect your invoice source in n8n.
Keep API keys on your server or in your automation runtime. Save the results your workflow needs before processing.result_expires_at. Live runs use your plan's page allowance, including results that need review.
HTTP details, when you need them
The SDK and CLI handle these calls for you. Building an integration in another language? Follow the HTTP guide, or expand the lifecycle below.
How the four API calls and recovery work
Every integration follows these steps. Your file goes directly to private storage without passing through the public API.
1 · Create the document
POST /v1/documents
{
"filename": "invoice.pdf",
"content_type": "application/pdf",
"file_size_bytes": 84213,
"policy": { "required_fields": [], "line_items": "advisory", "checks": { "duplicate_detection": true } }
}Send one stable Idempotency-Key header. A timeout may have created the resource, so retries reuse the exact key and body.
The first run uses the default policy. Before processing your own invoices, see the available review policy settings.
201 Created
{
"id": "doc_9f3kc28d",
"object": "document",
"status": "awaiting_upload",
"document_type": "invoice",
"schema_version": "invoice.v1",
"policy": { "required_fields": [], "line_items": "advisory", "checks": { "duplicate_detection": true } },
"upload": {
"method": "PUT",
"url": "https://<private-storage>/...",
"headers": { "…": "…" },
"expires_at": "2026-08-27T15:30:00.000Z"
}
}2 · Upload the bytes directly
PUT the file to the returned URL with exactly the returned headers. Invoice API credentials never reach the upload origin, and redirects are not followed automatically.
3 · Confirm the upload
POST /v1/documents/{document_id}/upload-complete verifies the stored object and queues processing. Final billing admission happens asynchronously after page inspection. Uploading bytes alone never starts processing.
4 · Poll until a terminal status
GET /v1/documents/{document_id}
{
"status": "needs_review",
"validation": {
"review_required": true,
"checks": [
{
"code": "total_consistency",
"status": "fail",
"message": "Extracted total does not match subtotal plus tax."
}
]
},
"processing": { "result_expires_at": "…" }
}Treat Retry-After as a minimum delay. Terminal statuses are completed, needs_review, and failed. A terminal failed document carries its processing error on the document resource. HTTP request errors use a separate typed envelope, for example:
{
"error": {
"type": "invalid_request",
"code": "unsupported_content_type",
"message": "The supplied content type is not supported.",
"request_id": "req_c81e728d",
"retryable": false
}
}