Constaia

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.

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:

EstadoCuándo
VálidoEl tipo coincide y ningún motivo es warning ni error.
No válidoAl menos un motivo tiene severidad error.
RevisarNingú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:

fields.document_number
{
  "value": "12345678Z",
  "confidence": 0.99,
  "validated": true,
  "source": { "page": 1, "bbox": [0.61, 0.12, 0.83, 0.16] }
}
  • value: el dato normalizado (fechas en YYYY-MM-DD).
  • confidence: de 0 a 1.
  • validated: true o false si un validador determinista lo ha comprobado (letra del NIF, MRZ, IBAN…); null si no aplica.
  • source.bbox: rectángulo [x0, y0, x1, y1] normalizado de 0 a 1 en la página de origen. Puede ser null.

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:

  • checks en 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 en verdict.reasons.
  • checks en 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 motivo error con 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ódigoSignificado
low_qualityCalidad baja en general.
blurryImagen desenfocada.
croppedEl documento está recortado.
glareReflejos que tapan datos.
screen_photo_suspectedPosible foto de una pantalla.
photocopy_suspectedPosible fotocopia.
edited_suspectedPosible edición digital.
multiple_documentsHay más de un documento en el fichero.
side_missingFalta una cara.
language_mismatchEl 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_...
ResultadoDeterminista, según el nombre del ficheroAnálisis real con IA
CréditosNunca consume (usage.credits: 0)Consume créditos
livemodefalsetrue
RequisitoNingunoEmail 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

storageQué pasa con el fichero
noneAnálisis síncrono: se procesa en memoria y no se guarda. Asíncrono o lote: se guarda cifrado solo hasta que termina.
temporarySe borra tras ttl_hours (1–720, por defecto 24).
persistentSe 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

En esta página