Constaia
Endpoints

Enlaces de verificación

Referencia de /v1/verification-links: crea una página alojada donde la persona sube sus documentos desde el móvil, recibe los resultados por webhook, callback o email y consulta, lista o cancela enlaces.

Un enlace de verificación es una página alojada por Constaia (url, con su código QR en qr_svg) donde la persona acepta el consentimiento y sube cada documento que pides, con la cámara del móvil o desde un archivo. Cada subida es un análisis normal en el modo de la clave (en live cobra créditos) y todos quedan en un expediente (dossier_id) con un veredicto global.

Guía paso a paso con callback, email de resultados y vuelta a tu web: Crear enlaces por API y recibir los resultados.

Método y rutaQué hace
POST /v1/verification-linksCrea un enlace (y su expediente).
GET /v1/verification-linksLista los enlaces del modo de la clave.
GET /v1/verification-links/{id}Recupera uno, con qr_svg.
DELETE /v1/verification-links/{id}Lo cancela: la página deja de aceptar documentos.

Todas las rutas usan una clave secreta (ck_test_… o ck_live_…) desde tu backend.

Crear un enlace

POST /v1/verification-links
Content-Type: application/json
CampoTipoDefectoDescripción
templatestring | null—Id de una plantilla de la cuenta (tpl_…). Sus opciones de análisis se aplican a cada documento. 422 template_not_found si no existe.
documentsobjeto[] (1–10)—Documentos que se piden, en orden. Cada uno: key (1–40 caracteres: letras, números, - o _, única), label (texto visible, hasta 120), expect (tipo o lista de tipos) y checks (como en analyze). Si falta y hay template, se pide uno (key: "document") con el expect de la plantilla. Sin documents ni template: 422 documents_required.
referencestring | null—Tu referencia (hasta 200 caracteres). Sirve para filtrar el listado.
metadataobjeto string → string{}Hasta 20 claves. Se copia al expediente y a cada análisis.
expires_in_hoursentero 1–72072Horas de validez. Al pasar, el enlace queda expired.
localees | en | pt | fridioma de la plantilla o de la peticiónIdioma de la página, de los emails y de los mensajes del expediente.
notify_emailemail | null—Envía el enlace por email a la persona, en locale.
consent_textstring | nullel de la cuentaTexto de consentimiento propio (hasta 2000 caracteres).
show_resultbooleanel de la cuentaEnseñar a la persona el resultado de cada documento.
redirect_urlstring https | null—A dónde vuelve la persona al terminar (botón en la pantalla final).
redirect_with_statusbooleanfalseAñade ?link_id=vl_…&status=<estado del enlace> a redirect_url.
face_verification{ enabled, required? } | nullel de la plantillaPaso Selfie tras los documentos (módulo opcional, cuentas del EEE con el anexo aceptado; si no, 403 face_verification_not_enabled). El enlace y el webhook llevan face_verification y face_match. Ver Verificación facial.
callback_urlstring https | null—Recibe un POST firmado con verification_link.completed y verification_link.expired. Debe ser https://; si no, 422 invalid_url (param: "callback_url").
include_resultsbooleantrueIncluir results (el análisis de cada documento) en el webhook y el callback. false: solo el enlace y el veredicto del expediente.
results_emailemail | null—Email que recibe un resumen de los resultados cuando el enlace se completa, en locale.

Los campos son estrictos: uno desconocido devuelve 422 invalid_parameter con su param.

curl https://api.constaia.com/v1/verification-links \
  -H "Authorization: Bearer $CONSTAIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "documents": [
      { "key": "id_card", "label": "DNI o NIE", "expect": ["es_dni", "es_nie"], "checks": { "min_age_years": 18 } },
      { "key": "receipt", "label": "Justificante de pago", "expect": "payment_receipt", "checks": { "expected_amount": 45 } }
    ],
    "reference": "inscripcion-4821",
    "metadata": { "registration_id": "4821" },
    "locale": "es",
    "callback_url": "https://example.com/constaia/callback",
    "results_email": "secretaria@example.com",
    "redirect_url": "https://example.com/inscripcion/4821",
    "redirect_with_status": true
  }'
201 Created (recortado)
{
  "id": "vl_01J9Z8Q3K4M5N6P7Q8R9S0T1V2",
  "object": "verification_link",
  "url": "https://app.constaia.com/v/3kqX…",
  "qr_svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" …</svg>",
  "status": "pending",
  "livemode": false,
  "template": null,
  "reference": "inscripcion-4821",
  "metadata": { "registration_id": "4821" },
  "documents": [
    {
      "key": "id_card",
      "label": "DNI o NIE",
      "expect": ["es_dni", "es_nie"],
      "checks": { "min_age_years": 18 },
      "status": "pending",
      "analysis_id": null,
      "attempts": 0,
      "verdict_status": null,
      "final_status": null,
      "warnings": []
    },
    { "key": "receipt", "label": "Justificante de pago", "…": "…" }
  ],
  "dossier_id": "dos_01J9Z8Q3K4M5N6P7Q8R9S0T1V3",
  "expires_at": "2026-10-03T10:00:00Z",
  "redirect_url": "https://example.com/inscripcion/4821",
  "redirect_with_status": true,
  "callback_url": "https://example.com/constaia/callback",
  "include_results": true,
  "results_email": "secretaria@example.com",
  "results_email_sent_at": null,
  "locale": "es",
  "notify_email": null,
  "last_sent_at": null,
  "show_result": false,
  "consent_text": null,
  "consent": null,
  "events": [{ "type": "created", "at": "2026-09-30T10:00:00Z" }],
  "created_at": "2026-09-30T10:00:00Z",
  "completed_at": null,
  "cancelled_at": null
}

