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

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_key in 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

Terminal
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-clean

The 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 recovery

Try 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.

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

Code example
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.

Create response · excerpt
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

Result response · excerpt
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:

Code example
{
  "error": {
    "type": "invalid_request",
    "code": "unsupported_content_type",
    "message": "The supplied content type is not supported.",
    "request_id": "req_c81e728d",
    "retryable": false
  }
}
Read the HTTP guide, including retries and recovery