Inbound · Vos la llamás
REST API Reference
Tu POS llama a BipBip para aceptar, rechazar, avanzar el estado y consultar órdenes. Esta es la contraparte del Webhook Spec: una vez que BipBip te entrega una orden, usás esta API para gestionar su ciclo de vida.
Base URL
https://api.bipbip.com.
Las rutas llevan prefijo /api/v1/ con versionado en el path.
Autenticación
Cada request debe incluir el header
X-Bipbip-Api-Key
con el valor entregado por el equipo BipBip durante el onboarding. No usamos Bearer tokens ni OAuth para esta API.
Para obtener tus API Keys, contactá al equipo BipBip en [email protected].
# Cada llamada debe llevar este header
curl -H "X-Bipbip-Api-Key: <tu-api-key>" \
https://api.bipbip.com/api/v1/Orders/<orderKey> Protegé tu API Key
Paths case-sensitive
/Orders/
va con O mayúscula literal — /orders/ devuelve 404.
Respetá el casing exacto de cada path documentado acá.
Idempotency-Key
Todas las mutaciones (/accept,
/reject,
/status)
requieren el header Idempotency-Key.
El valor debe ser un UUID v4 único por intento lógico.
- Misma key + mismo body dentro de las 24h → BipBip devuelve la respuesta en caché sin reejecutar.
- Misma key + body diferente → HTTP 409 Conflict.
- Key nueva → request procesado normalmente.
- Sin header en mutaciones → HTTP 422 Unprocessable Entity.
{
"type": "https://errors.bipbip.com/idempotency-conflict",
"title": "Idempotency conflict",
"detail": "Idempotency-Key reused with a different request body.",
"status": 409,
"traceId": "00-abc...",
"meta": null
} Rate limits
Los límites se aplican por API Key y están activos en todos los endpoints. Si los superás recibís HTTP 429 — implementá exponential backoff con jitter en tu cliente.
| Ventana | Límite | Estrategia |
|---|---|---|
| Ventana fija | 100 requests / min | Reset cada 60s |
| Ventana deslizante | 1.000 requests / hora | Evaluada continuamente |
Errores
La API sigue el formato RFC 7807 Problem Details. Todos los errores devuelven un body JSON con los campos
type,
title,
detail,
status,
traceId y
meta.
Para errores de validación (422), meta
incluye un mapa de campo → lista de mensajes.
| Código | Significado |
|---|---|
| 401 Unauthorized | API Key ausente o inválida |
| 404 Not Found | orderKey no existe o no pertenece al cliente autenticado |
| 409 Conflict | Idempotency-Key reutilizada con body diferente, orden en estado incorrecto para la transición, o transición inválida |
| 422 Unprocessable Entity | Datos inválidos en el body o falta el header Idempotency-Key. El campo meta.errors detalla los campos problemáticos. |
| 429 Too Many Requests | Rate limit superado — implementá backoff exponencial con jitter |
| 5xx | Error del servidor — reintentá con backoff |
Error genérico (401, 404, 409, 429)
{
"type": "https://errors.bipbip.com/not-found",
"title": "Order not found",
"detail": "The order ord_xxx does not exist or does not belong to the authenticated client.",
"status": 404,
"traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
"meta": null
} Error de validación (422)
{
"type": "https://errors.bipbip.com/validation",
"title": "Validation failed",
"detail": "One or more validation errors occurred.",
"status": 422,
"traceId": "00-abc...",
"meta": {
"errors": {
"reasonCode": ["The ReasonCode field is required."]
}
}
} Orders
Gestioná el ciclo de vida de las órdenes que BipBip te entregó por webhook. Los endpoints de mutación
requieren X-Bipbip-Api-Key
e Idempotency-Key.
/api/v1/Orders/{orderKey}/accept Transiciona la orden de pending a accepted. Cancela el job de timeout de aceptación y publica el evento order.accepted_by_external_merchant.v1. Body: { remoteOrderId?, estimatedPrepTimeMinutes? }. Idempotente: misma Idempotency-Key + mismo body → respuesta cacheada. Responde 202.
Example Response
{
"message": "Order accepted",
"data": {
"orderKey": "ord_7h3nXpQa2KvLmN9F",
"status": "accepted",
"acceptedAt": "2026-04-11T15:44:12Z",
"remoteOrderId": "POS-2026-04-11-00142"
}
} /api/v1/Orders/{orderKey}/reject Transiciona la orden de pending a rejected (terminal). Requiere un reasonCode (int) obligatorio. Body: { reasonCode*, reason?, notes? }. Publica el evento order.rejected_by_external_merchant.v1. Idempotente. Responde 202.
Example Response
{
"message": "Order rejected",
"data": {
"orderKey": "ord_7h3nXpQa2KvLmN9F",
"status": "rejected",
"rejectedAt": "2026-04-11T15:44:30Z",
"reason": "Producto agotado"
}
} /api/v1/Orders/{orderKey}/status Cambia el estado de una orden ya aceptada. Transiciones válidas: accepted → preparing → ready → handedOver. También permite cancelar (→ cancelled). Body: { newStatus* (MerchantStatus: pending/accepted/rejected/preparing/ready/handedOver/cancelled/driverAssigned), estimatedReadyAt? }. Publica order.status_changed_by_external_merchant.v1. Responde 202.
Example Response
{
"message": "Status updated",
"data": {
"orderKey": "ord_7h3nXpQa2KvLmN9F",
"status": "preparing",
"changedAt": "2026-04-11T15:47:00Z"
}
} /api/v1/Orders/{orderKey} Devuelve el snapshot completo de la orden: estado actual, timestamps de cada transición (receivedAt, acceptedAt?, rejectedAt?, preparingAt?, readyAt?, driverAssignedAt?, handedOverAt?, cancelledAt?) e historial completo de cambios. Solo retorna órdenes del cliente autenticado. No requiere Idempotency-Key. Responde 200.
Example Response
{
"message": "Ok",
"data": {
"orderKey": "ord_7h3nXpQa2KvLmN9F",
"storeId": 42,
"brandId": 7,
"status": "preparing",
"merchantStatusReason": null,
"remoteOrderId": "POS-2026-04-11-00142",
"receivedAt": "2026-04-11T15:42:00Z",
"acceptedAt": "2026-04-11T15:44:12Z",
"rejectedAt": null,
"preparingAt": "2026-04-11T15:47:00Z",
"readyAt": null,
"driverAssignedAt": null,
"handedOverAt": null,
"cancelledAt": null,
"history": [
{
"fromStatus": null,
"toStatus": "pending",
"changedAt": "2026-04-11T15:42:00Z",
"actorType": "system",
"actorId": null,
"reason": null
}
]
}
} /api/v1/Orders Lista órdenes del cliente autenticado con paginación por cursor opaco. Query params: Cursor?, PageSize? (máx 100), Status?, FromDate?, ToDate?. Ordenadas por fecha de creación descendente. Pasa nextCursor de la respuesta anterior para obtener la siguiente página. Responde 200.
Example Response
{
"message": "Ok",
"data": {
"items": [
{
"orderKey": "ord_7h3nXpQa2KvLmN9F",
"storeId": 42,
"status": "preparing",
"receivedAt": "2026-04-11T15:42:00Z",
"acceptedAt": "2026-04-11T15:44:12Z",
"remoteOrderId": "POS-2026-04-11-00142"
}
],
"nextCursor": "eyJsYXN0SWQiOjE3fQ",
"hasMore": true
}
} Máquina de estados
pending →
accepted /
rejected,
accepted →
preparing,
preparing →
ready →
handedOver.
El estado driverAssigned lo setea BipBip automáticamente entre ready y handedOver (el comercio no transiciona a este estado, solo lo lee).
Ver el glosario para detalles.
Nota: los valores de status
en la REST API son camelCase lowercase (ej: handedOver, driverAssigned),
distinto de los webhooks que usan PascalCase.