Constaia

Key concepts

Document types, expect, verdicts, reasons, fields, checks, warnings, test and live modes, credits, storage, webhooks and idempotency in Constaia.

Cette page n'est pas encore traduite dans votre langue. Voici la version anglaise.

This page sums up each API concept in a few lines. Every section links to the detailed reference.

Document type and catalogue

Each document is classified into a type from the catalogue: es_dni, es_nie, passport, eu_id_card, medical_certificate_sport, payment_receipt, invoice… If it fits none, the type is generic. The detected type comes in document.type, with its label (document.label), confidence, side (side) and country.

The catalogue grows over time, so don't copy the list into your code: look it up in the document catalogue or with GET /v1/document-types (public, no key). Each type lists its fields, validators and supported checks. See Document types.

expect

expect tells Constaia which document you expect. It can be one type ("es_dni") or a list of up to 20 (["es_dni", "es_nie", "passport"]). Without expect you get classification and data, but verdict is null. A type that doesn't exist in the catalogue returns 422 invalid_parameter with param: "options.expect".

Verdict and reasons

With expect, every analysis has verdict.status:

StatusWhen
VálidoThe type matches and no reason is warning or error.
No válidoAt least one reason has severity error.
RevisarNo error, but at least one warning.

verdict.reasons is the list of reasons. Each has a stable code (type_match, not_expired, holder, max_age_days, low_quality…), a severity (info, warning or error) and a message localised according to language. The same code appears with different severities depending on the outcome: a valid ID card gives not_expired with info; an expired one, not_expired with error. Code against code and severity, never against the text. See Verdicts and reasons.

Fields

fields holds the extracted data. Each field is an object:

fields.document_number
{
  "value": "12345678Z",
  "confidence": 0.99,
  "validated": true,
  "source": { "page": 1, "bbox": [0.61, 0.12, 0.83, 0.16] }
}
  • value: the normalised value (dates as YYYY-MM-DD).
  • confidence: from 0 to 1.
  • validated: true or false if a deterministic validator checked it (NIF check letter, MRZ, IBAN…); null if none applies.
  • source.bbox: rectangle [x0, y0, x1, y1] normalised 0 to 1 on the source page. May be null.

With extract you can turn extraction off (false) or pass your own JSON Schema: the fields returned are then those of your schema. See Analyze.

Checks and reasons

Two things have similar names:

  • checks in the options: business rules you ask for (not_expired, max_age_days, min_age_years, holder, require_signature, expected_amount, expected_iban…). Their result appears as reasons in verdict.reasons.
  • checks in the response: deterministic validations Constaia always runs when the type allows it (nif_check_digit, mrz_checksums, mrz_matches_visual, iban_checksum, invoice_totals, csv_format, date_consistency). Each one is { code, passed, message }. If one fails, it also appears as an error reason with the same code.

not_expired is on by default for types with an expiry date; send "not_expired": false to turn it off. Checks only apply if the detected type has the relevant field. See Checks.

Warnings

warnings is a list of signals about the image or document: low_quality, blurry, cropped, glare, screen_photo_suspected, photocopy_suspected, edited_suspected, multiple_documents, side_missing, language_mismatch. Quality ones produce the low_quality reason with severity warning, which leads to review.

They are signals, not proof of fraud. Constaia does no biometrics or face matching.

CodeSignification
low_qualityQualité globalement faible.
blurryImage floue.
croppedLe document est rogné.
glareDes reflets masquent des données.
screen_photo_suspectedPhoto d'écran possible.
photocopy_suspectedPhotocopie possible.
edited_suspectedRetouche numérique possible.
multiple_documentsPlusieurs documents dans le fichier.
side_missingUne face manque.
language_mismatchLa langue n'est pas celle attendue pour ce type.

Les warnings sont des indices, pas une preuve d'authenticité.

Test mode and live mode

ck_test_...ck_live_...
ResultDeterministic, based on the file nameReal AI analysis
CreditsNever consumed (usage.credits: 0)Consumes credits
livemodefalsetrue
RequirementNoneVerified email

Analyses, listings and webhooks are separate per mode. See Test mode and Authentication.

Credits

1 credit = 1 analysis of up to 2 pages; every 2 extra pages, 1 more credit (ceil(pages / 2), minimum 1). classify costs 0.2 credits. Exports are included. Failures on our side, quality rejections before OCR and test mode are not charged. The free plan gives 150 credits per month; after that, packs. Each analysis's consumption is in usage. See Credits and billing and Pricing.

Storage

storageWhat happens to the file
noneSynchronous analysis: processed in memory, never stored. Async or batch: stored encrypted only until it finishes.
temporaryDeleted after ttl_hours (1–720, default 24).
persistentKept until DELETE /v1/analyses/{id}.

If you don't set it, your account default (configurable in the dashboard) or none is used. With keep_results: false results are not stored either. storage.file_deleted_at tells you when the file was deleted. See Storage and privacy.

Processing profile

With processing you choose which AI providers process each document: sovereign (only providers headquartered and operated in the EU) or standard (also Claude on AWS Bedrock or Gemini on Vertex AI, in EU regions). If you don't set it, your account's profile is used. Every analysis returns the processing object with the profile, region and providers that handled it. See Data residency.

Synchronous and asynchronous

POST /v1/analyze waits up to 30 seconds. If it finishes, it responds 200 with the full analysis. If not, it responds 202 with status: "queued" or "processing", and the result arrives by webhook or by polling GET /v1/analyses/{id}.

With async: true the response is always an immediate 202. Use it for long PDFs (up to 200 pages async; 30 sync) or when you don't want to block the request. Batches are always asynchronous.

Webhooks

You register an HTTPS URL with POST /v1/webhook-endpoints and pick events: analysis.completed, analysis.failed, analysis.review_required, batch.completed, credits.low or *. Each delivery is signed following Standard Webhooks (webhook-id, webhook-timestamp, webhook-signature) and retried for about 3 days. Deduplicate on webhook-id. See Webhooks.

Idempotency

Send the Idempotency-Key header on any POST. If you repeat the same key with the same content within 24 hours, you get the stored response (with Idempotent-Replayed: true) and are not charged twice. The JavaScript and PHP SDKs generate a key automatically on every POST. See Idempotency.

Metadata

metadata is a string-to-string object (up to 20 keys, key up to 40 characters, value up to 500) stored with the analysis and returned in the response and in webhooks. Use it to link your IDs ({ "registration_id": "123" }) and filter: GET /v1/analyses?metadata[registration_id]=123. See Analyses.

Next steps

Sur cette page