Conceptos clave
Tipos de documento, expect, veredictos, motivos, campos, checks, warnings, modos test y live, créditos, almacenamiento, webhooks e idempotencia en Constaia.
Esta página resume en pocas líneas cada concepto de la API. Cada sección enlaza a la referencia detallada.
Tipo de documento y catálogo
Cada documento se clasifica en un tipo del catálogo: es_dni, es_nie, passport, eu_id_card,
medical_certificate_sport, payment_receipt, invoice… Si no encaja en ninguno, el tipo es generic. El
tipo detectado llega en document.type, con su etiqueta (document.label), la confianza, la cara (side) y el
país.
El catálogo crece con el tiempo, así que no copies la lista en tu código: consúltala en el
catálogo de documentos o con GET /v1/document-types (público, sin clave). Cada tipo indica sus
campos, validadores y los checks que admite. Ver Tipos de documento.
expect
expect le dice a Constaia qué documento esperas. Puede ser un tipo ("es_dni") o una lista de hasta 20
(["es_dni", "es_nie", "passport"]). Sin expect recibes clasificación y datos, pero verdict es null.
Un tipo que no existe en el catálogo devuelve 422 invalid_parameter con param: "options.expect".
Veredicto y motivos
Con expect, cada análisis trae verdict.status:
| Estado | Cuándo |
|---|---|
| Válido | El tipo coincide y ningún motivo es warning ni error. |
| No válido | Al menos un motivo tiene severidad error. |
| Revisar | Ningún error, pero al menos un warning. |
verdict.reasons es la lista de motivos. Cada uno tiene un code estable (type_match, not_expired,
holder, max_age_days, low_quality…), una severity (info, warning o error) y un message
traducido según language. El mismo código aparece con distinta severidad según el resultado: un DNI vigente
da not_expired con info; uno caducado, not_expired con error. Programa contra code y severity,
nunca contra el texto. Ver Veredictos y motivos.
Campos
fields contiene los datos extraídos. Cada campo es un objeto:
{
"value": "12345678Z",
"confidence": 0.99,
"validated": true,
"source": { "page": 1, "bbox": [0.61, 0.12, 0.83, 0.16] }
}value: el dato normalizado (fechas enYYYY-MM-DD).confidence: de 0 a 1.validated:trueofalsesi un validador determinista lo ha comprobado (letra del NIF, MRZ, IBAN…);nullsi no aplica.source.bbox: rectángulo[x0, y0, x1, y1]normalizado de 0 a 1 en la página de origen. Puede sernull.
Con extract puedes desactivar la extracción (false) o pasar tu propio JSON Schema: entonces los campos
devueltos son los de tu esquema. Ver Analizar.
Checks y motivos
Hay dos cosas que se llaman parecido:
checksen las opciones: reglas de negocio que tú pides (not_expired,max_age_days,min_age_years,holder,require_signature,expected_amount,expected_iban…). Su resultado aparece como motivos enverdict.reasons.checksen la respuesta: validaciones deterministas que Constaia ejecuta siempre que el tipo lo permite (nif_check_digit,mrz_checksums,mrz_matches_visual,iban_checksum,invoice_totals,csv_format,date_consistency). Cada una es{ code, passed, message }. Si una falla, también aparece como motivoerrorcon el mismo código.
not_expired está activado por defecto en los tipos con caducidad; envía "not_expired": false para
desactivarlo. Los checks solo se aplican si el tipo detectado tiene el campo correspondiente. Ver
Checks.
Warnings
warnings es una lista de señales sobre la imagen o el documento: low_quality, blurry, cropped, glare,
screen_photo_suspected, photocopy_suspected, edited_suspected, multiple_documents, side_missing,
language_mismatch. Las de calidad generan el motivo low_quality con severidad warning, lo que lleva a
review.
Son indicios, no prueba de fraude. Constaia no hace biometría ni comparación facial.
| Código | Significado |
|---|---|
low_quality | Calidad baja en general. |
blurry | Imagen desenfocada. |
cropped | El documento está recortado. |
glare | Reflejos que tapan datos. |
screen_photo_suspected | Posible foto de una pantalla. |
photocopy_suspected | Posible fotocopia. |
edited_suspected | Posible edición digital. |
multiple_documents | Hay más de un documento en el fichero. |
side_missing | Falta una cara. |
language_mismatch | El idioma no es el esperado para el tipo. |
Los warnings son indicios, no prueba de autenticidad.
Modo test y modo live
ck_test_... | ck_live_... | |
|---|---|---|
| Resultado | Determinista, según el nombre del fichero | Análisis real con IA |
| Créditos | Nunca consume (usage.credits: 0) | Consume créditos |
livemode | false | true |
| Requisito | Ninguno | Email verificado |
Los análisis, listados y webhooks de cada modo están separados. Ver Modo test y Autenticación.
Créditos
1 crédito = 1 análisis de hasta 2 páginas; cada 2 páginas más, 1 crédito adicional (ceil(páginas / 2), mínimo 1).
classify cuesta 0,2 créditos. Las exportaciones están incluidas. No se cobran los fallos de nuestro lado, los
rechazos por calidad antes del OCR ni el modo test. El plan gratuito da 150 créditos al mes; después, packs.
El consumo de cada análisis está en usage. Ver Créditos y facturación y
Precios.
Almacenamiento
storage | Qué pasa con el fichero |
|---|---|
none | Análisis síncrono: se procesa en memoria y no se guarda. Asíncrono o lote: se guarda cifrado solo hasta que termina. |
temporary | Se borra tras ttl_hours (1–720, por defecto 24). |
persistent | Se conserva hasta DELETE /v1/analyses/{id}. |
Si no lo indicas se usa el valor por defecto de tu cuenta (configurable en el panel) o none. Con
keep_results: false tampoco se guardan los resultados. storage.file_deleted_at indica cuándo se borró el
fichero. Ver Almacenamiento y privacidad.
Perfil de procesamiento
Con processing eliges qué proveedores de IA procesan cada documento: sovereign (solo proveedores con sede y
operación en la UE) o standard (además, Claude en AWS Bedrock o Gemini en Vertex AI, en regiones de la UE). Si no lo
indicas se usa el de tu cuenta. Cada análisis devuelve el objeto processing con el perfil, la región y los
proveedores que lo trataron. Ver Residencia de datos.
Síncrono y asíncrono
POST /v1/analyze espera hasta 30 segundos. Si termina, responde 200 con el análisis completo. Si no,
responde 202 con status: "queued" o "processing", y el resultado llega por webhook o consultando
GET /v1/analyses/{id}.
Con async: true la respuesta es siempre 202 inmediatamente. Úsalo con PDF largos (hasta 200 páginas en
asíncrono; 30 en síncrono) o cuando no quieras bloquear la petición. Los lotes son
siempre asíncronos.
Webhooks
Registras una URL HTTPS con POST /v1/webhook-endpoints y eliges eventos: analysis.completed,
analysis.failed, analysis.review_required, batch.completed, credits.low o *. Cada envío va firmado
según Standard Webhooks (webhook-id, webhook-timestamp, webhook-signature) y se reintenta durante unos
3 días. Deduplica por webhook-id. Ver Webhooks.
Idempotencia
Envía la cabecera Idempotency-Key en cualquier POST. Si repites la misma clave con el mismo contenido en 24 horas,
recibes la respuesta guardada (con Idempotent-Replayed: true) y no se cobra dos veces. Los SDKs de JavaScript y
PHP generan una clave automáticamente en cada POST. Ver Idempotencia.
Metadata
metadata es un objeto de texto a texto (hasta 20 claves, clave de hasta 40 caracteres, valor de hasta 500) que se
guarda con el análisis y vuelve en la respuesta y en los webhooks. Úsalo para enlazar con tus IDs
({ "registration_id": "123" }) y filtrar: GET /v1/analyses?metadata[registration_id]=123. Ver
Análisis.
Siguientes pasos
Inicio rápido
Valida tu primer DNI con la API de Constaia en 5 minutos usando una clave de prueba gratuita, con curl, JavaScript, PHP o Python.
Qué usar
Cuándo usar analyze, classify, lotes, el widget, el servidor MCP o una herramienta no-code en Constaia, con costes, latencia y límites de cada opción.