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.
MCPThe remote MCP endpoint for submission, results and finalized usage.
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
Rerunning a sample reuses its key, so you get the same document back for seven days. After that, the same file may become a new document and be flagged as a duplicate. Use a new key for each real invoice; never reuse a sample’s key 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
- A usable result with no blocking check. Warnings may remain. Review any warnings, then apply your business rules.
- needs_review
- A usable result with at least one blocking check. Use the checks to find what needs attention in your review step.
- failed
- No usable result was produced. This status is final. 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": "The invoice total does not equal the subtotal less discount, plus shipping, other charges and any tax the subtotal does not already include."
}
]
},
"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": "Supported content types are PDF, JPEG, and PNG.",
"request_id": "req_c81e728d",
"retryable": false,
"docs_url": "https://temlavo.com/docs/errors-recovery#error-unsupported_content_type"
}
}