Saltar al contenido

Webhooks

Recibe notificaciones en tiempo real cuando ocurren eventos en tu cuenta.

Cómo funcionan los webhooks

  1. Registras una URL y los eventos que deseas recibir.
  2. Cuando ocurre un evento, enviamos un payload JSON mediante POST a tu URL.
  3. Tu endpoint debe devolver un código de estado 2xx en un máximo de 10 segundos.
  4. Si la entrega falla, reintentamos con retroceso exponencial (hasta 5 intentos en ~24 horas).

Registrar un webhook

curl https://api.facturacion.srs-ngr.com/v1/webhooks \
  -u sk_test_xxx: \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/facturacion",
    "eventos_suscritos": ["factura.timbrada", "factura.cancelada", "pago.creado"]
  }'
{
  "id": "wh_1a2b3c4d",
  "url": "https://your-app.com/webhooks/facturacion",
  "eventos_suscritos": ["factura.timbrada", "factura.cancelada", "pago.creado"],
  "secreto_firma": "whsec_a1b2c3d4e5f6..."
}
El secreto_firma solo se devuelve al momento de la creación. Guárdalo — lo necesitarás para verificar las firmas de los webhooks.

Tipos de eventos

EventoDisparador
factura.creadaBorrador de factura creado
factura.timbradaFactura timbrada exitosamente (tiene UUID)
factura.timbrado_fallidoEl PAC rechazó la factura
factura.canceladaFactura cancelada
factura.cancelacion_fallidaCancelación rechazada
pago.creadoPago registrado
certificado.por_vencerEl CSD vence en 30 días
certificado.vencidoEl CSD ha expirado

Payload del webhook

{
  "id": "evt_1a2b3c",
  "tipo": "factura.timbrada",
  "creado_en": "2026-03-14T10:30:01Z",
  "datos": {
    "id": "fac_1a2b3c4d",
    "uuid": "A1B2C3D4-E5F6-...",
    "estado": "timbrada",
    "total": "2320.00",
    ...
  }
}

Verificación de firmas

Cada entrega de webhook incluye un encabezado X-Facturacion-Firma que contiene una firma HMAC-SHA256 del cuerpo de la solicitud.

import hmac
import hashlib

def verify_signature(payload_body, signature_header, secret):
    expected = hmac.new(
        secret.encode('utf-8'),
        payload_body,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature_header)
func verifySignature(body []byte, signatureHeader, secret string) bool {
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write(body)
    expected := hex.EncodeToString(mac.Sum(nil))
    return hmac.Equal([]byte(expected), []byte(signatureHeader))
}

Política de reintentos

IntentoDemora
1Inmediato
25 minutos
330 minutos
42 horas
524 horas

Después de 5 intentos fallidos, la entrega se marca como fallida. Consulta el registro de eventos en el panel de control para reenviar eventos perdidos.