Skip to main content
Registra una URL HTTPS de tu servidor y te avisamos cuando cambia el estado de un e-CF ante la DGII, sin que tengas que consultar.

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 de ecf.accepted, ecf.rejected y ecf.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

Un POST 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 un POST a tu URL. Antes de procesar una entrega:
  1. 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 401 y descártala.
  2. Rechaza entregas viejas: si timestamp tiene más de 5 minutos.
  3. Deduplica por deliveryId: un reintento trae el mismo deliveryId; si ya lo procesaste, responde 200 sin repetir el trabajo.

Responde rápido

Responde 2xx 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 timestamp nuevo, y conserva el mismo deliveryId. Por eso un reintento horas después pasa la regla de los 5 minutos.
  • Un deliveryId por webhook y por evento. Si dos webhooks tuyos reciben el mismo evento, cada uno tiene su propio deliveryId.
  • Guarda los deliveryId procesados al menos 27 horas, lo que dura el ciclo completo de reintentos. Para no procesar dos veces, marca el deliveryId y 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.occurredAt o 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-Key y el mismo cuerpo, la respuesta vuelve a traer el mismo secreto.
  • Si se agotan los intentos, la entrega queda como failed en GET /v1/webhooks/{id}. Para no perder estados, concilia periódicamente con GET /v1/invoices.