Referencia de la API de webhooks
Referencia completa del endpoint de la API de webhooks.
URL base
https://api.orcarail.com/api/v1
Recibir un webhook
Recibe eventos de webhook de OrcaRail.
POST /webhooks
Autenticación
- Clave de API (Basic Auth): opcional, pero recomendada
Cabeceras
| Cabecera | Tipo | Obligatoria | Descripción |
|---|---|---|---|
x-webhook-signature | string | Condicional | Firma HMAC SHA-256 (obligatoria si PAYMENTS_WEBHOOK_SECRET está definida) |
Content-Type | string | Sí | Debe ser application/json |
Cuerpo de la petición
{
"type": "payment_intent.completed",
"data": {
"object": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"amount": "100.00",
"currency": "usd",
"status": "succeeded",
"metadata": {
"order_id": "12345"
}
}
}
}
Respuesta
Devuelve siempre 200 OK de inmediato:
{
"received": true
}
Eventos de webhook
| Tipo de evento | Descripción |
|---|---|
payment_intent.completed | El Payment Intent se ha completado |
payment_intent.processing | El Payment Intent se está procesando |
payment_intent.canceled | El Payment Intent se ha cancelado |
payment_intent.requires_payment_method | El Payment Intent necesita un método de pago |
Verificación de la firma
Si PAYMENTS_WEBHOOK_SECRET está configurada, verifica la firma:
- Obtén la firma de la cabecera
x-webhook-signature - Calcula el HMAC SHA-256 del cuerpo de la petición con tu secreto
- Compara las firmas con una comparación de tiempo constante
Ejemplo: Node.js
const crypto = require('crypto')
function verifySignature(receivedSignature, payload, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex')
const receivedBuffer = Buffer.from(receivedSignature)
const expectedBuffer = Buffer.from(expectedSignature)
if (receivedBuffer.length !== expectedBuffer.length) {
return false
}
return crypto.timingSafeEqual(receivedBuffer, expectedBuffer)
}
Requisitos de la respuesta
Respuesta correcta
Devuelve siempre 200 OK con {"received": true} de inmediato, aunque falle el procesamiento:
{
"received": true
}
Respuesta de error
Si falla la verificación de la firma, devuelve 400 Bad Request:
{
"statusCode": 400,
"message": "Invalid webhook signature",
"error": "Bad Request"
}
Lógica de reintentos
Si tu endpoint devuelve un código distinto de 200 o no responde, OrcaRail reintentará el webhook:
- Intentos máximos: 3 intentos (1 inicial + 2 reintentos)
- Estrategia de espera: backoff exponencial que empieza en 2 segundos
- Tiempo de espera: 10 segundos por petición
Buenas prácticas
- Responde rápido: devuelve
200 OKen menos de 10 segundos (el tiempo de espera es de 10 segundos) - Procesa de forma asíncrona: gestiona los eventos en trabajos en segundo plano
- Verifica las firmas: verifica siempre las firmas de los webhooks
- Haz los gestores idempotentes: gestiona bien los eventos duplicados
- Registra los eventos: registra todos los eventos recibidos para depurar
Pruebas
Prueba tu endpoint de webhook:
curl -X POST https://your-webhook-url.com/webhooks/orcarail \
-H "Content-Type: application/json" \
-H "x-webhook-signature: test-signature" \
-d '{
"type": "payment_intent.completed",
"data": {
"object": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"amount": "100.00",
"currency": "usd",
"status": "succeeded"
}
}
}'
Webhook de prueba
Envía un evento de webhook de prueba a tu URL de webhook configurada.
POST /webhooks/test/:apiKeyId
Autenticación
- Token Bearer (JWT): obligatorio
Parámetros de ruta
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
apiKeyId | number | Sí | ID de la clave de API |
Respuesta
{
"success": true
}
Respuestas de error
404 Not Found: no se encuentra la clave de API o no hay URL de webhook configurada:
{
"statusCode": 404,
"message": "Webhook URL not configured for this API key",
"error": "Not Found"
}
Enviar un webhook personalizado
Envía un payload de webhook personalizado a tu URL de webhook configurada.
POST /webhooks/test/:apiKeyId/custom
Autenticación
- Token Bearer (JWT): obligatorio
Parámetros de ruta
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
apiKeyId | number | Sí | ID de la clave de API |
Cuerpo de la petición
{
"payload": {
"type": "payment_intent.completed",
"data": {
"object": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"amount": "100.00",
"currency": "usd",
"status": "succeeded"
}
}
}
}
Respuesta
{
"success": true
}
Obtener los registros de webhooks
Obtén los registros de entrega de webhooks de tu cuenta.
GET /webhooks/logs
Autenticación
- Token Bearer (JWT): obligatorio
Parámetros de consulta
| Parámetro | Tipo | Por defecto | Descripción |
|---|---|---|---|
limit | number | 50 | Número de registros que se devuelven |
offset | number | 0 | Número de registros que se omiten |
Respuesta
{
"logs": [
{
"id": 1,
"apiKeyId": 1,
"userId": 1,
"event": "payment_intent.completed",
"url": "https://api.example.com/webhooks/orcarail",
"statusCode": 200,
"success": true,
"attemptNumber": 1,
"createdAt": "2024-01-01T00:00:00.000Z"
}
],
"total": 1
}
Campos del objeto de registro
| Campo | Tipo | Descripción |
|---|---|---|
id | number | Identificador único del registro |
apiKeyId | number | ID de la clave de API que disparó el webhook |
userId | number | ID del usuario propietario de la clave de API |
event | string | Tipo de evento (por ejemplo payment_intent.completed) |
url | string | URL de webhook a la que se llamó |
statusCode | number | Código de estado HTTP devuelto por el endpoint del webhook |
success | boolean | Si el webhook se entregó correctamente |
attemptNumber | number | Número de intento (1, 2 o 3) |
error | string | Mensaje de error si falló la entrega |
response | string | Cuerpo de la respuesta del endpoint del webhook |
createdAt | string | Marca de tiempo ISO 8601 de creación del registro |
Consulta también
- Guía de webhooks: documentación detallada de los webhooks
- Configuración de webhooks: configura webhooks para las claves de API
- Eventos de webhook: todos los eventos disponibles
- Firmas de webhooks: verificación de firmas