Constaia
Guías por caso

Revisión humana desde tu backend

Lleva la revisión humana a tu propia aplicación con la API. Recibe los pendientes, descarga el documento original, registra la decisión y aplica el resultado final.

Cuando Constaia no puede decidir solo, el análisis queda pendiente de revisión humana. Tu equipo puede revisarlo en el panel, pero si ya tienes tu propia herramienta interna (un backoffice, un CRM, una pantalla de validación) puedes hacerlo todo desde tu backend:

  1. Analizas el documento con expect.
  2. Te enteras de que necesita revisión (webhook o consulta periódica).
  3. Descargas el documento original para enseñárselo al revisor.
  4. Registras la decisión en Constaia.
  5. Aplicas el resultado final.

Con el almacenamiento por defecto, Constaia solo guarda el documento, cifrado, mientras hace falta revisarlo, y lo borra al decidir. No tienes que custodiar tú una copia.

El flujo

Tu servidor                                          Constaia
───────────                                          ────────
1. POST /v1/analyze  { expect, metadata } ─────────▶ veredicto review → review.status: "pending"
                                                     el original se guarda cifrado (storage.kept: true)
2. /webhooks/constaia ◀── analysis.review_required
   o bien  GET /v1/reviews?status=pending ─────────▶ lista de pendientes, los más antiguos primero
3. GET /v1/analyses/{id}/file ─────────────────────▶ el documento original (o file_url, 15 min)
4. POST /v1/analyses/{id}/review  { decision } ────▶ verdict.final_status: valid | invalid
   (con Idempotency-Key)                             el original se borra 24 h después (ajustable)
5. /webhooks/constaia ◀── analysis.reviewed

Estos endpoints solo funcionan con una clave secreta (ck_…), nunca desde el navegador. Referencia completa en Revisiones.

Paso 1: analizar con expect

La revisión se hace sobre el veredicto, así que el análisis necesita expect: sin él no hay nada que aprobar o rechazar (409 not_reviewable). Usa metadata para enlazar el análisis con el registro de tu sistema.

No hace falta enviar storage: el modo por defecto (review) guarda el original solo si el análisis queda pendiente de revisión. Si envías storage: "none", el documento no se guarda nunca y el revisor solo podrá ver los datos extraídos.

Qué queda pendiente de revisión:

  • Por defecto, los análisis con veredicto review.
  • Si usas una plantilla (template: "tpl_…"), su política de revisión puede enviar también los invalid, o todos los valid si prefieres que ninguno se apruebe solo. La plantilla también puede fijar sus propios plazos de conservación.
Terminal
curl https://api.constaia.com/v1/analyze \
  -H "Authorization: Bearer $CONSTAIA_API_KEY" \
  -F file=@blurry.jpg \
  -F 'options={"expect":["es_dni","es_nie","passport"],"metadata":{"registration_id":"124"}}'
