Webhook


Cuando una empresa tiene habilitado el POS externo, NubeFood notifica cada orden enviando un POST a la URL de callback que configuraste. Este documento describe cómo configurar tu webhook y el payload que enviamos.

Configurar el webhook

Podés configurar tu propio webhook (URL de callback + secret) con tu access token (Authorization: Bearer <access token>). El endpoint opera sobre el webhook de tu empresa (el companyId sale del token). Hay un webhook por empresa: PUT lo crea o lo reemplaza.

Cuerpo de la consulta

callbackUrlstring

URL a la que enviaremos las notificaciones (http/https).

Required
secretstring

Secreto que enviaremos en el header x-webhook-secret. Enviá "" para limpiarlo; si se omite, se conserva el actual.

Optional
activeboolean

Habilita/deshabilita el envío (default true al crear).

Optional

Ejemplo.

curl -v -X PUT
    --url 'https://api.public.lumarketo.cl/webhook'
    --header 'Authorization: Bearer <access_token>'
    --data '{ "callbackUrl": "https://tu-pos.com/webhook", "secret": "un-secreto-compartido" }'

Respuesta: { success, message, data: { callbackUrl, active, hasSecret } }.

Para consultar la configuración actual (sin exponer el secret):

Devuelve { callbackUrl, active, hasSecret } (o data: null si no hay webhook configurado).

La solicitud que enviamos

POST
<tu-callbackUrl>
  • Método: POST
  • Content-Type: application/json
  • Cuerpo: el objeto de la orden normalizada (ver estructura abajo).
  • Disparo: al crear/confirmar la orden y en cada cambio de estado (mientras el webhook esté activo). Cada notificación trae el snapshot de la orden con su status actual.

Tu endpoint debe responder 2xx para confirmar la recepción.

Validación de origen (header secreto)

Si configuraste un secret para el webhook, cada request incluye el header:

x-webhook-secret: <tu-secret>

Validá ese header en tu endpoint y rechazá las solicitudes cuyo valor no coincida con el secret acordado. Si no configuraste un secret, el header no se envía.

Estructura del cuerpo

storeobject

Sucursal de la orden.

externalIdstring

extId de integración de la sucursal (o el id interno si no tiene extId).

internalOrderIdstring

ID interno de la orden en NubeFood.

statusstring

Estado actual de la orden en el momento de la notificación (cambia en cada cambio de estado). Ver 'Estados posibles' más abajo.

codenumber

Número de orden correlativo de la empresa (companyOrderNumber).

websiteIdstring

ID de la empresa (company) dueña de la orden.

namestring

Nombre legible de la orden: '#{code} - {nombre cliente} - {deliveryType} - Nubefood'.

createdAtstring

Fecha de creación de la orden (ISO).

deliveryTypestring

'delivery' si la orden tiene envío; 'pickup' si es retiro.

amountToPaynumber

Total a pagar de la orden (incluye envío).

amountnumber

Total de los productos, sin el costo de envío (total − deliveryFee).

deliveryFeenumber

Costo de envío.

couponDiscountnumber

Descuento aplicado por cupón.

deliveryTimestring

Fecha/hora de entrega estimada (o '' si no aplica).

isScheduledboolean

true si la orden es programada.

scheduledDatestring

Fecha programada (solo presente si isScheduled = true).

addressobject

Dirección de entrega. Solo se incluye cuando deliveryType = 'delivery'.

latnumber

Latitud.

lngnumber

Longitud.

addressstring

Dirección completa.

streetNumberstring

Número.

streetAddressstring

Calle.

countrystring

País.

statestring

Región/estado.

citystring

Ciudad.

zipCodestring

Código postal.

phoneNumberstring

Teléfono de contacto.

detailsstring

Detalles adicionales (depto, referencia, etc.).

userobject

Datos del cliente.

firstNamestring

Nombre.

lastNamestring

Apellido.

emailstring

Email.

phoneNumberstring

