Outbound · You implement it

Webhook Spec

This document describes the outbound contract BipBip uses to deliver new orders to your POS. It is the endpoint that your system must implement and expose so BipBip can call it.

This is the counterpart to the REST API

BipBip → your POS = webhook (this page). Your POS → BipBip = REST API. The integration guide explains how they fit together.

Transport contract

Fixed transport contract — these parameters are non-negotiable and are not customized per merchant.

Parameter Value
Creation path POST {yourBaseUrl}/v1/order/{remoteId}
Events path (multiplexed) POST {yourBaseUrl}/v1/order/{remoteId}/{remoteOrderId}
Events on this path order.cancelled, order.driver_assigned, order.delivered — distinguish by X-Bipbip-Event-Type
Versioning In the path (/v1/) — future versions can run in parallel
Body JSON — Order, OrderCancellation, OrderDriverAssigned, OrderDelivered schemas
Timeout 30 seconds per attempt
ACK (creation) HTTP 200 with { remoteOrderId } — required
ACK (events) HTTP 200 — body ignored

Signed headers

BipBip signs each request with HMAC-SHA256 over {timestamp}.{rawBody} using the shared secret provided during onboarding. See the HMAC verification guide for the full algorithm and code samples.

Header Description
X-Bipbip-Signature-256 HMAC-SHA256 in sha256=<hex> format (lowercase)
X-Bipbip-Timestamp Unix epoch in seconds. Reject if skew exceeds 300s.
X-Bipbip-Event-Type order.created, order.cancelled, order.driver_assigned, or order.delivered — use it to route to the correct handler
X-Bipbip-Delivery-Id Unique UUID per dispatch. Use for deduplication.

Retry policy

BipBip implements at-least-once delivery with exponential backoff.

  • 5xx or network error → BipBip retries (up to maxRetries, default 5)
  • 4xx → terminal, BipBip does not retry
  • Timeout > 30s → treats the attempt as a failure and retries
  • HTTP 200 without remoteOrderId → treats as failure and retries
  • All retries carry the same X-Bipbip-Delivery-Id — deduplicate using that UUID

If retries are exhausted

If BipBip exhausts all retries without success, the order is automatically cancelled and an order.cancelled webhook is sent (if the creation webhook ever reached your POS).

Endpoints

Your POS must expose these two endpoints. The second path multiplexes three event types — use the X-Bipbip-Event-Type header to route to the correct handler.

POST /v1/order/{remoteId}

Delivery of a new order (order.created). Verify the HMAC signature, deduplicate with X-Bipbip-Delivery-Id, persist the order in your POS, and respond HTTP 200 with { remoteOrderId } in the body. The remoteOrderId value is required — BipBip uses it to compose the URLs of subsequent events.

Example Response
{
  "remoteOrderId": "POS-2026-04-11-00142"
}
POST /v1/order/{remoteId}/{remoteOrderId}

Subsequent order events — multiplexes three types based on X-Bipbip-Event-Type: order.cancelled (cancel the order in your POS), order.driver_assigned (driver assigned, informational: optionally update your operational view), order.delivered (delivered to customer, terminal: mark as delivered). Verify HMAC, process the event, and respond HTTP 200 (body ignored). Only sent if the creation webhook was delivered successfully.

Subsequent events depend on creation success

If the creation webhook (order.created) never reached your POS with HTTP 200, BipBip will not send any of the subsequent events (cancelled, driver_assigned, delivered) for that order.

Schemas

The JSON bodies BipBip sends and the ACK it expects in return.

Order

Payload sent by BipBip on POST /v1/order/{remoteId} (eventType order.created).

Field Type Description
orderKeystringOpaque BipBip identifier (ord_ + 16 base62)
eventTypeenumAlways order.created
occurredAtISO-8601UTC timestamp of the event
correlationIduuidTrace ID for support and logging
customerobjectfullName, phone
deliveryobjectaddress, latitude?, longitude?
totalsobjecttotal, subTotal, taxes, deliveryCharge
items[]arrayproductCode, name, quantity, price, tax, modifiers[]
commentstring?Customer note (may be null)
dateDeliveryISO-8601Target delivery time
Full example
{
  "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 sent by BipBip on POST /v1/order/{remoteId}/{remoteOrderId} when a customer cancels an order.

Field Type Description
orderKeystringBipBip order identifier
remoteOrderIdstring?The value you returned in the original ACK (also present in the path)
cancelReasonIdinteger?Cancellation reason (informational, may be null)
previousStatusenumPending / Accepted / Preparing / Ready / DriverAssigned / Unknown
originenumWho cancelled: Customer (end customer), Operator (BackOffice operator), Timeout (your POS did not accept in time), or WebhookDlq (BipBip exhausted creation retries)
operatorUserNamestring?BackOffice operator username — only present when origin = Operator
occurredAtISO-8601UTC timestamp of the cancellation
Example
{
  "orderKey": "ord_7h3nXpQa2KvLmN9F",
  "remoteOrderId": "POS-2026-04-11-00142",
  "cancelReasonId": 3,
  "previousStatus": "Pending",
  "origin": "Customer",
  "occurredAt": "2026-04-11T15:52:00Z"
}

OrderDriverAssigned

Payload sent by BipBip on POST /v1/order/{remoteId}/{remoteOrderId} with X-Bipbip-Event-Type: order.driver_assigned when a driver has been assigned to pick up the order. Informational — the order remains in its active state; no action required beyond optionally updating your operational view.

Field Type Description
orderKeystringBipBip order identifier
remoteOrderIdstringThe value you returned in the original ACK (also present in the path)
driver.idintegerNumeric BipBip driver identifier
driver.fullNamestringDriver's full name
driver.phonestring?International phone number — may be null if unregistered or marked private
assignedAtISO-8601UTC timestamp when the driver was assigned
Example
{
  "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 sent by BipBip on POST /v1/order/{remoteId}/{remoteOrderId} with X-Bipbip-Event-Type: order.delivered when the order has been delivered to the customer. Terminal state — mark the order as delivered in your POS.

Field Type Description
orderKeystringBipBip order identifier
remoteOrderIdstringThe value you returned in the original ACK (also present in the path)
deliveredAtISO-8601UTC timestamp when the order was delivered to the customer
Example
{
  "orderKey": "ord_7h3nXpQa2KvLmN9F",
  "remoteOrderId": "POS-2026-04-11-00142",
  "deliveredAt": "2026-04-11T16:18:30Z"
}

OrderAck

Your response to the creation webhook. Required field: remoteOrderId.

{
  "remoteOrderId": "POS-2026-04-11-00142"
}

Without remoteOrderId, BipBip retries

Responses with remoteOrderId null, empty, or absent are treated as a failed delivery. BipBip will retry until maxRetries is exhausted.