Webhooks, callbacks y entregas
Estado documental: Contrato propuesto. Las rutas, campos, límites y tiempos pasan a estado confirmado solo después de su implementación y verificación.
Objetivo: Documentar el registro de callbacks, sus entregas, firma, reintentos y eventos cliente.
Endpoints receptores
La empresa registra previamente uno o varios endpoints HTTPS. Las órdenes no aceptan URLs arbitrarias sin autorización.
| Audiencia | Método | Ruta propuesta | Uso | Idempotencia | Eventos o callbacks relacionados |
|---|---|---|---|---|---|
| Integración | POST |
/v1/webhook-endpoints |
Registrar receptor. | Obligatoria | webhook.endpoint_created |
| Integración | GET |
/v1/webhook-endpoints |
Listar receptores. | No | Ninguno |
| Integración | GET |
/v1/webhook-endpoints/{id} |
Consultar receptor. | No | Ninguno |
| Integración | PATCH |
/v1/webhook-endpoints/{id} |
Modificar URL, eventos o estado. | Obligatoria | webhook.endpoint_updated |
| Integración | DELETE |
/v1/webhook-endpoints/{id} |
Desactivar o eliminar. | Obligatoria | webhook.endpoint_deleted |
| Integración | POST |
/v1/webhook-endpoints/{id}/test |
Enviar evento de prueba. | Obligatoria | webhook.test_sent |
| Integración | POST |
/v1/webhook-endpoints/{id}/rotate-secret |
Rotar secreto. | Obligatoria | webhook.secret_rotated |
| Integración | POST |
/v1/webhook-endpoints/{id}/pause |
Pausar entregas. | Obligatoria | webhook.endpoint_paused |
| Integración | POST |
/v1/webhook-endpoints/{id}/resume |
Reanudar. | Obligatoria | webhook.endpoint_resumed |
Ejemplo: registrar receptor
POST /v1/webhook-endpoints
Idempotency-Key: 0846d8ad-a8a3-49bc-a7e8-f9d8f839783b
{
"url": "https://api.cliente.com/webhooks/yupy",
"events": [
"payment.reconciled",
"payment.amount_difference",
"payment.late_detected"
],
"active": true
}
{
"webhook_endpoint_id": "whe_01JXYZ",
"url": "https://api.cliente.com/webhooks/yupy",
"secret": "<SHOWN_ONCE>",
"status": "active",
"request_id": "req_01JXYZ"
}
Referencia opcional desde una orden
{
"webhook_endpoint_id": "whe_01JXYZ"
}
El ID debe pertenecer a la empresa y estar autorizado. No se acepta una URL arbitraria en cada operación.
Entregas y reintentos
| Audiencia | Método | Ruta propuesta | Uso | Idempotencia | Eventos o callbacks relacionados |
|---|---|---|---|---|---|
| Integración | GET |
/v1/webhook-deliveries |
Listar intentos. | No | Ninguno |
| Integración | GET |
/v1/webhook-deliveries/{delivery_id} |
Consultar intento. | No | Ninguno |
| Integración | POST |
/v1/webhook-deliveries/{delivery_id}/retry |
Reintentar intento fallido. | Obligatoria | webhook.delivery_retried |
| Integración | POST |
/v1/webhook-events/{event_id}/redeliver |
Reenviar evento a receptores seleccionados. | Obligatoria | webhook.event_redelivered |
Solicitud enviada por YUPY
POST /webhooks/yupy HTTP/1.1
Content-Type: application/json
Yupy-Event-Id: evt_01JXYZ
Yupy-Timestamp: 1784567890
Yupy-Signature: v1=<HEX_SIGNATURE>
{
"event_id": "evt_01JXYZ",
"event_type": "payment.reconciled",
"event_version": "1.0",
"created_at": "2026-07-20T14:40:00-05:00",
"data": {
"yupy_transaction_id": "ypt_01JXYZ",
"external_transaction_id": "ORDER-10482",
"state": {
"operational": "active",
"financial": "reconciled"
}
}
}
Respuesta esperada
HTTP/1.1 200 OK
{
"received": true
}
Firma propuesta
HMAC-SHA256(
webhook_secret,
timestamp + "." + raw_body
)
La firma se valida sobre el cuerpo original. Los nombres de headers y la tolerancia temporal permanecen propuestos hasta implementación.
Idempotencia de recepción
event_id ya procesado
→ no repetir efectos comerciales
→ responder 200
Catálogo inicial de eventos
payment.reported
payment.evidence_received
payment.evidence_processed
payment.detected
payment.reconciled
payment.amount_difference
payment.ambiguous
payment.late_detected
payment.review_required
payment.cancelled
payment.supplemental_order_created
checkout.created
checkout.opened
checkout.expired
checkout.revoked
shift.opened
shift.expiring
shift.closed
shift.auto_closed
delivery.queued
delivery.sent
delivery.delivered
delivery.failed
claim.created
claim.evidence_received
claim.resolved
case.created
case.resolved
refund.identified
refund.requested
refund.approved
refund.rejected
refund.pending_execution
refund.execution_failed
refund.completed
refund.cancelled
report.queued
report.ready
report.failed
Callbacks relacionados con endpoints principales
| Operación | Eventos posibles |
|---|---|
POST /v1/payment-orders |
payment.*, checkout.created, delivery.* |
POST /v1/payment-orders/{id}/payment-reported |
payment.reported |
POST /v1/payment-orders/{id}/evidence |
payment.evidence_received, payment.evidence_processed |
POST /v1/payment-orders/{id}/cancel |
payment.cancelled |
POST /v1/shifts |
shift.opened |
POST /v1/shifts/{id}/close |
shift.closed |
POST /v1/report-jobs |
report.queued, report.ready, report.failed |
POST /v1/refund-cases/{id}/execution-attempts |
refund.completed o refund.execution_failed |
Errores principales
| HTTP | Código | Descripción |
|---|---|---|
| 404 | webhook_endpoint_not_found |
Receptor inexistente. |
| 401 | webhook_signature_invalid |
Firma inválida en el receptor. |
| 401 | webhook_timestamp_invalid |
Timestamp fuera de tolerancia. |
| 404 | webhook_delivery_not_found |
Intento inexistente. |
| 409 | webhook_retry_not_allowed |
El intento no puede repetirse. |
| 422 | webhook_url_invalid |
URL no válida o no autorizada. |