Conector de Redes
OpenAPIAPI v0.1.0
Explorar documentación

Operar · Webhooks

Recibe eventos firmados y deduplicables.

Cada suscripción pertenece a tu cliente y ambiente. La entrega es al menos una vez: debes verificar la firma y procesar cada identificador de evento de forma idempotente.

Operaciones disponibles

GET/v1/webhook-subscriptionswebhooks:read

Listar suscripciones.

POST/v1/webhook-subscriptionswebhooks:write

Crear y recibir el secreto.

PATCH/v1/webhook-subscriptions/{id}webhooks:write

Modificar, pausar o rotar.

GET/v1/webhook-subscriptions/deliverieswebhooks:read

Consultar entregas.

POST/v1/webhook-subscriptions/deliveries/{id}/retrywebhooks:write

Reencolar una entrega.

Crear una suscripción

El destino debe ser HTTPS público. Se rechazan URLs con credenciales, fragmentos, localhost o direcciones privadas. Cada cliente puede mantener hasta 20 suscripciones activas. Antes de cada entrega, el worker vuelve a resolver el destino y no sigue redirecciones.

Crear suscripción
curl --request POST \
  --url "$API_BASE_URL/v1/webhook-subscriptions" \
  --header "Authorization: Bearer $SENDINGBAY_API_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "url": "https://hooks.example.com/sendingbay",
    "event_types": ["shipment.created", "shipment.modified", "shipment.incident_reported", "shipment.reverse_logistics_created", "tracking.updated"]
  }'
Respuesta inicial
HTTP/1.1 201 Created
Cache-Control: no-store
Pragma: no-cache

{
  "id": "3c5a3217-eb59-477c-a037-c2717ed41721",
  "url": "https://hooks.example.com/sendingbay",
  "event_types": ["shipment.created", "shipment.modified", "shipment.incident_reported", "shipment.reverse_logistics_created", "tracking.updated"],
  "active": true,
  "version": 1,
  "created_at": "2026-09-10T12:00:00Z",
  "updated_at": "2026-09-10T12:00:00Z",
  "signing_secret": "<guardar-inmediatamente>"
}

Eventos disponibles

shipment.accepted

Una operación asíncrona fue aceptada.

shipment.created

El envío quedó creado con referencia del transportista.

shipment.modified

Una modificación canónica quedó aplicada y auditada.

shipment.reverse_logistics_created

La recogida o devolución quedó confirmada; no incluye direcciones ni etiqueta.

shipment.incident_reported

El transportista aceptó el reporte; no incluye la descripción.

tracking.updated

Se añadió un evento de seguimiento nuevo y deduplicado.

Sobre del evento
{
  "id": "2eb8c30d-1981-41a2-b493-8d92e1bd8d8b",
  "type": "tracking.updated",
  "created_at": "2026-09-10T12:00:00Z",
  "data": {
    "shipment_id": "274a2a5d-fef4-4fc6-9057-39d8df258367",
    "status": "in_transit",
    "effective_at": "2026-09-10T11:58:00Z"
  }
}

El campo id se mantiene durante todos los reintentos. Registra los identificadores procesados y devuelve 2xxtambién cuando recibas un duplicado ya tratado correctamente.

Verificar antes de deserializar

Cada petición incluye Webhook-Id,Webhook-Timestamp en segundos Unix yWebhook-Signature con formato v1=<hex>. Firma el valor timestamp + "." + cuerpo HTTP exacto con HMAC-SHA256 y compara en tiempo constante.

Python · verificación HMAC
import hashlib
import hmac

expected = hmac.new(
    secret.encode(),
    timestamp.encode() + b"." + raw_body,
    hashlib.sha256,
).hexdigest()

valid = hmac.compare_digest(
    signature.removeprefix("v1="),
    expected,
)
  • Lee el cuerpo como bytes antes de transformarlo.
  • Rechaza timestamps fuera de una tolerancia breve.
  • Compara la firma en tiempo constante.
  • Deduplica por el id estable del evento.

Entrega y reintentos

  1. pendingLa entrega espera su primer intento o un reintento.
  2. processingUn worker tiene la entrega reservada temporalmente.
  3. deliveredEl destino respondió con un estado 2xx.
  4. dead_letterSe agotaron los intentos y requiere intervención.

Los fallos de red y respuestas no 2xx utilizan backoff exponencial. Después de corregir la causa puedes reencolar manualmente una entrega agotada. El reintento responde con 202 y una cabecera Location que identifica la entrega reencolada.

Reintentar una entrega
curl --request POST \
  --url "$API_BASE_URL/v1/webhook-subscriptions/deliveries/965fdb91-2473-4c91-97e3-8da401280992/retry" \
  --header "Authorization: Bearer $SENDINGBAY_API_TOKEN"

Consultar configuración y entregas

La lista de suscripciones no vuelve a incluir el secreto. Las entregas pueden filtrarse por subscription_id y admiten unlimit entre 1 y 200, con 100 por defecto.

Listar suscripciones
curl --request GET \
  --url "$API_BASE_URL/v1/webhook-subscriptions" \
  --header "Authorization: Bearer $SENDINGBAY_API_TOKEN"
Listar entregas de una suscripción
curl --request GET \
  --url "$API_BASE_URL/v1/webhook-subscriptions/deliveries?subscription_id=3c5a3217-eb59-477c-a037-c2717ed41721&limit=100" \
  --header "Authorization: Bearer $SENDINGBAY_API_TOKEN"

Cada entrega informa status, attempts,response_status, last_error,available_at y delivered_at. Los mensajes de error están sanitizados y no contienen el cuerpo completo del destino.

Rotar o pausar

Envía la versión observada como expected_version. Al rotar, guarda el nuevo secreto de la respuesta. Las entregas ya creadas conservan su versión de secreto, por lo que siguen siendo verificables.

Rotar el secreto
curl --request PATCH \
  --url "$API_BASE_URL/v1/webhook-subscriptions/3c5a3217-eb59-477c-a037-c2717ed41721" \
  --header "Authorization: Bearer $SENDINGBAY_API_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "expected_version": 1,
    "rotate_secret": true
  }'
Siguiente lectura

Controla el ritmo de tus solicitudes.

Ir a cuotas →