Volver al inicio

Documentación de la API

API REST para conectar Digimenu con tu punto de venta u otros sistemas. Disponible en el plan Empresarial.

Autenticación

API keys por organización, enviadas como Bearer token en cada request.

REST JSON

Requests y respuestas en JSON. Versión en la URL: /api/v1.

Webhooks

Aviso por POST firmado cuando entra un pedido o cambia de estado.

Autenticación

La base de todos los endpoints es https://digimenu.com.mx/api/v1. Cada request lleva una API key en el header Authorization. Las llaves se crean en el panel, en Ajustes → API y webhooks (requiere plan Empresarial con suscripción activa); la llave completa se muestra una sola vez al crearla.

curl https://digimenu.com.mx/api/v1/orders \
  -H "Authorization: Bearer dgm_TU_API_KEY"

Los errores siempre tienen la misma forma:

{
  "error": {
    "code": "invalid_api_key",
    "message": "API key no reconocida."
  }
}
  • 401 — falta el header, la llave no existe o fue revocada (missing_authorization, invalid_api_key, revoked_api_key).
  • 403 — suscripción inactiva o plan distinto a Empresarial (subscription_inactive, plan_required), o recurso de otra organización (forbidden).
  • 400 — parámetros o body inválidos; el code indica el campo (ej. invalid_status, missing_fields).
  • 404 — recurso no encontrado (not_found).
  • 500 — error interno (internal_error).

Endpoints

GET
/api/v1/menu/:slug

Menú completo de tu restaurante: categorías con productos, modificadores y promociones activas. El slug debe ser el de tu propia organización; de lo contrario responde 403.

{
  "data": {
    "organization": { "id": "...", "name": "...", "slug": "..." },
    "categories": [ ... ],
    "promotions": [ ... ]
  }
}
GET
/api/v1/orders

Pedidos de tu organización, ordenados del más reciente al más antiguo, con sus order_items anidados.

Query params (todos opcionales)

  • status — pending, pending_payment, confirmed, preparing, ready, on_the_way, delivered, cancelled
  • type — pickup, delivery, dine_in
  • from / to — fechas ISO; filtran por created_at
  • limit — default 50, máximo 100
  • offset — default 0, para paginar
GET /api/v1/orders?status=pending&limit=20

{
  "data": [ { "id": "...", "order_number": "ORD-0042", "status": "pending", "order_items": [ ... ], ... } ],
  "pagination": { "total": 132, "limit": 20, "offset": 0 }
}
POST
/api/v1/orders

Crea un pedido para tu organización. Los montos se recalculan del lado del servidor con los precios actuales de tu menú: si subtotal o total no coinciden, el pedido se rechaza. El pedido siempre inicia en estado pending y el folio (order_number) lo asigna Digimenu.

{
  "customer_name": "Ana López",            // obligatorio
  "customer_phone": "2221234567",           // obligatorio
  "order_type": "pickup",                   // obligatorio: pickup | delivery | dine_in
  "items": [                                // obligatorio, 1 a 50 productos
    {
      "product_id": "uuid-del-producto",    // obligatorio
      "quantity": 2,                        // obligatorio, entero 1-100
      "modifiers_json": { "grupoId": ["opcionId"] },  // opcional
      "modifiers_summary": "Sin cebolla"    // opcional
    }
  ],
  "subtotal": 180.0,                        // obligatorio, se verifica contra la BD
  "shipping_cost": 0,                       // obligatorio (0 si no aplica)
  "tip": 0,                                 // obligatorio (0 si no aplica)
  "total": 180.0,                           // obligatorio, subtotal + envío + propina - descuento
  "payment_method": "cash",                 // obligatorio: cash | card | transfer
  "delivery_address": "...",                // opcional (pedidos a domicilio)
  "delivery_lat": 19.04, "delivery_lng": -98.2,  // opcionales
  "notes": "Tocar el timbre",               // opcional, máx. 500 caracteres
  "coupon_code": "PROMO10",                 // opcional; requiere discount_amount
  "discount_amount": 18.0,                  // opcional, se valida contra el cupón
  "table_id": "...", "table_name": "..."    // opcionales (pedidos en mesa)
}

Responde 201 con { "data": { ...pedido } }. Si algo no cuadra (producto inactivo, montos, cupón), responde 400 con order_rejected y el motivo.

PATCH
/api/v1/orders/:id/status

Actualiza el estado de un pedido de tu organización. Los pedidos de otras organizaciones responden 404.

PATCH /api/v1/orders/9b2e.../status
{ "status": "preparing" }

// status válidos:
// pending, pending_payment, confirmed, preparing,
// ready, on_the_way, delivered, cancelled

Responde { "data": { ...pedido actualizado } }.

Webhooks

Configura tu endpoint en Ajustes → API y webhooks. Digimenu manda un POST en JSON por cada evento suscrito. Hay dos eventos:

  • order.created — entra un pedido nuevo. data trae { order }.
  • order.status_updated — un pedido cambia de estado. data trae { order, previous_status }.

Body de la entrega

POST https://tusistema.com/webhooks/digimenu
Content-Type: application/json
X-Digimenu-Event: order.created
X-Digimenu-Signature: 3f1a9c... (HMAC-SHA256 hex del body)

{
  "event": "order.created",
  "created_at": "2026-08-26T18:30:00.000Z",
  "data": {
    "order": { "id": "...", "order_number": "ORD-0042", "status": "pending", ... }
  }
}

Verificar la firma

La firma es el HMAC-SHA256 (hex) del body crudo, calculado con el secreto que ves en Ajustes → API y webhooks. Verifícala antes de procesar el evento:

// Node.js
const crypto = require("node:crypto");

function verifyDigimenuSignature(rawBody, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");
  return (
    signature.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(signature, "hex"))
  );
}

Tu endpoint debe responder 2xx en menos de 5 segundos. Si falla, se reintenta una vez; si vuelve a fallar, la entrega se descarta y se registra en el contador de fallos del panel.

La API está disponible en el plan Empresarial. Si tienes dudas sobre la integración, escríbenos.

Escríbenos