Registrar un webhook
url: HTTPS, hasta 2048 caracteres. Solo entregamos a direcciones públicas en el puerto 443 u 8443, y no seguimos redirecciones.events: al menos uno deecf.accepted,ecf.rejectedyecf.cancelled, sin repetir.
El secret solo se devuelve en esta respuesta. Guárdalo de inmediato en tu gestor de secretos: con él verificas cada entrega. Si lo pierdes, borra el webhook y crea otro.
Para probar tu endpoint: POST /v1/webhooks/{id}/test envía un evento test y te dice si respondió 2xx. Para pausarlo sin borrarlo: PATCH /v1/webhooks/{id} con { "active": false }. GET /v1/webhooks/{id} muestra las entregas recientes con su estado (delivered, pending o failed) y sus intentos.
Mientras desarrollas en tu computadora, tu servidor local no es alcanzable desde internet. Expón tu puerto con un túnel HTTPS (por ejemplo, el de tu proveedor de nube o una herramienta de túneles) y registra esa URL en el sandbox. No lo dejes abierto más de lo necesario.
Qué recibes
UnPOST con cuerpo JSON:
Los eventos son livianos: para el detalle consulta el documento según
data.documentType, con GET /v1/invoices/{id}, GET /v1/notes/{id} o GET /v1/special-documents/{id}.
Verifica cada entrega
Cualquiera puede enviar unPOST a tu URL. Antes de procesar una entrega:
- Verifica la firma sobre el cuerpo crudo, antes de parsear el JSON (re-serializarlo cambia los bytes y la firma), con una comparación en tiempo constante. Si no coincide, responde
401y descártala. - Rechaza entregas viejas: si
timestamptiene más de 5 minutos. - Deduplica por
deliveryId: un reintento trae el mismodeliveryId; si ya lo procesaste, responde200sin repetir el trabajo.
Responde rápido
Responde2xx en menos de 10 segundos; si tu proceso tarda más, encólalo y responde de inmediato. Cualquier otra respuesta, un error de conexión o pasar de 10 segundos cuentan como fallo.
Después de cada fallo esperamos antes del siguiente intento: 1 minuto, luego 5 minutos, 30 minutos, 2 horas y 24 horas, hasta 6 intentos en total. Las esperas se suman: el último intento llega unas 26 horas y 36 minutos después del primero. Cada espera puede alargarse hasta un minuto.
Garantías de entrega
- Cada intento se firma de nuevo, con un
timestampnuevo, y conserva el mismodeliveryId. Por eso un reintento horas después pasa la regla de los 5 minutos. - Un
deliveryIdpor webhook y por evento. Si dos webhooks tuyos reciben el mismo evento, cada uno tiene su propiodeliveryId. - Guarda los
deliveryIdprocesados al menos 27 horas, lo que dura el ciclo completo de reintentos. Para no procesar dos veces, marca eldeliveryIdy encola el trabajo en la misma transacción de tu base de datos. - No garantizamos el orden. Un reintento puede llegar después de un evento más reciente. Usa
data.occurredAto consulta el documento para saber su estado actual. - Al menos una vez, no exactamente una vez: una entrega que tu servidor procesó, pero cuya respuesta no nos llegó, se repite con el mismo
deliveryId. - El secreto son 64 caracteres hexadecimales. Úsalo tal cual, como texto, como clave del HMAC (no lo decodifiques a bytes). Si reintentas el registro con la misma
Idempotency-Keyy el mismo cuerpo, la respuesta vuelve a traer el mismo secreto. - Si se agotan los intentos, la entrega queda como
failedenGET /v1/webhooks/{id}. Para no perder estados, concilia periódicamente conGET /v1/invoices.