Envía url a la persona (o enséñale qr_svg). La URL lleva un token secreto: trátala como una credencial de un solo uso y no la publiques.

CampoTipoDescripción
idstringPrefijo vl_.
urlstringPágina que abre la persona.
qr_svgstringQR de url en SVG. Solo en la creación y en el GET individual.
statusstringpending (nadie ha empezado), in_progress, completed, expired o cancelled.
livemodebooleanModo de la clave con la que se creó.
template, reference, metadataLo que indicaste al crearlo.
documents[]objeto[]Estado de cada documento: key, label, expect, checks, status (pending, processing, completed, failed), analysis_id (el análisis que cuenta), attempts, verdict_status, final_status (tras revisión humana) y warnings (avisos de calidad del último intento).
dossier_idstring | nullExpediente con todos los documentos, el veredicto global y las comprobaciones cruzadas (mismo titular, fechas coherentes).
expires_atstring ISO 8601Fin de la validez.
redirect_url, redirect_with_statusVuelta a tu web.
callback_url, include_resultsCallback firmado al completarse o caducar.
results_emailstring | nullDestinatario del resumen.
results_email_sent_atstring | nullCuándo se envió el resumen.
localestringIdioma de la página y de los emails.
notify_email, last_sent_atA quién se envió el enlace por email y cuándo.
show_result, consent_textConfiguración de la página.
consentobjeto | nullConsentimiento aceptado: accepted_at, ip y text.
events[]objeto[]Historial: type, at y, según el tipo, document_key o email.
created_at, completed_at, cancelled_atstring | nullFechas.

Tipos de events[].type:

TipoCuándo
createdSe crea el enlace.
sentSe envía el enlace por email (con email).
openedLa persona abre la página por primera vez.
consent_acceptedAcepta el consentimiento.
document_uploadedSube un documento (con document_key).
document_acceptedUn documento queda aceptado (con document_key).
document_rejectedUn documento necesita repetirse, por ejemplo por una foto borrosa (con document_key).
completedTodos los documentos están terminados.
expiredPasa expires_at sin completarse.
cancelledLo cancelas.
results_sentSe envía el resumen a results_email (con email).

Cada documento admite hasta 5 intentos. Un documento con avisos de calidad que piden otra foto (y veredicto no válido) se puede repetir mientras queden intentos. El enlace se completa cuando todos los documentos están aceptados o sin intentos.

Resultados: webhook, callback y email

Cuando el enlace pasa a completed o expired recibes el mismo cuerpo por dos vías:

  • Webhook global: verification_link.completed y verification_link.expired, en los endpoints de webhook suscritos a esos eventos.
  • Callback del enlace: un POST a callback_url, firmado con Standard Webhooks y con los mismos reintentos.

data es el objeto verification_link (sin qr_svg) más:

CampoDescripción
results[]Solo si include_results es true. Uno por documento pedido, en orden: document_key, label y analysis (el objeto analysis que cuenta para ese documento, tal como se guardó: con mask_fields aplicado y sin file_url; null si no se subió).
dossier{ id, verdict: { status, reasons: [{ code, severity, message }] } } del expediente, en el idioma del enlace, o null. status: complete_valid, incomplete, invalid o review.

Con results_email se envía además un resumen sin datos de los documentos al completarse. Detalle de la firma, el secreto, los reintentos, el cuerpo completo y el email en la guía de resultados.

Listar enlaces

curl "https://api.constaia.com/v1/verification-links?status=completed&metadata[registration_id]=4821" \
  -H "Authorization: Bearer $CONSTAIA_API_KEY"
ParámetroDescripción
limit1–100, por defecto 20.
starting_afterId del último enlace de la página anterior. Ver paginación.
statuspending, in_progress, completed, expired o cancelled.
referenceTu referencia exacta.
metadata[clave]Filtra por un valor de metadata.

Devuelve { "object": "list", "data": [...], "has_more": false, "url": "/v1/verification-links" }, solo con los enlaces del modo de la clave y sin qr_svg.

Recuperar y cancelar

curl https://api.constaia.com/v1/verification-links/vl_01J9Z8Q3K4M5N6P7Q8R9S0T1V2 \
  -H "Authorization: Bearer $CONSTAIA_API_KEY"

curl -X DELETE https://api.constaia.com/v1/verification-links/vl_01J9Z8Q3K4M5N6P7Q8R9S0T1V2 \
  -H "Authorization: Bearer $CONSTAIA_API_KEY"

DELETE devuelve el enlace con status: "cancelled"; cancelar uno ya cancelado lo devuelve igual. Un enlace completado o caducado no se puede cancelar: 409 link_not_active. Un id que no existe en la cuenta devuelve 404 resource_missing.

Errores

HTTPcodeCuándo
422invalid_parameterUn campo no es válido (param indica cuál), por ejemplo redirect_url sin https://.
422invalid_urlcallback_url no es una URL https (param: "callback_url").
422documents_requiredNi documents ni template.
422template_not_foundLa plantilla no existe en la cuenta.
409link_not_activeCancelar un enlace completado o caducado.
404resource_missingEl enlace no existe.

Siguientes pasos

En esta página