Outbound · Vos lo implementás
Webhook Spec
Este documento describe el contrato outbound que BipBip usa para entregar órdenes nuevas a tu POS. Es el endpoint que tu sistema debe implementar y exponer para que BipBip pueda llamarlo.
Esta es la contraparte de la REST API
Transport contract
Contrato de transporte cerrado — estos parámetros son fijos y no se negocian por merchant.
| Parámetro | Valor |
|---|---|
| Path de creación | POST {tuBaseUrl}/v1/order/{remoteId} |
| Path de eventos (multiplexed) | POST {tuBaseUrl}/v1/order/{remoteId}/{remoteOrderId} |
| Eventos en este path | order.cancelled, order.driver_assigned, order.delivered — distinguilos por X-Bipbip-Event-Type |
| Versionado | En el path (/v1/) — futuras versiones pueden correr en paralelo |
| Body | JSON — schemas Order, OrderCancellation, OrderDriverAssigned, OrderDelivered |
| Timeout | 30 segundos por intento |
| ACK (creación) | HTTP 200 con { remoteOrderId } — obligatorio |
| ACK (eventos) | HTTP 200 — body ignorado |
Headers firmados
BipBip firma cada request con HMAC-SHA256 sobre {timestamp}.{rawBody}
usando el secret compartido durante onboarding. Consultá la guía de verificación HMAC para el algoritmo completo y los code samples.
| Header | Descripción |
|---|---|
| X-Bipbip-Signature-256 | HMAC-SHA256 en formato sha256=<hex> (lowercase) |
| X-Bipbip-Timestamp | Unix epoch segundos. Rechazá si supera 300s de skew. |
| X-Bipbip-Event-Type | order.created, order.cancelled, order.driver_assigned o order.delivered — usalo para rutear al handler correcto |
| X-Bipbip-Delivery-Id | UUID único por dispatch. Usar para deduplicación. |
Política de reintentos
BipBip implementa at-least-once delivery con exponential backoff.
- 5xx o error de red → BipBip reintenta (hasta
maxRetries, default 5) - 4xx → terminal, BipBip no reintenta
- Timeout > 30s → trata el intento como fallo y reintenta
- HTTP 200 sin remoteOrderId → trata como fallo y reintenta
- Todos los reintentos llevan el mismo
X-Bipbip-Delivery-Id— deduplicá con ese UUID
Si agotás los reintentos
order.cancelled (si el creation llegó a tu POS alguna vez).
Endpoints
Tu POS debe exponer estos dos endpoints. El segundo path multiplexea tres tipos de evento — usá el header
X-Bipbip-Event-Type
para rutear al handler correcto.
/v1/order/{remoteId} Entrega de una orden nueva (order.created). Verificá la firma HMAC, deduplicá con X-Bipbip-Delivery-Id, persistí la orden en tu POS y respondé HTTP 200 con { remoteOrderId } en el body. El valor de remoteOrderId es obligatorio — BipBip lo usa para componer la URL de los eventos siguientes.
Example Response
{
"remoteOrderId": "POS-2026-04-11-00142"
} /v1/order/{remoteId}/{remoteOrderId} Eventos posteriores de una orden — multiplexa tres tipos según X-Bipbip-Event-Type: order.cancelled (cancelar la orden en tu POS), order.driver_assigned (driver asignado, informativo: actualizá la pantalla operativa si lo querés), order.delivered (entregada al cliente, terminal: marcala como entregada). Verificá HMAC, procesá el evento y respondé HTTP 200 (body ignorado). Solo se envían si el creation webhook llegó con éxito.
Eventos atados al éxito del creation
order.created) nunca llegó a tu POS con HTTP 200,
BipBip no envía ninguno de los eventos posteriores (cancelled,
driver_assigned,
delivered) para esa orden.
Schemas
Los cuerpos JSON que BipBip envía y el ACK que esperamos de vuelta.
Order
Payload enviado por BipBip en POST /v1/order/{remoteId}
(eventType order.created).
| Campo | Tipo | Descripción |
|---|---|---|
| orderKey | string | Identificador opaco BipBip (ord_ + 16 base62) |
| eventType | enum | Siempre order.created |
| occurredAt | ISO-8601 | Timestamp UTC del evento |
| correlationId | uuid | Trace ID para soporte/logs |
| customer | object | fullName, phone |
| delivery | object | address, latitude?, longitude? |
| totals | object | total, subTotal, taxes, deliveryCharge |
| items[] | array | productCode, name, quantity, price, tax, modifiers[] |
| comment | string? | Nota del cliente (puede ser null) |
| dateDelivery | ISO-8601 | Hora objetivo de entrega |
Ejemplo completo
{
"orderKey": "ord_7h3nXpQa2KvLmN9F",
"eventType": "order.created",
"occurredAt": "2026-04-11T15:42:00Z",
"correlationId": "5f8e4b2a-3c1d-4f9e-b8a7-2d6e1c4b5f9a",
"customer": {
"fullName": "Ana Martínez",
"phone": "+50499887766"
},
"delivery": {
"address": "Col. Lomas del Guijarro, calle 2, casa 15, Tegucigalpa",
"latitude": 14.0818,
"longitude": -87.2068
},
"totals": {
"total": 285.00,
"subTotal": 250.00,
"taxes": 35.00,
"deliveryCharge": 0.00
},
"items": [
{
"productCode": "BM-001",
"name": "Big Mac Combo",
"quantity": 2,
"price": 120.00,
"tax": 18.00,
"comments": "Sin cebolla",
"imageUrl": "https://cdn.bipbip.com/products/bm.png",
"modifiers": [
{ "name": "Extra queso", "price": 15.00, "quantity": 1 }
]
}
],
"comment": "Dejar en portería, favor llamar al llegar",
"dateDelivery": "2026-04-11T16:15:00Z"
} OrderCancellation
Payload enviado por BipBip en POST /v1/order/{remoteId}/{remoteOrderId}
cuando el cliente cancela una orden.
| Campo | Tipo | Descripción |
|---|---|---|
| orderKey | string | Identificador BipBip de la orden |
| remoteOrderId | string? | El que devolviste en el ACK original (también en el path) |
| cancelReasonId | integer? | Razón de cancelación (informativo, puede ser null) |
| previousStatus | enum | Pending / Accepted / Preparing / Ready / DriverAssigned / Unknown |
| origin | enum | Quién canceló: Customer (cliente final), Operator (operador BackOffice), Timeout (tu POS no aceptó a tiempo) o WebhookDlq (BipBip agotó reintentos del creation) |
| operatorUserName | string? | Username del operador BackOffice — solo presente cuando origin = Operator |
| occurredAt | ISO-8601 | Timestamp UTC de la cancelación |
Ejemplo
{
"orderKey": "ord_7h3nXpQa2KvLmN9F",
"remoteOrderId": "POS-2026-04-11-00142",
"cancelReasonId": 3,
"previousStatus": "Pending",
"origin": "Customer",
"occurredAt": "2026-04-11T15:52:00Z"
} OrderDriverAssigned
Payload enviado por BipBip en POST /v1/order/{remoteId}/{remoteOrderId}
con X-Bipbip-Event-Type: order.driver_assigned
cuando un repartidor se asigna a la orden. Es informativo — la orden sigue en su estado activo, no requiere acción más allá de actualizar la pantalla operativa si lo querés.
| Campo | Tipo | Descripción |
|---|---|---|
| orderKey | string | Identificador BipBip de la orden |
| remoteOrderId | string | El que devolviste en el ACK original (también en el path) |
| driver.id | integer | Identificador numérico del driver en BipBip |
| driver.fullName | string | Nombre completo del driver |
| driver.phone | string? | Teléfono internacional — puede ser null si el driver no lo registró o lo tiene privado |
| assignedAt | ISO-8601 | Timestamp UTC de la asignación |
Ejemplo
{
"orderKey": "ord_7h3nXpQa2KvLmN9F",
"remoteOrderId": "POS-2026-04-11-00142",
"driver": {
"id": 4218,
"fullName": "Juan Pérez",
"phone": "+50498765432"
},
"assignedAt": "2026-04-11T16:05:12Z"
} OrderDelivered
Payload enviado por BipBip en POST /v1/order/{remoteId}/{remoteOrderId}
con X-Bipbip-Event-Type: order.delivered
cuando la orden se entrega al cliente. Estado terminal — marcala como entregada en tu POS.
| Campo | Tipo | Descripción |
|---|---|---|
| orderKey | string | Identificador BipBip de la orden |
| remoteOrderId | string | El que devolviste en el ACK original (también en el path) |
| deliveredAt | ISO-8601 | Timestamp UTC de la entrega al cliente |
Ejemplo
{
"orderKey": "ord_7h3nXpQa2KvLmN9F",
"remoteOrderId": "POS-2026-04-11-00142",
"deliveredAt": "2026-04-11T16:18:30Z"
} OrderAck
Tu response al webhook de creación. Campo obligatorio: remoteOrderId.
{
"remoteOrderId": "POS-2026-04-11-00142"
} Sin remoteOrderId, BipBip reintenta
remoteOrderId null, vacío o ausente
se tratan como delivery fallido. BipBip retriará hasta agotar maxRetries.