Empezar
De cero a tu primera verificación real. Cinco pasos, cada uno con el enlace directo a la pantalla del panel donde se hace.
Qué vas a lograr
Al terminar esta página vas a tener:
- Una llave de API que funciona, con los permisos justos.
- El negocio listo para que verificar sirva de algo: con su banco conectado.
- Tu primera respuesta real de la API, y la primera verificación de un comprobante.
- Claro qué sigue: webhooks, reintentos sin duplicar y manejo de errores.
Cuánto tarda: unos 5 minutos si el negocio ya tiene su banco conectado en Verifika; unos 15 si hay que conectarlo (es un asistente guiado, no un trámite técnico).
¿No vas a escribir código?
Si lo que quieres es preguntarle a Claude o a ChatGPT por tus pagos, no necesitas nada de esto: ve a Conectar con un clic. Y si programas con un asistente de IA (Claude Code, Cursor, Codex…), instala primero la skill de Verifika: le da todo este contexto de una vez.
Revisa que tu plan incluya la API pública
La API pública, los webhooks y la conexión con asistentes (MCP) son funciones del plan, y cada una se incluye por separado. Tienes tres formas de saber si la tuya las trae:
- En el panel: abre Configuración → Plan. O entra directo a Integraciones → API pública: si tu plan no la incluye, la sección sale con un candado y te dice qué trae.
- En la web: verifika.tech/#precios muestra qué incluye cada plan hoy.
- Desde tu código, cuando ya tengas llave:
GET /v1/plandevuelve las funciones del plan. Es la forma que no se desactualiza:
{
"object": "plan",
"features": {
"public_api": true,
"webhooks_outbound": true,
"mcp_server": true
},
"usage": { "verifications": { "used": 312, "limit": 4000, "remaining": 3688 } }
}| Función | Para qué |
|---|---|
public_api | Toda la API /v1. Sin ella, nada de lo demás funciona. |
webhooks_outbound | Que te avisemos en tu URL cuando pasa algo (pagos verificados, sospechosos…). |
mcp_server | Conectar asistentes de IA como Claude o ChatGPT. |
Si tu plan no trae una función y la llamas igual, la respuesta es 403 PLAN_FEATURE_REQUIRED
y details.feature dice cuál falta:
{
"error": {
"code": "PLAN_FEATURE_REQUIRED",
"message": "Esta función no está incluida en tu plan.",
"details": { "feature": "public_api" },
"requestId": "req_5837b3c1d2e04f6a9b1c7d8e0f2a3b4c"
}
}No ramifiques por el nombre del plan
Los planes cambian de nombre y de contenido. Pregunta por la función (features.public_api),
nunca por cómo se llama el plan: así tu integración sigue funcionando el día que cambien.
Conecta el banco del negocio: sin esto, verificar no sirve
Verifika no adivina si un pago entró: cruza el comprobante contra el aviso que el banco le manda al negocio —un correo, un mensaje de texto o una notificación de la app del banco—. Si el negocio no tiene su banco conectado, no hay contra qué cruzar: todo lo que mandes se queda pendiente para siempre y tu bot nunca va a poder decir «tu pago entró».
Por eso este paso va antes de la llave. Lo hace el dueño del negocio en un asistente de cuatro pasos; cada enlace abre el paso exacto:
| Paso | Qué se hace | Enlace directo |
|---|---|---|
| 1. Tus bancos | Marcar los bancos y billeteras donde el negocio recibe pagos (Bancolombia, Nequi, Daviplata…). Con eso se arma lo demás. | Abrir |
| 2. Tu correo | Conectar el Gmail u Outlook donde llegan los avisos de transferencia, con un clic. Si el correo es de otro proveedor, con una regla de reenvío. | Abrir |
| 3. Tu celular | Sumar los mensajes de texto del banco desde la app de Verifika: en Android lee los SMS y las notificaciones de la app del banco; en iPhone, con un atajo. | Abrir |
| 4. ¡Listo! | Mandar un comprobante de prueba y ver cómo se confirma. | Abrir |
Con que un canal quede conectado ya se puede verificar; con correo y celular no se
escapa ningún pago. El estado de cada canal se ve en
Conexión con bancos, y desde tu código, con
GET /v1/connections: healthy: true quiere decir
que al menos un canal está conectado y recibiendo.
Si el negocio no tiene ningún canal conectado, las verificaciones quedan esperando a que una
persona del negocio las confirme (AWAITING_REVIEW): nadie las cruza solas.
Crea la llave
- Abre Crear llave con el atajo «Registro de pagos» ya marcado. Hace falta el permiso «Gestionar integraciones», que tienen el Dueño y el Administrador.
- Ponle un nombre que diga dónde vive: «Bot de WhatsApp», «ERP del contador». Con tres llaves sin nombre no vas a saber cuál revocar.
- Revisa los permisos. El atajo Registro de pagos marca verificar y consultar comprobantes, leer ingresos, ver el plan y el estado del banco. Lo que tu plan no incluye sale en gris con candado. El catálogo completo está en Autenticación y permisos.
- ¿Vas a construir y probar primero? Enciende Llave de prueba: lee los comprobantes con la IA de verdad pero no registra nada ni gasta verificaciones (guía; o directo: crear una llave de prueba).
- Cópiala en ese momento. Se muestra una sola vez.
La llave se muestra UNA sola vez
Después solo vas a ver vk_live_a1b2…7f3a en la lista de llaves. No es una molestia de diseño: para volver a
mostrártela tendríamos que guardarla de forma reversible, y una filtración de nuestra base sería
la llave de tu sistema. Guárdala donde guardas tus otros secretos. Si la pierdes, rótala
desde el menú de la llave; no hace falta rehacer la integración.
Déjala en una variable de entorno, nunca en el código ni en el navegador:
export VERIFIKA_API_KEY="vk_live_…"Haz tu primer request
GET /v1/me es la llamada con la que conviene empezar
siempre: valida la llave y dice a qué negocio entra y qué permisos tiene. Si algo va a
fallar por configuración, falla aquí y no a mitad de tu flujo.
curl https://api.verifika.tech/v1/me \
-H "Authorization: Bearer $VERIFIKA_API_KEY"{
"object": "apiKey",
"id": "cmtnj6kmc00000bw16bx3gkkm",
"name": "Bot de WhatsApp",
"type": "BUSINESS",
"scopes": ["verifications.write", "verifications.read", "incomes.read", "plan.read", "connections.read"],
"companies": [{ "id": "cmt7xbfrg0001q3w1itst7uwo", "name": "Panadería Delipan" }],
"branchId": null,
"plan": { "key": "TU_PLAN", "name": "El nombre de tu plan", "status": "ACTIVE" },
"livemode": true
}Ahora comprueba que el banco del paso 2 está conectado:
curl https://api.verifika.tech/v1/connections \
-H "Authorization: Bearer $VERIFIKA_API_KEY"{
"object": "connectionStatus",
"healthy": true,
"channels": [
{
"object": "connection",
"type": "EMAIL_GMAIL",
"status": "CONNECTED",
"paused": false,
"lastEventAt": "2026-10-12T14:02:11.000Z",
"connectedAt": "2026-09-20T16:40:00.000Z"
}
]
}Y ahora, un comprobante de verdad
Con healthy: true, manda la imagen de un comprobante —en una URL https pública o en
base64—. Verifika la lee con IA, revisa que no se haya usado antes y la cruza contra el aviso del
banco. Con una llave real, esto consume una verificación de tu cupo si queda registrada (un
duplicado o un rechazo no gasta nada); con una de prueba, nunca.
curl -X POST https://api.verifika.tech/v1/verifications \
-H "Authorization: Bearer $VERIFIKA_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "https://cdn.tubot.com/comprobantes/7f3a.jpg",
"reporter": { "name": "Laura Restrepo", "externalId": "wa_573104567890" },
"metadata": { "chatId": "wa_573104567890" }
}'{
"object": "verification",
"id": "vrf_3f9a1c0e7b2d4e8fa61c5d90b7e24a13",
"livemode": true,
"status": "PENDING",
"code": "AWAITING_BANK",
"message": "Recibimos tu comprobante por $85.000. Estamos esperando la confirmación del banco; en unos minutos te avisamos.",
"extracted": { "isReceipt": true, "amount": 85000, "reference": "M48213907", "bankLabel": "Nequi", "confidence": 0.96, "…": "…" },
"metadata": { "chatId": "wa_573104567890" },
"nextStep": { "type": "AWAIT_BANK", "until": "2026-10-12T20:30:06.000Z", "webhookEvents": ["verification.verified", "verification.not_found"] }
}PENDING quiere decir que el banco todavía no ha avisado. Cuando avise, Verifika lo confirma
solo y te llega el webhook verification.verified con tu metadata (siguiente paso). Si el
banco ya había avisado, la respuesta ya viene VERIFIED. message está escrito para quien pagó:
reenvíalo tal cual. Cada code posible y qué hacer con él está en
Verifica desde tu propio bot.
¿Ya leíste tú el comprobante?
Si tu sistema ya tiene el monto y la referencia, manda amount y el phone de alguien del equipo
en vez de la imagen: es el contrato de datos, el de antes. Ver
la alternativa.
Qué sigue
Cuando el comprobante llega antes que el banco
El caso más común: avisarle al cliente minutos después, por webhook.
Webhooks
Que te avisemos en tu URL, con firma y reintentos, en vez de preguntar cada minuto.
Modo de prueba
Valores mágicos para provocar cada veredicto sin tocar pagos reales.
Idempotencia
Reintentar sin registrar la misma venta dos veces.
Errores
Qué códigos existen, cuáles se reintentan y para qué sirve el requestId.
Si tu llave entra a varios negocios
Una llave puede cubrir más de un negocio de la misma cuenta. En ese caso tienes que decir
sobre cuál actúas, con companyId:
curl "https://api.verifika.tech/v1/incomes?companyId=cmt7xbfrg0001q3w1itst7uwo" \
-H "Authorization: Bearer $VERIFIKA_API_KEY"Si no lo mandas, la respuesta es 400 con la lista de negocios de la llave en
details.companyIds. No elegimos por ti a propósito: escribir en el libro equivocado no se nota
hasta que el contador cuadra el mes.
Si algo falla en estos pasos
| Ves | Qué pasa | Qué hacer |
|---|---|---|
401 UNAUTHORIZED | La llave está mal copiada, revocada o vencida. | Revísala en API pública o rótala. |
403 PLAN_FEATURE_REQUIRED | Tu plan no incluye esa función (details.feature). | Paso 1. |
403 SCOPE_REQUIRED | La llave no tiene ese permiso (details.scope). | Agrégalo desde Editar en el menú de la llave: el secreto no cambia. |
403 ACCOUNT_… | La cuenta está bloqueada (prueba vencida, cancelada o pago pendiente). | El dueño la regulariza en Plan o en Facturación. |
403 TEST_MODE_UNAVAILABLE | Usaste una llave de prueba en algo que no tiene modo prueba. | Ver Modo de prueba. |
503 AI_UNAVAILABLE | La lectura con IA falló. | Si details.retryable es true, reintenta con la misma Idempotency-Key. |
healthy: false | Ningún canal del banco está conectado. | Paso 2. |