Revisiones
Referencia de la revisión humana por API. Lista los análisis pendientes con GET /v1/reviews, descarga el original con GET /v1/analyses/{id}/file y decide con POST /v1/analyses/{id}/review.
Cuando un análisis necesita que lo mire una persona, puedes resolverlo desde el panel o desde tu propio backend con estos endpoints. Guía paso a paso en Revisión humana desde tu backend.
| Método y ruta | Qué hace |
|---|---|
GET /v1/reviews | Lista los análisis pendientes de revisión (o ya decididos). |
GET /v1/analyses/{id}/file | Descarga el documento original, si sigue guardado. |
POST /v1/analyses/{id}/review | Aprueba o rechaza un análisis pendiente de revisión. |
Solo funcionan con una clave secreta (ck_test_… o ck_live_…). Con una clave publicable (pk_…) la respuesta es
403 publishable_key_not_allowed.
Cuándo un análisis queda pendiente de revisión
Un análisis con veredicto entra en la cola de revisión (review.status: "pending") cuando:
- su veredicto es
review; - su veredicto es
invalidy la plantilla usada pide revisión humana para los inválidos; - su veredicto es
validy la plantilla usada no aprueba solos los válidos.
Mientras está pendiente, verdict.final_status es null. Al decidir pasa a valid (aprobado) o invalid
(rechazado). Sin expect no hay veredicto y el análisis no se puede revisar (409 not_reviewable).
El objeto review del análisis:
"review": {
"status": "pending",
"decision": null,
"assignee": null,
"reviewed_by": null,
"reviewed_at": null,
"reason": null,
"note": null
}| Campo | Descripción |
|---|---|
status | pending, approved o rejected. |
decision | approve, reject o null si aún no se ha decidido. |
assignee | Persona del equipo a la que se asignó en el panel, o null. |
reviewed_by | Quién decidió: el id de un usuario del panel o, si se decidió por API, el id de la clave (key_…). |
reviewed_at | Cuándo se decidió. |
reason | Motivo breve de la decisión (hasta 200 caracteres). |
note | Nota interna (hasta 2000 caracteres). |
review es null en los análisis que no necesitan revisión.
Listar revisiones
GET /v1/reviews| Parámetro | Tipo | Descripción |
|---|---|---|
status | pending | decided | approved | rejected | all | Por defecto pending. decided son los aprobados y los rechazados. |
type | string | Filtra por tipo de documento, p. ej. es_dni. |
template | string | Filtra por plantilla (tpl_…). |
metadata[clave] | string | Filtra por un valor de metadata. Repetible: deben coincidir todas. |
limit | entero 1–100 | Elementos por página. Por defecto 10. |
starting_after | string | Id (an_…) del último análisis de la página anterior. |
Solo incluye análisis del modo de tu clave (test o live). Orden:
pending: los más antiguos primero, como una cola: atiende primero lo que lleva más tiempo esperando.- El resto: los más recientes primero.
{
"object": "list",
"data": [
{
"id": "an_01J9Z8Q3K4M5N6P7Q8R9S0T1V3",
"object": "analysis",
"status": "completed",
"verdict": { "status": "review", "final_status": null, "…": "…" },
"review": { "status": "pending", "decision": null, "…": "…" },
"storage": { "mode": "review", "kept": true, "reason": "pending_review", "expires_at": "2026-10-29T10:05:01Z", "file_deleted_at": null },
"file_url": "https://api.constaia.com/v1/files/…",
"metadata": { "registration_id": "124" }
}
],
"has_more": false,
"url": "/v1/reviews"
}Cada elemento es el objeto analysis completo. La paginación
funciona como en el resto de listados: ver Paginación.
curl -G https://api.constaia.com/v1/reviews \
-H "Authorization: Bearer $CONSTAIA_API_KEY" \
--data-urlencode "status=pending" \
--data-urlencode "metadata[event]=42" \
--data-urlencode "limit=50"Descargar el original
GET /v1/analyses/{id}/fileDevuelve el documento original tal como se subió, solo si sigue guardado (storage.kept: true). Con el modo de
almacenamiento por defecto (review) eso ocurre mientras el análisis espera revisión y durante el margen posterior a
la decisión. Ver Almacenamiento y privacidad.
Respuesta 200 con el binario:
| Cabecera | Valor |
|---|---|
Content-Type | El del original: image/jpeg, image/png, image/webp, image/heic o application/pdf. |
Content-Disposition | inline; filename="an_….jpg" |
Cache-Control | private, no-store |
Errores:
| HTTP | code | Cuándo |
|---|---|---|
404 | resource_missing | El análisis no existe o no es de tu cuenta. |
404 | file_not_stored | El original no se guardó (no hacía falta revisarlo o se analizó con storage: "none") o ya se borró tras su plazo. param es id. Los datos extraídos siguen disponibles. |
Alternativa sin clave: mientras el original está guardado, el campo file_url del análisis trae una URL firmada que
caduca a los 15 minutos. Es útil para enseñar el documento en tu pantalla de revisión; no la guardes, pide el análisis
de nuevo cuando necesites otra.
curl -o original.jpg \
https://api.constaia.com/v1/analyses/an_01J9Z8Q3K4M5N6P7Q8R9S0T1V3/file \
-H "Authorization: Bearer $CONSTAIA_API_KEY"Decidir una revisión
POST /v1/analyses/{id}/review| Campo | Tipo | Descripción |
|---|---|---|
decision | approve | reject | Obligatorio. |
reason | string (≤ 200) | null | Motivo breve, p. ej. "Datos coinciden con el formulario". Opcional. |
note | string (≤ 2000) | null | Nota interna. Opcional. |
Responde 200 con el objeto analysis actualizado:
review.status:approvedorejected;review.decision:approveoreject.review.reviewed_by: el id de la clave con la que decidiste (key_…);review.reviewed_at,review.reasonyreview.note.verdict.final_status:validsi apruebas,invalidsi rechazas.storage.expires_atpasa a la hora de la decisión másreview_retention_hours_after_decision(24 h por defecto). Si ese plazo es0, el original se borra al decidir ystorage.keptpasa afalse.
Además se envía el webhook analysis.reviewed y la decisión queda en el registro de auditoría de
la cuenta a nombre de la clave de API.
{
"id": "an_01J9Z8Q3K4M5N6P7Q8R9S0T1V3",
"object": "analysis",
"verdict": { "status": "review", "final_status": "valid", "…": "…" },
"review": {
"status": "approved",
"decision": "approve",
"assignee": null,
"reviewed_by": "key_01J9Z8Q3K4M5N6P7Q8R9S0T1V9",
"reviewed_at": "2026-09-30T08:12:40Z",
"reason": "Datos coinciden con el formulario",
"note": null
},
"storage": { "mode": "review", "kept": true, "reason": null, "expires_at": "2026-10-01T08:12:40Z", "file_deleted_at": null }
}Reintentos seguros
- Envía la cabecera
Idempotency-Key: la misma clave con el mismo cuerpo devuelve la misma respuesta, con la cabeceraIdempotent-Replayed: true. Ver Idempotencia. - Repetir la misma decisión sobre un análisis ya decidido devuelve el análisis tal cual (
200) y no envía otro webhook. - Una decisión distinta sobre un análisis ya decidido devuelve
409 already_reviewed. Solo un propietario o administrador puede cambiarla, desde el panel.
Errores
| HTTP | code | Cuándo |
|---|---|---|
403 | publishable_key_not_allowed | Usaste una clave publicable (pk_…). |
404 | resource_missing | El análisis no existe o no es de tu cuenta. |
409 | already_reviewed | El análisis ya tiene otra decisión. |
409 | not_reviewable | El análisis no tiene veredicto: no se indicó expect o aún no ha terminado. |
422 | invalid_parameter | El cuerpo no es válido (decision falta o no es approve/reject, reason o note demasiado largos). |
curl https://api.constaia.com/v1/analyses/an_01J9Z8Q3K4M5N6P7Q8R9S0T1V3/review \
-H "Authorization: Bearer $CONSTAIA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: review-an_01J9Z8Q3K4M5N6P7Q8R9S0T1V3" \
-d '{ "decision": "approve", "reason": "Datos coinciden con el formulario" }'Plantillas y plazos
Si usas plantillas, cada una puede fijar su propio almacenamiento y sus plazos de revisión. El objeto template
incluye siempre estos campos:
| Campo | Tipo | Descripción |
|---|---|---|
storage | none | review | temporary | persistent | Modo de almacenamiento de los análisis hechos con la plantilla. |
review_retention_hours_after_decision | entero 0–720 | null | Horas que se conserva el original tras decidir. null = el valor de la cuenta (24 por defecto). |
review_max_days | entero 1–90 | null | Días máximos que se conserva un original pendiente si nadie decide. null = el valor de la cuenta (30 por defecto). |
Los valores de la cuenta se cambian en el panel (Ajustes de la cuenta).
Siguientes pasos
Análisis guardados
Recupera, lista con filtros y paginación por cursor, exporta y borra análisis con /v1/analyses, y descarga exportaciones con las URLs firmadas de /v1/files.
POST /v1/batches
Referencia de POST /v1/batches: analiza hasta 100 documentos en una llamada asíncrona, con opciones comunes o por documento y export combinado.