API pública de Yallegó
Documentación para integradores externos que consumen la API de Yallegó con
una clave de API (Authorization: Bearer yk_live_...). Si estás
implementando el panel administrativo o la app Android del propio proyecto,
usa en cambio el contrato interno docs/06_API_CONTRACT.md del repositorio
(incluye las superficies de panel, dispositivo y plataforma).
Base URL:
https://api.yallego.app/v1Especificación máquina-legible:../openapi.yaml(OpenAPI 3.1)
Contenido
| Guía | Contenido |
|---|---|
| 01 — Inicio rápido | Crear una clave, hacer la primera solicitud, registrar el primer webhook |
| 02 — Autenticación | Formato de la clave, alcances, claves por plan, GET /v1/me y errores de autenticación |
| 03 — Transacciones | Consultar, confirmar y disputar cobros capturados |
| 04 — Webhooks | Registrar endpoints, probar, rotar el secreto, ver entregas |
| 05 — Dispositivos | Consultar el estado de los dispositivos de captura (solo lectura) |
| 06 — Catálogo de eventos | Todos los eventos que puede emitir un webhook, con su payload completo |
| 07 — Verificación de firma | Cómo validar que un evento entrante viene de Yallegó, con ejemplos en Node.js, Python y PHP |
| 08 — Política de reintentos | Calendario de reintentos de webhooks y desactivación automática |
| 09 — Límites de tasa | Límites por plan y cómo interpretar las cabeceras X-RateLimit-* |
| 10 — Idempotencia | Reintentar escrituras con Idempotency-Key sin duplicar nada |
Qué NO cubre esta guía
/internal/v1/*— exclusivo de la app Android de captura, autenticado con token de dispositivo./platform/v1/*— administración interna de Yallegó, no es una superficie pública.- Rutas de
/v1que solo aceptan sesión del panel (registro, miembros, catálogo de billeteras, suscripción) — una clave de API no puede llamarlas.
Errores
Toda respuesta de error tiene la misma forma:
{
"error": {
"code": "NOT_FOUND",
"message": "La transacción no existe.",
"request_id": "b7f3a2e1-..."
}
}
codees estable: decide con él, no conmessage, que es un texto en español para mostrar.detailsaparece solo en algunos errores: el400de validación (fields, abajo), el409deconfirmydispute(status,note), el429(limit,window_seconds,retry_after,scope), el422de cupo del plan (limit,current) y los deIdempotency-Key.request_ides elX-Request-Idque enviaste o, si no enviaste uno, uno que genera Yallegó. También llega en la cabeceraX-Request-Idde toda respuesta.
Errores de validación
Un cuerpo o una query que no cumplen el esquema de la ruta (un campo que no
existe, un valor fuera de un enum, un texto demasiado largo, una URL de webhook
http://) responden 400 VALIDATION_ERROR con un mensaje genérico y, en
details.fields, cada campo que falló:
// 400 Bad Request
{
"error": {
"code": "VALIDATION_ERROR",
"message": "La solicitud contiene datos inválidos.",
"details": {
"fields": [
{
"path": "subscribed_events[1]",
"code": "invalid_value",
"message": "Evento desconocido. Usa uno de: transaction.created, …"
},
{ "path": "secret", "code": "unknown_field", "message": "No es un campo admitido." }
]
},
"request_id": "b7f3a2e1-..."
}
}
pathes la ruta del campo en notación de punto y corchetes (subscribed_events[0],device.label). Vacío si el problema es el cuerpo o la query completa (por ejemplo, unPATCHsin ningún campo).codedice qué pasó y es estable:required(falta),invalid_type(otro tipo),invalid_value(fuera de los valores permitidos),invalid_format(URL, UUID, fecha),too_small/too_big(largo o rango),unknown_field(el cuerpo no admite ese campo) oinvalid(una regla propia de la ruta).messagees un texto en español para mostrar o registrar; no lo compares.- La respuesta nunca repite el valor que enviaste, solo qué se esperaba.
- Llegan hasta 20 campos por respuesta.
Estas validaciones propias de una ruta traen un mensaje específico y no traen
fields:
| Caso | message | details |
|---|---|---|
| Cursor que no salió de la API | «El cursor de paginación no es válido.» | — |
Idempotency-Key inválida | «La cabecera Idempotency-Key debe tener entre 1 y 255 caracteres ASCII visibles, sin espacios.» | { "header": "Idempotency-Key" } |
| Registrar una URL cuyo dominio no resuelve | «No se pudo resolver el dominio del webhook.» | — |
| Registrar una URL que apunta a una red interna | «La URL del webhook no puede apuntar a una red interna.» | — |
Un cuerpo que no es JSON válido responde 400 VALIDATION_ERROR con el mensaje
genérico y sin details; como cualquier otra respuesta, trae request_id y la
cabecera X-Request-Id.
Soporte
Ante dudas sobre la integración, escribe a soporte con el request_id del
error o la cabecera X-Request-Id de la respuesta (está en toda respuesta,
exitosa o no) — acelera el diagnóstico.