Constaia
Endpoints

POST /v1/batches

Reference for POST /v1/batches: analyse up to 100 documents in one asynchronous call, with common or per-document options and a combined export.

A batch groups up to 100 documents in a single request. It is always asynchronous: the API answers 202 immediately, each document becomes a normal analysis (an_…) with batch_id, and when they have all finished you receive a single batch.completed webhook. Optionally, a combined file (for example, a spreadsheet with one row per document).

Use it for bulk loads: the month's invoices, the receipts of a registration, the certificates of a whole team. For a single document use POST /v1/analyze. Practical guide in Bulk batches.

Method and routeWhat it does
POST /v1/batchesCreates a batch. Always 202.
GET /v1/batches/{id}Retrieves the batch with its counters and exports.

Creating a batch

There are two ways to send it.

multipart/form-data: files

FieldDescription
files[]One file per field; repeat the field for each document. files is also accepted.
optionsJSON with the options common to every document.
curl https://api.constaia.com/v1/batches \
  -H "Authorization: Bearer $CONSTAIA_API_KEY" \
  -F "files[]=@invoice_001.pdf" \
  -F "files[]=@invoice_002.pdf" \
  -F "files[]=@invoice_003.pdf" \
  -F 'options={"expect":"invoice","export":["xlsx"],"metadata":{"month":"2026-09"}}'

With multipart every document shares the same options. The -F expect=… shortcut of analyze does not exist for batches: use options.

application/json: URLs or base64, with per-document options

Body
{
  "items": [
    { "file_url": "https://example.com/receipts/123.pdf",
      "options": { "checks": { "expected_amount": 45, "expected_reference": "INSCRIPCION 123" },
                   "metadata": { "registration_id": "123" } } },
    { "file_url": "https://example.com/receipts/124.pdf",
      "options": { "checks": { "expected_amount": 60, "expected_reference": "INSCRIPCION 124" },
                   "metadata": { "registration_id": "124" } } },
    { "file_base64": "JVBERi0xLjcK…", "filename": "125.pdf" }
  ],
  "options": { "expect": "payment_receipt", "export": ["xlsx"], "metadata": { "event": "42" } }
}

Each item carries file_url or file_base64 + filename, and optionally its own options. URLs are downloaded when the request arrives, with the same rules as analyze (https, 20 MB, 15 s): if one fails, the whole request returns the error and nothing is created.

Common and per-document options

The options are the same as in analyze, split like this:

OptionScope
exportBatch: when it finishes, a single combined file is generated with one row per document. Individual documents do not generate their own export.
metadataBatch: returned in the batch object. It is not copied to each analysis. To tag each document, put metadata in the item's options.
The rest (expect, extract, checks, storage, ttl_hours, keep_results, language)Per document: common options apply to every item, and the item's options override them.

Options are merged key by key, and so is checks: the item's checks are added to the common ones and, when both set the same key, the item wins. In the example above, each receipt inherits expect: "payment_receipt" and carries its own expected_amount. If the common options have checks: { "max_age_days": 30 } and an item has checks: { "expected_amount": 45 }, that item is validated with both. async has no effect: batch documents are always processed in the background.

Limits and credits

  • Between 1 and 100 documents per batch. More than 100 returns 400 batch_too_large and none returns 400 empty_batch, both in multipart and with JSON items.
  • Same per-file limits as analyze: 20 MB, JPEG/PNG/WEBP/HEIC/PDF, and up to 200 pages per PDF (batches are always asynchronous).
  • With a live key, before creating anything the API checks that you have at least 1 credit per document; otherwise 402 insufficient_credits. The real cost of each document is that of a normal analysis (1 credit per 2 pages). Test mode is free.
  • The batch is atomic. Before anything is created, every file_url is downloaded and every file is validated (format, size, pages). If one fails, the request returns that document's error (for format, size or page errors, with param: "items[i]", zero-based, and the file name in the message) and no analysis is created or charged. Fix that document and resend the whole batch.
  • Supports Idempotency-Key to retry without creating the batch twice. See Idempotency.

The batch object

202 Accepted
{
  "id": "bat_01J9Z8Q3K4M5N6P7Q8R9S0T1V2",
  "object": "batch",
  "status": "processing",
  "livemode": false,
  "total": 3,
  "counts": { "queued": 3, "processing": 0, "completed": 0, "failed": 0, "valid": 0, "invalid": 0, "review": 0 },
  "analyses": ["an_01J9Z8Q3K4M5N6P7Q8R9S0T1V3", "an_01J9Z8Q3K4M5N6P7Q8R9S0T1V4", "an_01J9Z8Q3K4M5N6P7Q8R9S0T1V5"],
  "exports": {},
  "metadata": { "month": "2026-09" },
  "created_at": "2026-09-29T10:00:00.000Z",
  "completed_at": null
}
FieldDescription
idId with prefix bat_.
objectAlways "batch".
statusprocessing while any document is pending; completed when all have finished (successfully or not).
livemodeMode of the key that created it.
totalNumber of documents.
countsBy status (queued, processing, completed, failed) and by verdict (valid, invalid, review). Verdict counters only count documents with expect.
analysesIds of the batch's analyses, in creation order.
exportsFormat → signed URL of the combined file. Appears when the batch completes and expires after 24 h.
metadataThe batch's common metadata.
created_at, completed_atISO 8601 dates; completed_at is null until it finishes.

Retrieving a batch

curl https://api.constaia.com/v1/batches/bat_01J9Z8Q3K4M5N6P7Q8R9S0T1V2 \
  -H "Authorization: Bearer $CONSTAIA_API_KEY"

Returns the same object with up-to-date counters. For each document's detail, walk analyses with GET /v1/analyses/{id} or filter the list by the metadata you set on each item.

Batch webhooks

EventWhen
analysis.review_requiredA batch document finishes with a review verdict.
analysis.failedA batch document fails.
batch.completedThey have all finished. data is the batch object, with exports if you requested export.

Batch documents do not emit analysis.completed, so you do not get a hundred notifications. When batch.completed arrives, read each analysis or download the combined file. Details and signature verification in Webhooks.

Examples

curl https://api.constaia.com/v1/batches \
  -H "Authorization: Bearer $CONSTAIA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: invoices-2026-09" \
  -d '{
    "items": [
      { "file_url": "https://example.com/invoices/2026-0041.pdf" },
      { "file_url": "https://example.com/invoices/2026-0042.pdf" }
    ],
    "options": { "expect": "invoice", "export": ["xlsx"], "metadata": { "month": "2026-09" } }
  }'

To see a batch's full flow without spending credits, use a ck_test_ key and name the files as in Test mode (for example, invoice_001.pdf returns a valid invoice).

Next steps

On this page