Skip to main content
Los webhooks te avisan en tiempo real, en tu propio servidor, cada vez que un cobro cambia de estado — sin que tengas que consultar la API en bucle. 1to1 envía un POST firmado a la URL que registres, con el detalle del pago.
Estos webhooks son salientes (1to1 → tu servidor). No los llamas tú: los recibes. Cada entrega va firmada (estándar Standard Webhooks) para que verifiques que vino de nosotros y no fue alterada.

Configurar un endpoint

Desde el dashboard, en Configuración → API y Conexiones, agrega la URL de tu sistema y elige los eventos que quieres recibir. Al crearlo obtienes un signing secret (whsec_…) que se muestra una sola vez — guárdalo como un secreto: es la llave con la que verificas cada webhook. Puedes registrar hasta 10 endpoints por negocio.
La URL debe ser https:// y pública. Guarda el whsec_… en un lugar seguro del servidor (variable de entorno, secret manager) — nunca en código cliente ni en el repositorio. Si lo pierdes, rota el secret desde el dashboard.

Catálogo de eventos

payment.failed cubre solo los pagos manuales marcados como fallidos por tu equipo. Los fallos de pagos online (tarjeta declinada, sesión expirada) no emiten webhook.

El payload

Cada POST lleva un cuerpo JSON con esta forma. El ejemplo es un pago manual acreditado:
event_at es el momento en que ocurrió el evento del pago (para payment.failed es la hora de la falla). Es distinto del header webhook-timestamp, que es el instante de envío usado para la firma anti-replay.
Algunos campos son exclusivos de pagos manuales (provider: "manual"): bank_account (la etiqueta de la cuenta a la que entró el dinero, p. ej. "BANORTE 0876"), bank_datetime (fecha/hora en banca, opcional) y files (comprobantes subidos). En pagos online quedan null / []. Para tarjeta y SPEI online usa transaction_id y receipt_url.
conversation_info.uuid puede ser null si la conversación asociada se borró — el pago igual notifica (el webhook es del ciclo de vida del pago, no de la conversación). Correlaciona siempre por data.payment.uuid.

Headers de cada entrega

string
Id único de la entrega. Estable entre reintentos de un mismo evento — úsalo para deduplicar (ver Entrega).
integer
Instante de envío (segundos Unix). Se recomputa en cada reintento y entra en la firma. Rechaza los que estén fuera de una ventana razonable (±5 min) para protegerte de replays.
string
Una o más firmas v1,<base64> separadas por espacio (habrá dos durante una rotación de secret). La entrega es válida si alguna coincide.
string
El tipo de evento (payment.credited, payment.failed, …). Coincide con type del cuerpo.
string
Siempre 1to1-Webhooks/1.0.

Verificar la firma

La firma es un HMAC-SHA256 del contenido {webhook-id}.{webhook-timestamp}.{body}, donde body es el cuerpo crudo exacto que recibiste (no lo re-serialices). La clave es tu whsec_… con el prefijo removido y el resto decodificado de base64.
Verifica sobre el cuerpo crudo (raw body), antes de parsear el JSON. Re-serializar el objeto cambia bytes (espacios, orden de llaves) y rompe la firma.
La forma más simple es la librería oficial de Standard Webhooks, que maneja la rotación y la comparación en tiempo constante por ti:
Si prefieres verificar a mano (sin dependencias), replica el HMAC y compara en tiempo constante contra cada firma del header:

Entrega y reintentos

1

Responde 2xx rápido

Contesta con cualquier 2xx en cuanto recibas el webhook. Si tardas más de 10 segundos o respondes otro código, lo tratamos como fallo y reintentamos.
2

Deduplica por webhook-id

La entrega es at-least-once: un mismo evento puede llegar más de una vez (un reintento tras un timeout, por ejemplo). El webhook-id es estable entre reintentos — guárdalo y descarta los repetidos.
3

No asumas orden

Los eventos no llegan garantizadamente en orden. Usa data.payment.uuid
  • status como la verdad, no el orden de llegada: un payment.registered que llegue tarde no debe pisar un payment.credited que ya procesaste.
4

Reintentos ~3 días

Un endpoint caído recibe reintentos con espaciado creciente durante ~3 días. Si sigue fallando, la suscripción se deshabilita automáticamente (tras 5 fallos consecutivos agotados) — la reactivas desde el dashboard.

Rotar el secret

Desde el dashboard puedes rotar el signing secret cuando quieras. Durante una gracia de 24 horas, cada webhook se firma con el secret nuevo y el anterior a la vez (dos firmas en el header). Así actualizas tu sistema sin perder ni rechazar eventos: valida contra cualquiera de las dos; cuando vence la gracia de 24 h, el secret anterior deja de firmarse automáticamente.

Comprobantes

En un pago manual, files[] lista los comprobantes subidos con referencias estables — uuid, name y mime_type — pero sin URL de descarga: el payload es un snapshot que se reintenta durante días y una URL firmada expiraría en el camino. La descarga del archivo se hace con tu API key por un endpoint autenticado (se documentará aquí cuando esté disponible); mientras tanto, el uuid te sirve para correlacionar el comprobante en el dashboard.

Próximos pasos

Autenticación

Cómo se autentica tu integración con la API key.

Errores

El contrato de errores de la API pública.