Respuesta (extracto)
{
  "id": "an_01J9Z8Q3K4M5N6P7Q8R9S0T1V3",
  "verdict": { "status": "review", "final_status": null, "…": "…" },
  "review": { "status": "pending", "decision": null, "assignee": null, "reviewed_by": null, "reviewed_at": null, "reason": null, "note": 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" }
}

Paso 2: enterarte de los pendientes

Tienes dos formas, y puedes combinarlas:

  • Webhook analysis.review_required: llega cuando un análisis termina con veredicto review. Es lo más inmediato. Ver Webhooks.
  • Consultar GET /v1/reviews: devuelve todos los análisis pendientes, los más antiguos primero, como una cola. Incluye también los que una plantilla manda a revisión aunque su veredicto sea valid o invalid. Úsalo en un proceso periódico o para montar la bandeja de tu herramienta interna.

Si usas los dos, identifica cada elemento por el id del análisis para no duplicarlo.

Terminal
curl -G https://api.constaia.com/v1/reviews \
  -H "Authorization: Bearer $CONSTAIA_API_KEY" \
  --data-urlencode "status=pending" \
  --data-urlencode "limit=50"

Filtra con type, template o metadata[clave] si cada equipo revisa un tipo de documento o un evento distinto.

Paso 3: enseñar el documento al revisor

Mientras el análisis está pendiente, el original sigue guardado (storage.kept: true). Dos formas de obtenerlo:

  • file_url del análisis: una URL firmada que caduca a los 15 minutos. Sirve para mostrar la imagen o el PDF directamente en tu pantalla de revisión. No la guardes: pide el análisis de nuevo con GET /v1/analyses/{id} cuando necesites otra.
  • GET /v1/analyses/{id}/file: descarga el fichero con tu clave, por ejemplo para servirlo tú mismo desde tu backend. El Content-Type es el del original (image/jpeg, image/png, image/webp, image/heic o application/pdf).

Junto al documento, enseña los motivos del veredicto (verdict.reasons con warning o error) y los campos extraídos (fields), para que el revisor compare.

Si el original ya no está guardado, la descarga devuelve 404 file_not_stored: no hacía falta revisarlo, se analizó con storage: "none" o ya se borró tras su plazo. Los datos extraídos siguen disponibles, así que el revisor puede decidir con ellos o pedir un documento nuevo.

Terminal
curl -o original \
  https://api.constaia.com/v1/analyses/an_01J9Z8Q3K4M5N6P7Q8R9S0T1V3/file \
  -H "Authorization: Bearer $CONSTAIA_API_KEY"

Paso 4: registrar la decisión

Cuando el revisor decide, envía approve o reject con un motivo breve (reason, hasta 200 caracteres) y, si quieres, una nota interna (note, hasta 2000). Envía siempre una Idempotency-Key: si la red falla y reintentas, la decisión no se duplica.

  • Aprobar deja verdict.final_status en valid; rechazar, en invalid.
  • review.reviewed_by queda con el id de tu clave de API (key_…), y la decisión se guarda en el registro de auditoría de la cuenta a nombre de esa clave. Guarda en tu sistema qué persona decidió, o ponlo en note.
  • Repetir la misma decisión devuelve el análisis tal cual, sin error.
Terminal
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": "reject", "reason": "La foto no deja leer la fecha de caducidad", "note": "Revisado por Ana" }'

Paso 5: aplicar el resultado

Aplica la consecuencia en tu sistema con verdict.final_status: valid, confirma; invalid, rechaza o pide otro documento. Puedes hacerlo con la respuesta de la decisión o con el webhook analysis.reviewed, que se envía siempre que se decide una revisión, tanto desde el panel como desde la API. Si parte de tu equipo revisa en el panel, escuchar este webhook mantiene tu sistema al día.

Dentro de tu manejador de webhooks
if (event.type === "analysis.reviewed") {
  const analysis = event.data;
  await applyDecision(analysis.metadata.registration_id, analysis.verdict.final_status);
}

Qué pasa con el documento después

  • Al decidir, el original se conserva 24 horas más (para poder consultar la decisión) y después se borra. storage.expires_at te dice cuándo.
  • Si nadie decide, se borra a los 30 días de terminar el análisis. Los datos extraídos siguen disponibles.
  • Ambos plazos se cambian en el panel (Ajustes de la cuenta) y, si lo necesitas, por plantilla: review_retention_hours_after_decision (0–720 horas; con 0 se borra al decidir) y review_max_days (1–90 días).

Más detalle en Almacenamiento y privacidad.

Errores habituales

HTTPcodeQué significaQué hacer
404file_not_storedEl original no está guardado (no hacía falta revisarlo, storage: "none" o ya se borró).Revisa con los datos extraídos o pide otro documento.
409already_reviewedEl análisis ya tiene otra decisión.No reintentes. Solo un propietario o administrador puede cambiarla, desde el panel.
409not_reviewableNo hay veredicto: se analizó sin expect o aún no ha terminado.Analiza con expect o espera a que termine.
403publishable_key_not_allowedUsaste una clave publicable (pk_…).Usa la clave secreta, siempre desde tu backend.

Todos los códigos en Errores.

Probarlo

Con una clave ck_test_…, analiza una imagen llamada blurry.jpg con expect: "es_dni": el veredicto es review y el análisis aparece en GET /v1/reviews. Decídelo con POST /v1/analyses/{id}/review y, si tienes un endpoint de webhooks de test, recibirás analysis.review_required y después analysis.reviewed. Más en Modo test.

Siguientes pasos

En esta página