Teléfono.

itemsarray

Productos de la orden.

productobject

Producto.

externalIdstring

extId de integración del producto para esa sucursal. Es null si el ítem tiene modificadores/adicionales.

namestring

Nombre del producto.

amountnumber

Cantidad pedida del producto.

commentstring

Instrucciones/comentario del ítem.

unitPricenumber

Precio unitario final (con descuentos): bestPrice / cantidad.

baseUnitPricenumber

Precio unitario de lista (sin descuentos): price / cantidad.

productPricenumber

Precio final del ítem incluyendo adicionales (bestPrice + adicionales).

productBasePricenumber

Precio de lista del ítem incluyendo adicionales (price + adicionales).

modifiersarray

Adicionales/modificadores del ítem.

externalIdstring

Reservado (actualmente null a nivel modificador).

namestring

Nombre del modificador.

shortNamestring

Nombre corto del modificador.

countByIdobject

Mapa { modifierId: cantidad }.

countByExternalIdobject

Mapa { extId: cantidad } (extId de integración del modificador para la sucursal).

optionsarray

Opciones del modificador: { optionId, externalId, name, price }.

Estados posibles (status)

El campo status puede tomar estos valores (ciclo de vida de la orden):

statusSignificado
pendingEsperando confirmación del método de pago
payment-pendingEn espera del pago
payment-approvedEl pago fue aprobado
payment-canceledEl pago fue cancelado u ocurrió un error
picker-pendingPendiente (por tomar)
inProcessEn proceso (aceptada / en preparación)
readyLista para despachar
routedEn camino (delivery con el pedido)
dispatchedEntregado
cancelCancelada
refundReembolsada
shippingErrorError en el envío

Ejemplo

{
  "store": { "externalId": "1546626" },
  "internalOrderId": "652f0a1b2c3d4e5f60718293",
  "status": "inProcess",
  "couponDiscount": 0,
  "amountToPay": 15900,
  "deliveryFee": 2500,
  "amount": 13400,
  "websiteId": "63ebadc353f9eb8978f057a0",
  "code": 1042,
  "createdAt": "2026-07-22T18:30:00.000Z",
  "deliveryTime": "2026-07-22T19:15:00.000Z",
  "isScheduled": false,
  "deliveryType": "delivery",
  "address": {
    "lat": -33.4489,
    "lng": -70.6693,
    "address": "Av. Siempre Viva 742, Santiago",
    "streetNumber": "742",
    "streetAddress": "Av. Siempre Viva",
    "country": "CL",
    "state": "Región Metropolitana",
    "city": "Santiago",
    "zipCode": "",
    "phoneNumber": "+56912345678",
    "details": "Depto 4B"
  },
  "user": {
    "firstName": "Juan",
    "lastName": "Pérez",
    "email": "juan.perez@mail.com",
    "phoneNumber": "+56912345678"
  },
  "name": "#1042 - Juan Pérez - delivery - Nubefood",
  "items": [
    {
      "product": { "externalId": "777", "name": "Hamburguesa clásica" },
      "comment": "Sin cebolla",
      "amount": 2,
      "unitPrice": 5450,
      "baseUnitPrice": 5950,
      "productPrice": 11900,
      "productBasePrice": 11900,
      "modifiers": [
        {
          "externalId": null,
          "name": "Extra queso",
          "shortName": "Extra queso",
          "description": [],
          "countById": { "652a1b2c3d4e5f6071829300": 1 },
          "countByExternalId": { "Q-01": 1 },
          "options": [
            {
              "optionId": "652a1b2c3d4e5f6071829300",
              "externalId": "Q-01",
              "name": "Extra queso",
              "price": 500
            }
          ]
        }
      ]
    }
  ]
}

Notas: el campo address solo viene en órdenes de delivery. En pickup se omite. Los importes van en la moneda de la empresa. El externalId de producto/modificador corresponde al id de integración (Fudo/Toteat) mapeado para esa sucursal.