API reference

One REST lifecycle, five operations.

The Temlavo HTTP API is small on purpose: create, upload, confirm, retrieve, and delete. This page covers the rules every operation shares. Operation details live in the generated reference, which is rendered from the same executable contracts as the OpenAPI artifact.

On this page

Base URL

The API uses an unversioned root with versioned route paths. HTTPS is enforced; clients must not rely on redirects to another hostname.

API base URL
https://api.temlavo.com

Authentication

Every request carries a bearer key. Keys are server-side credentials: never embed them in browser or mobile code.

Code example
Authorization: Bearer inv_live_...

Every response includes X-Request-Id: req_01…; errors repeat it as error.request_id so support can find the exact request without parsing message text.

Idempotency

Send one stable Idempotency-Key header on create and keep its request body byte-stable. A timeout may have created the resource, so retries reuse the exact key and body. Changing the normalized request under the same live key returns idempotency_conflict.

An exact replay may refresh the signed upload capability for the same awaiting document while the reservation is alive. A replay returning 200 awaiting_upload must probe /upload-complete before re-uploading, because source presence is unknown.

The direct-upload boundary

Source bytes never pass through the public API. The create response carries an opaque signed upload capability: follow its method, URL, and all returned headers exactly, adding nothing. Invoice API credentials never reach the upload origin, and redirects are not followed automatically.

Upload completion is explicit: POST …/upload-complete verifies the stored object and admits the document for processing. Supported sources are PDF, JPEG, and PNG through 20 MiB and 20 pages, with the correct declared size and content type.

Rate limits and polling

Throttled requests return 429 with a Retry-After header. Treat Retry-After as a minimum delay everywhere - it is also the polling hint on queued/processing documents. Transient 5xx responses may be retried with the same idempotency semantics.

Statuses

  • awaiting_upload - processing is not admitted yet; the upload reservation is alive.
  • queued - the source passed admission; processing is waiting to begin.
  • processing - active processing underway.
  • completed - usable result; warnings may remain.
  • needs_review - usable result with a blocking review condition.
  • failed - no usable result was produced.

Result-bearing terminal documents include processing.result_expires_at - the deadline after which the retained result returns 410 document_expired.

Errors

Every synchronous error uses one typed envelope:

Code example
{
  "error": {
    "code": "document_expired",
    "message": "The processing result has expired.",
    "request_id": "req_c81e728d",
    "retryable": false
  }
}

Branch on the stable code, HTTP status, and retryable - never on message text. Unknown future codes must be preserved and handled through those stable fields.

The full error catalogue and recovery playbook