API — Sesiones
Una sesión representa una verificación de identidad de un usuario. Se crea con un conjunto de features, se alimenta con documentos y biometría, y termina con una decisión. Todos los endpoints requieren autenticación por API key (X-API-Key: zkyc_...), salvo donde se indica rol operador.
Prefijo: /v1/sessions.
Endpoints
Sección titulada «Endpoints»| Método | Ruta | Auth | Descripción |
|---|---|---|---|
| POST | /v1/sessions | API key | Crear sesión |
| GET | /v1/sessions/:id | API key | Detalle de una sesión |
| GET | /v1/sessions | API key | Listar sesiones (paginado) |
| DELETE | /v1/sessions/:id | API key | Eliminar sesión |
| GET | /v1/sessions/pending | Operador | Cola de revisión manual |
| POST | /v1/sessions/:id/decision | Operador | Aprobar / rechazar manualmente |
| POST | /v1/sessions/:id/share | API key | Generar share token (reusable KYC) |
| POST | /v1/sessions/import | API key | Importar verificación compartida |
| POST | /v1/sessions/workflows | API key | Crear workflow |
| GET | /v1/sessions/workflows | API key | Listar workflows |
| GET | /v1/sessions/workflows/:id | API key | Detalle de workflow |
| PATCH | /v1/sessions/workflows/:id | API key | Actualizar workflow |
| DELETE | /v1/sessions/workflows/:id | API key | Eliminar workflow |
Estados y decisión
Sección titulada «Estados y decisión»Estado (status) | Significado |
|---|---|
not_started | Creada, sin actividad |
in_progress | Recibiendo documentos/biometría |
pending | A la espera de pasos del usuario |
in_review | Requiere decisión manual del operador |
approved | Aprobada |
declined | Rechazada |
abandoned | Abandonada por el usuario |
La decisión (decision) puede ser approved, declined o in_review. Regla fija: un hit AML nunca auto-aprueba — fuerza in_review para revisión manual.
Crear sesión
Sección titulada «Crear sesión»POST /v1/sessionsX-API-Key: zkyc_...Content-Type: application/json
{ "workflowId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "vendorData": "user-1234", "features": ["id", "liveness", "face_match", "aml"], "callbackUrl": "https://miapp.com/kyc/callback"}| Campo | Tipo | Descripción |
|---|---|---|
workflowId | string (UUID), opcional | Workflow del que heredar features/config |
vendorData | string ≤255, opcional | Tu identificador interno del usuario |
features | string[], opcional | id · liveness · face_match · aml · age · poa · phone · email |
callbackUrl | string (URL), opcional | URL de retorno del flujo de verificación |
Respuesta 201 Created:
{ "ok": true, "session": { "id": "9b1c0e2a-3d4f-4a5b-8c6d-7e8f9a0b1c2d", "status": "not_started", "sessionToken": "stk_a1b2c3...", "verificationUrl": "https://kyc.zentto.net/verify/stk_a1b2c3...", "features": ["id", "liveness", "face_match", "aml"] }}curl -X POST https://kyc.zentto.net/v1/sessions \ -H "X-API-Key: $KYC_API_KEY" \ -H "Content-Type: application/json" \ -d '{"features":["id","liveness","aml"],"vendorData":"user-1234"}'const { session } = await kyc.sessions.create({ features: ["id", "liveness", "face_match", "aml"], vendorData: "user-1234",});Detalle de una sesión
Sección titulada «Detalle de una sesión»GET /v1/sessions/9b1c0e2a-3d4f-4a5b-8c6d-7e8f9a0b1c2dX-API-Key: zkyc_...{ "ok": true, "session": { "id": "9b1c0e2a-...", "status": "approved", "features": ["id", "liveness"] } }const { session } = await kyc.sessions.get("9b1c0e2a-...");Listar sesiones
Sección titulada «Listar sesiones»GET /v1/sessions?status=approved&limit=20&offset=0X-API-Key: zkyc_...| Query | Default | Descripción |
|---|---|---|
status | — | Filtra por estado |
limit | 20 | 1–100 |
offset | 0 | Desplazamiento |
{ "ok": true, "sessions": [ { "id": "9b1c0e2a-...", "status": "approved" } ], "total": 1, "limit": 20, "offset": 0 }const { sessions, total } = await kyc.sessions.list({ status: "approved", limit: 20 });Eliminar sesión
Sección titulada «Eliminar sesión»DELETE /v1/sessions/9b1c0e2a-...X-API-Key: zkyc_...{ "ok": true }Cola de revisión (operador)
Sección titulada «Cola de revisión (operador)»GET /v1/sessions/pendingX-API-Key: zkyc_<operador>{ "ok": true, "sessions": [ { "id": "9b1c0e2a-...", "status": "in_review" } ], "total": 1 }const { sessions } = await kyc.sessions.pending();Decisión manual (operador)
Sección titulada «Decisión manual (operador)»POST /v1/sessions/9b1c0e2a-.../decisionX-API-Key: zkyc_<operador>Content-Type: application/json
{ "approve": true, "reason": "Documento legible y face-match OK" }| Campo | Tipo | Descripción |
|---|---|---|
approve | boolean | true aprueba, false rechaza |
reason | string ≤1000, opcional | Motivo de la decisión |
{ "ok": true, "session": { "id": "9b1c0e2a-...", "status": "approved" } }await kyc.sessions.decide("9b1c0e2a-...", { approve: true, reason: "OK" });Compartir e importar (reusable KYC)
Sección titulada «Compartir e importar (reusable KYC)»Una sesión aprobada puede generar un shareToken para reutilizar la verificación en otra app/tenant, sin repetir el proceso.
POST /v1/sessions/9b1c0e2a-.../shareX-API-Key: zkyc_...{ "ok": true, "share": { "shareToken": "shr_a1b2c3d4e5f6...", "expiresAt": "2026-07-21T10:00:00.000Z" } }El receptor lo importa:
POST /v1/sessions/importX-API-Key: zkyc_...Content-Type: application/json
{ "shareToken": "shr_a1b2c3d4e5f6..." }{ "ok": true, "imported": { "id": "c3d4e5f6-...", "status": "approved" } }const { share } = await kyc.sessions.share("9b1c0e2a-...");const { imported } = await kyc.sessions.import(share.shareToken);share solo funciona si decision = approved. El shareToken tiene 16–80 caracteres y un TTL configurable (default 30 días).
Workflows
Sección titulada «Workflows»Un workflow encapsula un conjunto de features (+ config) reutilizable al crear sesiones vía workflowId.
Crear workflow
Sección titulada «Crear workflow»POST /v1/sessions/workflowsX-API-Key: zkyc_...Content-Type: application/json
{ "name": "Onboarding estándar", "features": ["id", "liveness", "face_match", "aml"], "config": { "minAge": 18 }}| Campo | Tipo | Descripción |
|---|---|---|
name | string 1–120 | Nombre del workflow |
features | string[] (mín. 1) | Features de las sesiones que lo usen |
config | objeto, opcional | Config extra; admite minAge (0–150) |
Respuesta 201 Created:
{ "ok": true, "workflow": { "id": "f47ac10b-...", "name": "Onboarding estándar", "features": ["id", "liveness", "face_match", "aml"] } }Listar / detalle / actualizar / eliminar
Sección titulada «Listar / detalle / actualizar / eliminar»GET /v1/sessions/workflowsGET /v1/sessions/workflows/:idPATCH /v1/sessions/workflows/:idDELETE /v1/sessions/workflows/:idPATCH acepta name, features, config e isActive (todos opcionales).
const { workflow } = await kyc.sessions.createWorkflow({ name: "Onboarding estándar", features: ["id", "liveness", "face_match", "aml"],});await kyc.sessions.updateWorkflow(workflow.id, { features: ["id", "liveness"] });await kyc.sessions.listWorkflows();await kyc.sessions.deleteWorkflow(workflow.id);Flujo del usuario
Sección titulada «Flujo del usuario»Vista no técnica del proceso de verificación completo desde el punto de vista del usuario final.
Editable en draw.io: descarga el SVG → en draw.io: File → Import from → Device → selecciona el SVG. Cada nodo queda editable.
Flujo técnico
Sección titulada «Flujo técnico»Vista técnica: crear sesión → subir documento/selfie → inferencia → decisión orquestada → webhook.
| Componente | Tipo | Ubicación |
|---|---|---|
POST /v1/sessions | Route Express | src/sessions/routes.ts |
GET /v1/sessions/:id | Route Express | src/sessions/routes.ts |
GET /v1/sessions/pending | Route Express (operador) | src/sessions/routes.ts |
POST /v1/sessions/:id/decision | Route Express (operador) | src/sessions/routes.ts |
POST /v1/sessions/:id/share | Route Express | src/sessions/routes.ts |
POST /v1/sessions/import | Route Express | src/sessions/routes.ts |
POST /v1/sessions/workflows | Route Express | src/sessions/routes.ts |
sessions.service.ts | Servicio de sesiones | src/sessions/sessions.service.ts |
sessions.orchestrator.ts | Orquestador de decisión | src/sessions/sessions.orchestrator.ts |
sessions | Tabla operativa | src/db/migrations/ |
session_results | Tabla resultados por feature | src/db/migrations/ |
POST /v1/ocr | Inferencia ML (FastAPI :5200) | inference/app/routers/ocr.py |
POST /v1/liveness | Inferencia ML (FastAPI :5200) | inference/app/routers/liveness.py |
POST /v1/face-match | Inferencia ML (FastAPI :5200) | inference/app/routers/face.py |
Editable en draw.io: descarga el SVG → File → Import from → Device.