Referencia de la API v1

Base https://kmand.mx/api/v1. Convenciones, errores y webhooks en la guía; el contrato completo en openapi.json.

Endpoints

Llave

GET/yo· Tu llave

Modo (en vivo o prueba), alcances, restaurantes a los que llega y la cuota del minuto. Útil para probar la llave.

Alcance: cualquier llave

curl y JavaScript
curl "https://kmand.mx/api/v1/yo" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/yo", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos } = await r.json();
Respuesta 200 (UnaLlave)
{
  "datos": {
    "llave_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "modo": "live",
    "organizacion_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
    "alcances": [],
    "restaurantes": [],
    "cuota": {
      "limite_por_minuto": 120,
      "restantes": 118,
      "reinicio": 1759190460
    }
  }
}

Restaurantes

GET/restaurantes· Restaurantes y sucursales

Los que la llave alcanza: una sucursal, todas las de la organización (y su menú maestro) o el sandbox.

Alcance: cualquier llave

curl y JavaScript
curl "https://kmand.mx/api/v1/restaurantes" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/restaurantes", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaRestaurantes)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "organizacion_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
      "nombre": "<nombre>",
      "slug": "<slug>",
      "zona_horaria": "<zona_horaria>",
      "moneda": "<moneda>",
      "direccion": "<direccion>",
      "telefono": "<telefono>",
      "razon_social": "<razon_social>",
      "rfc": "<rfc>",
      "iva_pct": 16,
      "es_maestro": true,
      "es_cocina_central": true,
      "es_sandbox": true,
      "activo": true,
      "modulos": [],
      "actualizado_at": "2026-09-29T14:05:00.000-06:00"
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

GET/restaurantes/{id}· Un restaurante

Alcance: cualquier llave

ParámetroTipoDescripción
id *en la rutauuid
curl y JavaScript
curl "https://kmand.mx/api/v1/restaurantes/:id" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch(`https://kmand.mx/api/v1/restaurantes/${id}`, {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos } = await r.json();
Respuesta 200 (UnRestaurante)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "organizacion_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
    "nombre": "<nombre>",
    "slug": "<slug>",
    "zona_horaria": "<zona_horaria>",
    "moneda": "<moneda>",
    "direccion": "<direccion>",
    "telefono": "<telefono>",
    "razon_social": "<razon_social>",
    "rfc": "<rfc>",
    "iva_pct": 16,
    "es_maestro": true,
    "es_cocina_central": true,
    "es_sandbox": true,
    "activo": true,
    "modulos": [],
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

Catálogo

GET/categorias· Categorías

Alcance: catalogo:leer

ParámetroTipoDescripción
restaurante_idconsultauuidUna sola sucursal (llaves de organización); por omisión, todas las que la llave alcanza.
updated_sinceconsultadate-timeSolo lo que cambió desde este instante (ISO con zona). Para sincronizar: guarda el actualizado_at más reciente que viste y vuelve a pedir con él (puede repetir filas; son idempotentes).
cursorconsultastringEl siguiente_cursor de la página anterior.
limiteconsultaintegerFilas por página (1–100, 50 por omisión).
curl y JavaScript
curl "https://kmand.mx/api/v1/categorias" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/categorias", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaCategorias)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "nombre": "<nombre>",
      "nombre_en": "<nombre_en>",
      "color": "<color>",
      "orden": 1,
      "activo": true,
      "maestro_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
      "actualizado_at": "2026-09-29T14:05:00.000-06:00"
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

GET/productos· Productos

Con sus variantes y modificadores, IVA, SKU y código de barras. En el menú maestro trae el precio de cada sucursal.

Alcance: catalogo:leer

ParámetroTipoDescripción
restaurante_idconsultauuidUna sola sucursal (llaves de organización); por omisión, todas las que la llave alcanza.
updated_sinceconsultadate-timeSolo lo que cambió desde este instante (ISO con zona). Para sincronizar: guarda el actualizado_at más reciente que viste y vuelve a pedir con él (puede repetir filas; son idempotentes).
cursorconsultastringEl siguiente_cursor de la página anterior.
limiteconsultaintegerFilas por página (1–100, 50 por omisión).
categoria_idconsultauuidSolo los de esta categoría.
curl y JavaScript
curl "https://kmand.mx/api/v1/productos?limite=20" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/productos?limite=20", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaProductos)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "categoria_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
      "nombre": "<nombre>",
      "nombre_en": "<nombre_en>",
      "descripcion": "<descripcion>",
      "descripcion_en": "<descripcion_en>",
      "precio": "123.50",
      "precio_centavos": 12350,
      "disponible": true,
      "activo": true,
      "orden": 1,
      "sku": "<sku>",
      "codigo_barras": "<codigo_barras>",
      "tasa_iva": "0",
      "iva_pct": 16,
      "objeto_impuesto": "<objeto_impuesto>",
      "alergenos": [],
      "etiquetas": [],
      "con_alcohol": true,
      "foto_url": "<foto_url>",
      "maestro_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
      "sobrescrito": [],
      "grupos": [
        {
          "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
          "nombre": "<nombre>",
          "tipo": "variante",
          "obligatorio": true,
          "minimo": 1,
          "maximo": 1,
          "opciones": [
            {
              "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
              "nombre": "<nombre>",
              "sobreprecio": "123.50",
              "sobreprecio_centavos": 12350,
              "disponible": true
            }
          ]
        }
      ],
      "precios_sucursal": [],
      "actualizado_at": "2026-09-29T14:05:00.000-06:00"
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

GET/productos/{id}· Un producto

Alcance: catalogo:leer

ParámetroTipoDescripción
id *en la rutauuid
curl y JavaScript
curl "https://kmand.mx/api/v1/productos/:id" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch(`https://kmand.mx/api/v1/productos/${id}`, {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos } = await r.json();
Respuesta 200 (UnProducto)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "categoria_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
    "nombre": "<nombre>",
    "nombre_en": "<nombre_en>",
    "descripcion": "<descripcion>",
    "descripcion_en": "<descripcion_en>",
    "precio": "123.50",
    "precio_centavos": 12350,
    "disponible": true,
    "activo": true,
    "orden": 1,
    "sku": "<sku>",
    "codigo_barras": "<codigo_barras>",
    "tasa_iva": "0",
    "iva_pct": 16,
    "objeto_impuesto": "<objeto_impuesto>",
    "alergenos": [],
    "etiquetas": [],
    "con_alcohol": true,
    "foto_url": "<foto_url>",
    "maestro_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "sobrescrito": [],
    "grupos": [
      {
        "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
        "nombre": "<nombre>",
        "tipo": "variante",
        "obligatorio": true,
        "minimo": 1,
        "maximo": 1,
        "opciones": [
          {
            "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
            "nombre": "<nombre>",
            "sobreprecio": "123.50",
            "sobreprecio_centavos": 12350,
            "disponible": true
          }
        ]
      }
    ],
    "precios_sucursal": [],
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

POST/productos· Crear un producto

Creado en el menú maestro, llega a todas las sucursales (herencia de la Fase 14). El menú QR y la tienda lo muestran en segundos.

Alcance: catalogo:escribir · pide Idempotency-Key

Cuerpo de ejemplo
{
  "categoria_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
  "nombre": "Taco de canasta",
  "precio": 16,
  "tasa_iva": "16"
}
curl y JavaScript
curl -X POST "https://kmand.mx/api/v1/productos" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"categoria_id":"3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f","nombre":"Taco de canasta","precio":16,"tasa_iva":"16"}'
const r = await fetch("https://kmand.mx/api/v1/productos", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "categoria_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "nombre": "Taco de canasta",
    "precio": 16,
    "tasa_iva": "16"
  }),
});
const { datos } = await r.json();
Respuesta 201 (UnProducto)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "categoria_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
    "nombre": "<nombre>",
    "nombre_en": "<nombre_en>",
    "descripcion": "<descripcion>",
    "descripcion_en": "<descripcion_en>",
    "precio": "123.50",
    "precio_centavos": 12350,
    "disponible": true,
    "activo": true,
    "orden": 1,
    "sku": "<sku>",
    "codigo_barras": "<codigo_barras>",
    "tasa_iva": "0",
    "iva_pct": 16,
    "objeto_impuesto": "<objeto_impuesto>",
    "alergenos": [],
    "etiquetas": [],
    "con_alcohol": true,
    "foto_url": "<foto_url>",
    "maestro_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "sobrescrito": [],
    "grupos": [
      {
        "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
        "nombre": "<nombre>",
        "tipo": "variante",
        "obligatorio": true,
        "minimo": 1,
        "maximo": 1,
        "opciones": [
          {
            "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
            "nombre": "<nombre>",
            "sobreprecio": "123.50",
            "sobreprecio_centavos": 12350,
            "disponible": true
          }
        ]
      }
    ],
    "precios_sucursal": [],
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

PATCH/productos/{id}· Cambiar un producto o su precio

En el maestro propaga a las sucursales que no lo sobrescribieron; en una sucursal que hereda, cambiar el precio lo marca como propio de esa sucursal.

Alcance: catalogo:escribir · pide Idempotency-Key

ParámetroTipoDescripción
id *en la rutauuid
Cuerpo de ejemplo
{
  "precio_centavos": 2200
}
curl y JavaScript
curl -X PATCH "https://kmand.mx/api/v1/productos/:id" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"precio_centavos":2200}'
const r = await fetch(`https://kmand.mx/api/v1/productos/${id}`, {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "precio_centavos": 2200
  }),
});
const { datos } = await r.json();
Respuesta 200 (UnProducto)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "categoria_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
    "nombre": "<nombre>",
    "nombre_en": "<nombre_en>",
    "descripcion": "<descripcion>",
    "descripcion_en": "<descripcion_en>",
    "precio": "123.50",
    "precio_centavos": 12350,
    "disponible": true,
    "activo": true,
    "orden": 1,
    "sku": "<sku>",
    "codigo_barras": "<codigo_barras>",
    "tasa_iva": "0",
    "iva_pct": 16,
    "objeto_impuesto": "<objeto_impuesto>",
    "alergenos": [],
    "etiquetas": [],
    "con_alcohol": true,
    "foto_url": "<foto_url>",
    "maestro_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "sobrescrito": [],
    "grupos": [
      {
        "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
        "nombre": "<nombre>",
        "tipo": "variante",
        "obligatorio": true,
        "minimo": 1,
        "maximo": 1,
        "opciones": [
          {
            "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
            "nombre": "<nombre>",
            "sobreprecio": "123.50",
            "sobreprecio_centavos": 12350,
            "disponible": true
          }
        ]
      }
    ],
    "precios_sucursal": [],
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

POST/productos/{id}/agotar· Agotar (el 86)

Emite producto_agotado: las cajas, el menú QR y la tienda lo ven al momento.

Alcance: catalogo:escribir · pide Idempotency-Key

ParámetroTipoDescripción
id *en la rutauuid
curl y JavaScript
curl -X POST "https://kmand.mx/api/v1/productos/:id/agotar" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{}'
const r = await fetch(`https://kmand.mx/api/v1/productos/${id}/agotar`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});
const { datos } = await r.json();
Respuesta 200 (UnProducto)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "categoria_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
    "nombre": "<nombre>",
    "nombre_en": "<nombre_en>",
    "descripcion": "<descripcion>",
    "descripcion_en": "<descripcion_en>",
    "precio": "123.50",
    "precio_centavos": 12350,
    "disponible": true,
    "activo": true,
    "orden": 1,
    "sku": "<sku>",
    "codigo_barras": "<codigo_barras>",
    "tasa_iva": "0",
    "iva_pct": 16,
    "objeto_impuesto": "<objeto_impuesto>",
    "alergenos": [],
    "etiquetas": [],
    "con_alcohol": true,
    "foto_url": "<foto_url>",
    "maestro_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "sobrescrito": [],
    "grupos": [
      {
        "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
        "nombre": "<nombre>",
        "tipo": "variante",
        "obligatorio": true,
        "minimo": 1,
        "maximo": 1,
        "opciones": [
          {
            "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
            "nombre": "<nombre>",
            "sobreprecio": "123.50",
            "sobreprecio_centavos": 12350,
            "disponible": true
          }
        ]
      }
    ],
    "precios_sucursal": [],
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

POST/productos/{id}/reactivar· Volver a tener

Emite producto_disponible.

Alcance: catalogo:escribir · pide Idempotency-Key

ParámetroTipoDescripción
id *en la rutauuid
curl y JavaScript
curl -X POST "https://kmand.mx/api/v1/productos/:id/reactivar" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{}'
const r = await fetch(`https://kmand.mx/api/v1/productos/${id}/reactivar`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});
const { datos } = await r.json();
Respuesta 200 (UnProducto)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "categoria_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
    "nombre": "<nombre>",
    "nombre_en": "<nombre_en>",
    "descripcion": "<descripcion>",
    "descripcion_en": "<descripcion_en>",
    "precio": "123.50",
    "precio_centavos": 12350,
    "disponible": true,
    "activo": true,
    "orden": 1,
    "sku": "<sku>",
    "codigo_barras": "<codigo_barras>",
    "tasa_iva": "0",
    "iva_pct": 16,
    "objeto_impuesto": "<objeto_impuesto>",
    "alergenos": [],
    "etiquetas": [],
    "con_alcohol": true,
    "foto_url": "<foto_url>",
    "maestro_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "sobrescrito": [],
    "grupos": [
      {
        "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
        "nombre": "<nombre>",
        "tipo": "variante",
        "obligatorio": true,
        "minimo": 1,
        "maximo": 1,
        "opciones": [
          {
            "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
            "nombre": "<nombre>",
            "sobreprecio": "123.50",
            "sobreprecio_centavos": 12350,
            "disponible": true
          }
        ]
      }
    ],
    "precios_sucursal": [],
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

Ventas

GET/ordenes· Órdenes

Con partidas, pagos, descuentos y devoluciones. Sin órdenes de prueba. Ordenadas por su último cambio: para sincronizar usa updated_since.

Alcance: ventas:leer

ParámetroTipoDescripción
restaurante_idconsultauuidUna sola sucursal (llaves de organización); por omisión, todas las que la llave alcanza.
updated_sinceconsultadate-timeSolo lo que cambió desde este instante (ISO con zona). Para sincronizar: guarda el actualizado_at más reciente que viste y vuelve a pedir con él (puede repetir filas; son idempotentes).
cursorconsultastringEl siguiente_cursor de la página anterior.
limiteconsultaintegerFilas por página (1–100, 50 por omisión).
desdeconsultadateDesde esta fecha de negocio (incluida).
hastaconsultadateHasta esta fecha de negocio (incluida).
estadoconsultaabierta | cerrada | cancelada | fusionada
canalconsultamostrador | mesa | menu_qr | reserva | en_linea | telefono
curl y JavaScript
curl "https://kmand.mx/api/v1/ordenes?desde=2026-09-01&hasta=2026-09-30&estado=cerrada" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/ordenes?desde=2026-09-01&hasta=2026-09-30&estado=cerrada", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaOrdenes)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "numero": 1,
      "folio_provisional": "<folio_provisional>",
      "nombre_cliente": "<nombre_cliente>",
      "estado": "<estado>",
      "canal": "mostrador",
      "mesa_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
      "mesero_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
      "comensales": 1,
      "marca_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "abierta_at": "2026-09-29T14:05:00.000-06:00",
      "cerrada_at": "2026-09-29T14:05:00.000-06:00",
      "fecha_negocio": "2026-09-29",
      "subtotal": "123.50",
      "subtotal_centavos": 12350,
      "descuento": "123.50",
      "descuento_centavos": 12350,
      "propina": "123.50",
      "propina_centavos": 12350,
      "total": "123.50",
      "total_centavos": 12350,
      "pagado": "123.50",
      "pagado_centavos": 12350,
      "devuelto": "123.50",
      "devuelto_centavos": 12350,
      "saldo": "123.50",
      "saldo_centavos": 12350,
      "motivo_cancelacion": "<motivo_cancelacion>",
      "descuentos": [],
      "partidas": [
        {
          "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
          "producto_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
          "nombre": "<nombre>",
          "cantidad": 1,
          "precio_unitario": "123.50",
          "precio_unitario_centavos": 12350,
          "modificadores": [
            {
              "grupo_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
              "grupo": "<grupo>",
              "opcion_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
              "opcion": "<opcion>",
              "sobreprecio": "123.50",
              "sobreprecio_centavos": 12350
            }
          ],
          "importe": "123.50",
          "importe_centavos": 12350,
          "estado": "<estado>",
          "tasa_iva": "<tasa_iva>",
          "nota": "<nota>",
          "asiento": 1,
          "tiempo": 1,
          "cantidad_devuelta": 1,
          "agregada_at": "2026-09-29T14:05:00.000-06:00"
        }
      ],
      "pagos": [
        {
          "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
          "metodo": "<metodo>",
          "monto": "123.50",
          "monto_centavos": 12350,
          "recibido": "123.50",
          "recibido_centavos": 12350,
          "cambio": "123.50",
          "cambio_centavos": 12350,
          "referencia": "<referencia>",
          "etiqueta": "<etiqueta>",
          "pagado_at": "2026-09-29T14:05:00.000-06:00",
          "fecha_negocio": "2026-09-29"
        }
      ],
      "devoluciones": [],
      "actualizado_at": "2026-09-29T14:05:00.000-06:00"
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

GET/ordenes/{id}· Una orden

Alcance: ventas:leer

ParámetroTipoDescripción
id *en la rutauuid
curl y JavaScript
curl "https://kmand.mx/api/v1/ordenes/:id" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch(`https://kmand.mx/api/v1/ordenes/${id}`, {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos } = await r.json();
Respuesta 200 (UnaOrden)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "numero": 1,
    "folio_provisional": "<folio_provisional>",
    "nombre_cliente": "<nombre_cliente>",
    "estado": "<estado>",
    "canal": "mostrador",
    "mesa_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "mesero_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
    "comensales": 1,
    "marca_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "abierta_at": "2026-09-29T14:05:00.000-06:00",
    "cerrada_at": "2026-09-29T14:05:00.000-06:00",
    "fecha_negocio": "2026-09-29",
    "subtotal": "123.50",
    "subtotal_centavos": 12350,
    "descuento": "123.50",
    "descuento_centavos": 12350,
    "propina": "123.50",
    "propina_centavos": 12350,
    "total": "123.50",
    "total_centavos": 12350,
    "pagado": "123.50",
    "pagado_centavos": 12350,
    "devuelto": "123.50",
    "devuelto_centavos": 12350,
    "saldo": "123.50",
    "saldo_centavos": 12350,
    "motivo_cancelacion": "<motivo_cancelacion>",
    "descuentos": [],
    "partidas": [
      {
        "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
        "producto_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
        "nombre": "<nombre>",
        "cantidad": 1,
        "precio_unitario": "123.50",
        "precio_unitario_centavos": 12350,
        "modificadores": [
          {
            "grupo_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
            "grupo": "<grupo>",
            "opcion_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
            "opcion": "<opcion>",
            "sobreprecio": "123.50",
            "sobreprecio_centavos": 12350
          }
        ],
        "importe": "123.50",
        "importe_centavos": 12350,
        "estado": "<estado>",
        "tasa_iva": "<tasa_iva>",
        "nota": "<nota>",
        "asiento": 1,
        "tiempo": 1,
        "cantidad_devuelta": 1,
        "agregada_at": "2026-09-29T14:05:00.000-06:00"
      }
    ],
    "pagos": [
      {
        "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
        "metodo": "<metodo>",
        "monto": "123.50",
        "monto_centavos": 12350,
        "recibido": "123.50",
        "recibido_centavos": 12350,
        "cambio": "123.50",
        "cambio_centavos": 12350,
        "referencia": "<referencia>",
        "etiqueta": "<etiqueta>",
        "pagado_at": "2026-09-29T14:05:00.000-06:00",
        "fecha_negocio": "2026-09-29"
      }
    ],
    "devoluciones": [],
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

Caja

GET/turnos· Turnos de caja

Cada turno con su corte por método de pago. El esperado y la diferencia solo con el turno cerrado.

Alcance: caja:leer

ParámetroTipoDescripción
restaurante_idconsultauuidUna sola sucursal (llaves de organización); por omisión, todas las que la llave alcanza.
updated_sinceconsultadate-timeSolo lo que cambió desde este instante (ISO con zona). Para sincronizar: guarda el actualizado_at más reciente que viste y vuelve a pedir con él (puede repetir filas; son idempotentes).
cursorconsultastringEl siguiente_cursor de la página anterior.
limiteconsultaintegerFilas por página (1–100, 50 por omisión).
desdeconsultadateDesde esta fecha de negocio (incluida).
hastaconsultadateHasta esta fecha de negocio (incluida).
estadoconsultaabierto | cerrado
curl y JavaScript
curl "https://kmand.mx/api/v1/turnos" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/turnos", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaTurnos)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "dispositivo_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "estado": "abierto",
      "abierto_at": "2026-09-29T14:05:00.000-06:00",
      "cerrado_at": "2026-09-29T14:05:00.000-06:00",
      "fecha_negocio": "2026-09-29",
      "turno_dia": "<turno_dia>",
      "num_ventas": 1,
      "fondo_inicial": "123.50",
      "fondo_inicial_centavos": 12350,
      "ventas_total": "123.50",
      "ventas_total_centavos": 12350,
      "descuentos": "123.50",
      "descuentos_centavos": 12350,
      "cancelaciones": "123.50",
      "cancelaciones_centavos": 12350,
      "devoluciones": "123.50",
      "devoluciones_centavos": 12350,
      "gastos": "123.50",
      "gastos_centavos": 12350,
      "retiros": "123.50",
      "retiros_centavos": 12350,
      "ingresos": "123.50",
      "ingresos_centavos": 12350,
      "ventas_por_metodo": {
        "efectivo": "123.50",
        "tarjeta": "123.50",
        "transferencia": "123.50",
        "tarjeta_mp": "123.50",
        "link_mp": "123.50",
        "nota_credito": "123.50",
        "tarjeta_regalo": "123.50",
        "monedero": "123.50",
        "otro": "123.50"
      },
      "propinas": {
        "efectivo": "123.50",
        "tarjeta": "123.50",
        "otras": "123.50"
      },
      "esperado_efectivo": "123.50",
      "esperado_efectivo_centavos": 12350,
      "contado_efectivo": "123.50",
      "contado_efectivo_centavos": 12350,
      "diferencia": "123.50",
      "diferencia_centavos": 12350,
      "motivo_diferencia": "<motivo_diferencia>",
      "actualizado_at": "2026-09-29T14:05:00.000-06:00"
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

GET/turnos/{id}· Un turno de caja

Alcance: caja:leer

ParámetroTipoDescripción
id *en la rutauuid
curl y JavaScript
curl "https://kmand.mx/api/v1/turnos/:id" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch(`https://kmand.mx/api/v1/turnos/${id}`, {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos } = await r.json();
Respuesta 200 (UnTurno)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "dispositivo_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "estado": "abierto",
    "abierto_at": "2026-09-29T14:05:00.000-06:00",
    "cerrado_at": "2026-09-29T14:05:00.000-06:00",
    "fecha_negocio": "2026-09-29",
    "turno_dia": "<turno_dia>",
    "num_ventas": 1,
    "fondo_inicial": "123.50",
    "fondo_inicial_centavos": 12350,
    "ventas_total": "123.50",
    "ventas_total_centavos": 12350,
    "descuentos": "123.50",
    "descuentos_centavos": 12350,
    "cancelaciones": "123.50",
    "cancelaciones_centavos": 12350,
    "devoluciones": "123.50",
    "devoluciones_centavos": 12350,
    "gastos": "123.50",
    "gastos_centavos": 12350,
    "retiros": "123.50",
    "retiros_centavos": 12350,
    "ingresos": "123.50",
    "ingresos_centavos": 12350,
    "ventas_por_metodo": {
      "efectivo": "123.50",
      "tarjeta": "123.50",
      "transferencia": "123.50",
      "tarjeta_mp": "123.50",
      "link_mp": "123.50",
      "nota_credito": "123.50",
      "tarjeta_regalo": "123.50",
      "monedero": "123.50",
      "otro": "123.50"
    },
    "propinas": {
      "efectivo": "123.50",
      "tarjeta": "123.50",
      "otras": "123.50"
    },
    "esperado_efectivo": "123.50",
    "esperado_efectivo_centavos": 12350,
    "contado_efectivo": "123.50",
    "contado_efectivo_centavos": 12350,
    "diferencia": "123.50",
    "diferencia_centavos": 12350,
    "motivo_diferencia": "<motivo_diferencia>",
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

GET/cortes· Cortes del día (Z)

Una fila por sucursal y día de negocio. Rango máximo de 93 días.

Alcance: caja:leer

ParámetroTipoDescripción
restaurante_idconsultauuidUna sola sucursal (llaves de organización); por omisión, todas las que la llave alcanza.
desde *consultadateDesde esta fecha de negocio (incluida).
hasta *consultadateHasta esta fecha (incluida; máximo 93 días de rango).
curl y JavaScript
curl "https://kmand.mx/api/v1/cortes?desde=2026-09-01&hasta=2026-09-07" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/cortes?desde=2026-09-01&hasta=2026-09-07", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaCortes)
{
  "datos": [
    {
      "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "fecha": "2026-09-29",
      "cobrado": "123.50",
      "cobrado_centavos": 12350,
      "propinas": "123.50",
      "propinas_centavos": 12350,
      "devoluciones": "123.50",
      "devoluciones_centavos": 12350,
      "ventas_netas": "123.50",
      "ventas_netas_centavos": 12350,
      "ordenes_cerradas": 1,
      "ordenes_canceladas": 1,
      "turnos": 1,
      "turnos_cerrados": 1,
      "por_metodo": {
        "efectivo": {
          "monto": "123.50",
          "monto_centavos": 12350,
          "pagos": 1
        }
      }
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

Clientes

GET/clientes· Clientes

Sin WhatsApp ni correo salvo con clientes:contacto.

Alcance: clientes:leer

ParámetroTipoDescripción
restaurante_idconsultauuidUna sola sucursal (llaves de organización); por omisión, todas las que la llave alcanza.
updated_sinceconsultadate-timeSolo lo que cambió desde este instante (ISO con zona). Para sincronizar: guarda el actualizado_at más reciente que viste y vuelve a pedir con él (puede repetir filas; son idempotentes).
cursorconsultastringEl siguiente_cursor de la página anterior.
limiteconsultaintegerFilas por página (1–100, 50 por omisión).
curl y JavaScript
curl "https://kmand.mx/api/v1/clientes" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/clientes", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaClientes)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "nombre": "<nombre>",
      "whatsapp": "<whatsapp>",
      "correo": "<correo>",
      "alergias": "<alergias>",
      "preferencias": "<preferencias>",
      "etiquetas": [],
      "lista_negra": true,
      "consentimiento": true,
      "origen": "<origen>",
      "registrado_at": "2026-09-29T14:05:00.000-06:00",
      "actualizado_at": "2026-09-29T14:05:00.000-06:00"
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

GET/clientes/{id}· Un cliente

Alcance: clientes:leer

ParámetroTipoDescripción
id *en la rutauuid
curl y JavaScript
curl "https://kmand.mx/api/v1/clientes/:id" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch(`https://kmand.mx/api/v1/clientes/${id}`, {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos } = await r.json();
Respuesta 200 (UnCliente)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "nombre": "<nombre>",
    "whatsapp": "<whatsapp>",
    "correo": "<correo>",
    "alergias": "<alergias>",
    "preferencias": "<preferencias>",
    "etiquetas": [],
    "lista_negra": true,
    "consentimiento": true,
    "origen": "<origen>",
    "registrado_at": "2026-09-29T14:05:00.000-06:00",
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

POST/clientes· Dar de alta un cliente

Emite cliente_registrado. El id sale del WhatsApp (dos altas del mismo número no lo duplican: la segunda responde 409 cliente_existente). Necesita el módulo de reservas o de lealtad.

Alcance: clientes:escribir · pide Idempotency-Key

Cuerpo de ejemplo
{
  "whatsapp": "4441234567",
  "nombre": "Carmen López",
  "consentimiento": true
}
curl y JavaScript
curl -X POST "https://kmand.mx/api/v1/clientes" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"whatsapp":"4441234567","nombre":"Carmen López","consentimiento":true}'
const r = await fetch("https://kmand.mx/api/v1/clientes", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "whatsapp": "4441234567",
    "nombre": "Carmen López",
    "consentimiento": true
  }),
});
const { datos } = await r.json();
Respuesta 201 (UnCliente)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "nombre": "<nombre>",
    "whatsapp": "<whatsapp>",
    "correo": "<correo>",
    "alergias": "<alergias>",
    "preferencias": "<preferencias>",
    "etiquetas": [],
    "lista_negra": true,
    "consentimiento": true,
    "origen": "<origen>",
    "registrado_at": "2026-09-29T14:05:00.000-06:00",
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

Reservas

GET/reservas· Reservas

Alcance: reservas:leer · módulo reservas

ParámetroTipoDescripción
restaurante_idconsultauuidUna sola sucursal (llaves de organización); por omisión, todas las que la llave alcanza.
updated_sinceconsultadate-timeSolo lo que cambió desde este instante (ISO con zona). Para sincronizar: guarda el actualizado_at más reciente que viste y vuelve a pedir con él (puede repetir filas; son idempotentes).
cursorconsultastringEl siguiente_cursor de la página anterior.
limiteconsultaintegerFilas por página (1–100, 50 por omisión).
desdeconsultadateDesde esta fecha de negocio (incluida).
hastaconsultadateHasta esta fecha de negocio (incluida).
estadoconsultapendiente_pago | reservada | confirmada | llegada | sentada | no_show | cancelada
curl y JavaScript
curl "https://kmand.mx/api/v1/reservas?desde=2026-09-29&hasta=2026-10-05" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/reservas?desde=2026-09-29&hasta=2026-10-05", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaReservas)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "cliente_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
      "nombre": "<nombre>",
      "personas": 1,
      "fecha": "2026-09-29",
      "hora": "20:00",
      "duracion_min": 1,
      "inicio_at": "2026-09-29T14:05:00.000-06:00",
      "fin_at": "2026-09-29T14:05:00.000-06:00",
      "canal": "<canal>",
      "estado": "<estado>",
      "estado_efectivo": "<estado_efectivo>",
      "mesa_ids": [],
      "area_preferida_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "ocasion": "<ocasion>",
      "notas": "<notas>",
      "deposito": "123.50",
      "deposito_centavos": 12350,
      "deposito_estado": "<deposito_estado>",
      "confirmada_at": "2026-09-29T14:05:00.000-06:00",
      "llegada_at": "2026-09-29T14:05:00.000-06:00",
      "sentada_at": "2026-09-29T14:05:00.000-06:00",
      "no_show_at": "2026-09-29T14:05:00.000-06:00",
      "cancelada_at": "2026-09-29T14:05:00.000-06:00",
      "cancelada_por": "<cancelada_por>",
      "motivo": "<motivo>",
      "orden_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "creada_at": "2026-09-29T14:05:00.000-06:00",
      "actualizado_at": "2026-09-29T14:05:00.000-06:00"
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

GET/reservas/{id}· Una reserva

Alcance: reservas:leer · módulo reservas

ParámetroTipoDescripción
id *en la rutauuid
curl y JavaScript
curl "https://kmand.mx/api/v1/reservas/:id" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch(`https://kmand.mx/api/v1/reservas/${id}`, {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos } = await r.json();
Respuesta 200 (UnaReserva)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "cliente_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "nombre": "<nombre>",
    "personas": 1,
    "fecha": "2026-09-29",
    "hora": "20:00",
    "duracion_min": 1,
    "inicio_at": "2026-09-29T14:05:00.000-06:00",
    "fin_at": "2026-09-29T14:05:00.000-06:00",
    "canal": "<canal>",
    "estado": "<estado>",
    "estado_efectivo": "<estado_efectivo>",
    "mesa_ids": [],
    "area_preferida_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "ocasion": "<ocasion>",
    "notas": "<notas>",
    "deposito": "123.50",
    "deposito_centavos": 12350,
    "deposito_estado": "<deposito_estado>",
    "confirmada_at": "2026-09-29T14:05:00.000-06:00",
    "llegada_at": "2026-09-29T14:05:00.000-06:00",
    "sentada_at": "2026-09-29T14:05:00.000-06:00",
    "no_show_at": "2026-09-29T14:05:00.000-06:00",
    "cancelada_at": "2026-09-29T14:05:00.000-06:00",
    "cancelada_por": "<cancelada_por>",
    "motivo": "<motivo>",
    "orden_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "creada_at": "2026-09-29T14:05:00.000-06:00",
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

POST/reservas· Crear una reserva

Mismas reglas que la reserva en línea (horario, anticipación, cupo, mesa libre toda la duración). Si el grupo pide depósito responde 409 deposito_requerido: la API no cobra.

Alcance: reservas:escribir · módulo reservas · pide Idempotency-Key

Cuerpo de ejemplo
{
  "fecha": "2026-10-03",
  "hora": "20:00",
  "personas": 4,
  "nombre": "Familia Ortiz",
  "whatsapp": "4449876543",
  "ocasion": "Cumpleaños"
}
curl y JavaScript
curl -X POST "https://kmand.mx/api/v1/reservas" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"fecha":"2026-10-03","hora":"20:00","personas":4,"nombre":"Familia Ortiz","whatsapp":"4449876543","ocasion":"Cumpleaños"}'
const r = await fetch("https://kmand.mx/api/v1/reservas", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "fecha": "2026-10-03",
    "hora": "20:00",
    "personas": 4,
    "nombre": "Familia Ortiz",
    "whatsapp": "4449876543",
    "ocasion": "Cumpleaños"
  }),
});
const { datos } = await r.json();
Respuesta 201 (UnaReserva)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "cliente_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "nombre": "<nombre>",
    "personas": 1,
    "fecha": "2026-09-29",
    "hora": "20:00",
    "duracion_min": 1,
    "inicio_at": "2026-09-29T14:05:00.000-06:00",
    "fin_at": "2026-09-29T14:05:00.000-06:00",
    "canal": "<canal>",
    "estado": "<estado>",
    "estado_efectivo": "<estado_efectivo>",
    "mesa_ids": [],
    "area_preferida_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "ocasion": "<ocasion>",
    "notas": "<notas>",
    "deposito": "123.50",
    "deposito_centavos": 12350,
    "deposito_estado": "<deposito_estado>",
    "confirmada_at": "2026-09-29T14:05:00.000-06:00",
    "llegada_at": "2026-09-29T14:05:00.000-06:00",
    "sentada_at": "2026-09-29T14:05:00.000-06:00",
    "no_show_at": "2026-09-29T14:05:00.000-06:00",
    "cancelada_at": "2026-09-29T14:05:00.000-06:00",
    "cancelada_por": "<cancelada_por>",
    "motivo": "<motivo>",
    "orden_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "creada_at": "2026-09-29T14:05:00.000-06:00",
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

PATCH/reservas/{id}· Modificar una reserva

Cambiar fecha, hora o personas vuelve a revisar la disponibilidad.

Alcance: reservas:escribir · módulo reservas · pide Idempotency-Key

ParámetroTipoDescripción
id *en la rutauuid
Cuerpo de ejemplo
{
  "hora": "20:30",
  "personas": 5
}
curl y JavaScript
curl -X PATCH "https://kmand.mx/api/v1/reservas/:id" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"hora":"20:30","personas":5}'
const r = await fetch(`https://kmand.mx/api/v1/reservas/${id}`, {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "hora": "20:30",
    "personas": 5
  }),
});
const { datos } = await r.json();
Respuesta 200 (UnaReserva)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "cliente_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "nombre": "<nombre>",
    "personas": 1,
    "fecha": "2026-09-29",
    "hora": "20:00",
    "duracion_min": 1,
    "inicio_at": "2026-09-29T14:05:00.000-06:00",
    "fin_at": "2026-09-29T14:05:00.000-06:00",
    "canal": "<canal>",
    "estado": "<estado>",
    "estado_efectivo": "<estado_efectivo>",
    "mesa_ids": [],
    "area_preferida_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "ocasion": "<ocasion>",
    "notas": "<notas>",
    "deposito": "123.50",
    "deposito_centavos": 12350,
    "deposito_estado": "<deposito_estado>",
    "confirmada_at": "2026-09-29T14:05:00.000-06:00",
    "llegada_at": "2026-09-29T14:05:00.000-06:00",
    "sentada_at": "2026-09-29T14:05:00.000-06:00",
    "no_show_at": "2026-09-29T14:05:00.000-06:00",
    "cancelada_at": "2026-09-29T14:05:00.000-06:00",
    "cancelada_por": "<cancelada_por>",
    "motivo": "<motivo>",
    "orden_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "creada_at": "2026-09-29T14:05:00.000-06:00",
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

POST/reservas/{id}/cancelar· Cancelar una reserva

Cancelada por el restaurante. Con depósito pagado responde 409: el reembolso se decide en el libro del host.

Alcance: reservas:escribir · módulo reservas · pide Idempotency-Key

ParámetroTipoDescripción
id *en la rutauuid
Cuerpo de ejemplo
{
  "motivo": "El cliente llamó para cancelar"
}
curl y JavaScript
curl -X POST "https://kmand.mx/api/v1/reservas/:id/cancelar" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"motivo":"El cliente llamó para cancelar"}'
const r = await fetch(`https://kmand.mx/api/v1/reservas/${id}/cancelar`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "motivo": "El cliente llamó para cancelar"
  }),
});
const { datos } = await r.json();
Respuesta 200 (UnaReserva)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "cliente_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "nombre": "<nombre>",
    "personas": 1,
    "fecha": "2026-09-29",
    "hora": "20:00",
    "duracion_min": 1,
    "inicio_at": "2026-09-29T14:05:00.000-06:00",
    "fin_at": "2026-09-29T14:05:00.000-06:00",
    "canal": "<canal>",
    "estado": "<estado>",
    "estado_efectivo": "<estado_efectivo>",
    "mesa_ids": [],
    "area_preferida_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "ocasion": "<ocasion>",
    "notas": "<notas>",
    "deposito": "123.50",
    "deposito_centavos": 12350,
    "deposito_estado": "<deposito_estado>",
    "confirmada_at": "2026-09-29T14:05:00.000-06:00",
    "llegada_at": "2026-09-29T14:05:00.000-06:00",
    "sentada_at": "2026-09-29T14:05:00.000-06:00",
    "no_show_at": "2026-09-29T14:05:00.000-06:00",
    "cancelada_at": "2026-09-29T14:05:00.000-06:00",
    "cancelada_por": "<cancelada_por>",
    "motivo": "<motivo>",
    "orden_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "creada_at": "2026-09-29T14:05:00.000-06:00",
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

Pedidos en línea

GET/pedidos· Pedidos en línea

Para llevar y a domicilio. Nombre, WhatsApp y dirección solo con clientes:contacto.

Alcance: ventas:leer

ParámetroTipoDescripción
restaurante_idconsultauuidUna sola sucursal (llaves de organización); por omisión, todas las que la llave alcanza.
updated_sinceconsultadate-timeSolo lo que cambió desde este instante (ISO con zona). Para sincronizar: guarda el actualizado_at más reciente que viste y vuelve a pedir con él (puede repetir filas; son idempotentes).
cursorconsultastringEl siguiente_cursor de la página anterior.
limiteconsultaintegerFilas por página (1–100, 50 por omisión).
desdeconsultadateDesde esta fecha de negocio (incluida).
hastaconsultadateHasta esta fecha de negocio (incluida).
estadoconsultapago_pendiente | por_confirmar | recibido | aceptado | rechazado | en_preparacion | listo | en_camino | entregado | cancelado
curl y JavaScript
curl "https://kmand.mx/api/v1/pedidos" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/pedidos", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaPedidos)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "numero": 1,
      "canal": "<canal>",
      "marca_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "tipo": "llevar",
      "estado": "pago_pendiente",
      "nombre_corto": "<nombre_corto>",
      "subtotal": "123.50",
      "subtotal_centavos": 12350,
      "descuento": "123.50",
      "descuento_centavos": 12350,
      "costo_envio": "123.50",
      "costo_envio_centavos": 12350,
      "propina": "123.50",
      "propina_centavos": 12350,
      "total": "123.50",
      "total_centavos": 12350,
      "pago_metodo": "<pago_metodo>",
      "pagado_at": "2026-09-29T14:05:00.000-06:00",
      "programado_para": "2026-09-29T14:05:00.000-06:00",
      "prometido_at": "2026-09-29T14:05:00.000-06:00",
      "recibido_at": "2026-09-29T14:05:00.000-06:00",
      "aceptado_at": "2026-09-29T14:05:00.000-06:00",
      "listo_at": "2026-09-29T14:05:00.000-06:00",
      "en_camino_at": "2026-09-29T14:05:00.000-06:00",
      "entregado_at": "2026-09-29T14:05:00.000-06:00",
      "cerrado_at": "2026-09-29T14:05:00.000-06:00",
      "motivo": "<motivo>",
      "orden_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "zona_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
      "cupon_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "seguimiento_ruta": "<seguimiento_ruta>",
      "partidas": [
        {
          "producto_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
          "nombre": "<nombre>",
          "cantidad": 1,
          "precio_unitario": "123.50",
          "precio_unitario_centavos": 12350,
          "modificadores": [
            {
              "grupo_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
              "grupo": "<grupo>",
              "opcion_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
              "opcion": "<opcion>",
              "sobreprecio": "123.50",
              "sobreprecio_centavos": 12350
            }
          ],
          "nota": "<nota>"
        }
      ],
      "cliente": {
        "nombre": "<nombre>",
        "whatsapp": "<whatsapp>",
        "direccion": "<direccion>",
        "referencias": "<referencias>",
        "lat": 22.1514,
        "lng": -100.9762,
        "notas": "<notas>"
      },
      "actualizado_at": "2026-09-29T14:05:00.000-06:00"
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

GET/pedidos/{id}· Un pedido

Alcance: ventas:leer

ParámetroTipoDescripción
id *en la rutauuid
curl y JavaScript
curl "https://kmand.mx/api/v1/pedidos/:id" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch(`https://kmand.mx/api/v1/pedidos/${id}`, {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos } = await r.json();
Respuesta 200 (UnPedido)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "numero": 1,
    "canal": "<canal>",
    "marca_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "tipo": "llevar",
    "estado": "pago_pendiente",
    "nombre_corto": "<nombre_corto>",
    "subtotal": "123.50",
    "subtotal_centavos": 12350,
    "descuento": "123.50",
    "descuento_centavos": 12350,
    "costo_envio": "123.50",
    "costo_envio_centavos": 12350,
    "propina": "123.50",
    "propina_centavos": 12350,
    "total": "123.50",
    "total_centavos": 12350,
    "pago_metodo": "<pago_metodo>",
    "pagado_at": "2026-09-29T14:05:00.000-06:00",
    "programado_para": "2026-09-29T14:05:00.000-06:00",
    "prometido_at": "2026-09-29T14:05:00.000-06:00",
    "recibido_at": "2026-09-29T14:05:00.000-06:00",
    "aceptado_at": "2026-09-29T14:05:00.000-06:00",
    "listo_at": "2026-09-29T14:05:00.000-06:00",
    "en_camino_at": "2026-09-29T14:05:00.000-06:00",
    "entregado_at": "2026-09-29T14:05:00.000-06:00",
    "cerrado_at": "2026-09-29T14:05:00.000-06:00",
    "motivo": "<motivo>",
    "orden_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "zona_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "cupon_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "seguimiento_ruta": "<seguimiento_ruta>",
    "partidas": [
      {
        "producto_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
        "nombre": "<nombre>",
        "cantidad": 1,
        "precio_unitario": "123.50",
        "precio_unitario_centavos": 12350,
        "modificadores": [
          {
            "grupo_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
            "grupo": "<grupo>",
            "opcion_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
            "opcion": "<opcion>",
            "sobreprecio": "123.50",
            "sobreprecio_centavos": 12350
          }
        ],
        "nota": "<nota>"
      }
    ],
    "cliente": {
      "nombre": "<nombre>",
      "whatsapp": "<whatsapp>",
      "direccion": "<direccion>",
      "referencias": "<referencias>",
      "lat": 22.1514,
      "lng": -100.9762,
      "notas": "<notas>"
    },
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

POST/pedidos· Crear un pedido

Entra por el mismo camino que la tienda en línea: precios del catálogo (nunca los tuyos), modificadores obligatorios, zona de reparto por lat/lng, mínimo, horario, cupo por franja, pausa y cupón. Si algo no cuadra responde 409 pedido_rechazado con el motivo. Llega a la bandeja del POS como cualquier pedido.

Alcance: pedidos:crear · módulo pedidos_linea · pide Idempotency-Key

Cuerpo de ejemplo
{
  "tipo": "domicilio",
  "partidas": [
    {
      "producto_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "cantidad": 3,
      "opciones": [
        "a0d861cf-afba-4cc2-a9a4-697eced718ac",
        "b70a07e5-bb4b-483c-be84-2797f7790197"
      ]
    }
  ],
  "cliente": {
    "nombre": "Carmen",
    "whatsapp": "4441234567"
  },
  "entrega": {
    "direccion": "Av. Carranza 1200, Col. Centro",
    "lat": 22.1523,
    "lng": -100.9781
  },
  "pago": "efectivo",
  "paga_con": 200
}
curl y JavaScript
curl -X POST "https://kmand.mx/api/v1/pedidos" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"tipo":"domicilio","partidas":[{"producto_id":"b6152f21-3c67-4896-a4a5-ea72ec44601a","cantidad":3,"opciones":["a0d861cf-afba-4cc2-a9a4-697eced718ac","b70a07e5-bb4b-483c-be84-2797f7790197"]}],"cliente":{"nombre":"Carmen","whatsapp":"4441234567"},"entrega":{"direccion":"Av. Carranza 1200, Col. Centro","lat":22.1523,"lng":-100.9781},"pago":"efectivo","paga_con":200}'
const r = await fetch("https://kmand.mx/api/v1/pedidos", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "tipo": "domicilio",
    "partidas": [
      {
        "producto_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
        "cantidad": 3,
        "opciones": [
          "a0d861cf-afba-4cc2-a9a4-697eced718ac",
          "b70a07e5-bb4b-483c-be84-2797f7790197"
        ]
      }
    ],
    "cliente": {
      "nombre": "Carmen",
      "whatsapp": "4441234567"
    },
    "entrega": {
      "direccion": "Av. Carranza 1200, Col. Centro",
      "lat": 22.1523,
      "lng": -100.9781
    },
    "pago": "efectivo",
    "paga_con": 200
  }),
});
const { datos } = await r.json();
Respuesta 201 (UnPedido)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "numero": 1,
    "canal": "<canal>",
    "marca_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "tipo": "llevar",
    "estado": "pago_pendiente",
    "nombre_corto": "<nombre_corto>",
    "subtotal": "123.50",
    "subtotal_centavos": 12350,
    "descuento": "123.50",
    "descuento_centavos": 12350,
    "costo_envio": "123.50",
    "costo_envio_centavos": 12350,
    "propina": "123.50",
    "propina_centavos": 12350,
    "total": "123.50",
    "total_centavos": 12350,
    "pago_metodo": "<pago_metodo>",
    "pagado_at": "2026-09-29T14:05:00.000-06:00",
    "programado_para": "2026-09-29T14:05:00.000-06:00",
    "prometido_at": "2026-09-29T14:05:00.000-06:00",
    "recibido_at": "2026-09-29T14:05:00.000-06:00",
    "aceptado_at": "2026-09-29T14:05:00.000-06:00",
    "listo_at": "2026-09-29T14:05:00.000-06:00",
    "en_camino_at": "2026-09-29T14:05:00.000-06:00",
    "entregado_at": "2026-09-29T14:05:00.000-06:00",
    "cerrado_at": "2026-09-29T14:05:00.000-06:00",
    "motivo": "<motivo>",
    "orden_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "zona_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "cupon_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "seguimiento_ruta": "<seguimiento_ruta>",
    "partidas": [
      {
        "producto_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
        "nombre": "<nombre>",
        "cantidad": 1,
        "precio_unitario": "123.50",
        "precio_unitario_centavos": 12350,
        "modificadores": [
          {
            "grupo_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
            "grupo": "<grupo>",
            "opcion_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
            "opcion": "<opcion>",
            "sobreprecio": "123.50",
            "sobreprecio_centavos": 12350
          }
        ],
        "nota": "<nota>"
      }
    ],
    "cliente": {
      "nombre": "<nombre>",
      "whatsapp": "<whatsapp>",
      "direccion": "<direccion>",
      "referencias": "<referencias>",
      "lat": 22.1514,
      "lng": -100.9762,
      "notas": "<notas>"
    },
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

Inventario

GET/insumos· Insumos y existencias

Alcance: inventario:leer · módulo inventario

ParámetroTipoDescripción
restaurante_idconsultauuidUna sola sucursal (llaves de organización); por omisión, todas las que la llave alcanza.
updated_sinceconsultadate-timeSolo lo que cambió desde este instante (ISO con zona). Para sincronizar: guarda el actualizado_at más reciente que viste y vuelve a pedir con él (puede repetir filas; son idempotentes).
cursorconsultastringEl siguiente_cursor de la página anterior.
limiteconsultaintegerFilas por página (1–100, 50 por omisión).
bajo_minimoconsultatrue | falsetrue = solo los que están por debajo de su mínimo.
curl y JavaScript
curl "https://kmand.mx/api/v1/insumos?bajo_minimo=true" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/insumos?bajo_minimo=true", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaInsumos)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "nombre": "<nombre>",
      "categoria": "<categoria>",
      "unidad_base": "<unidad_base>",
      "unidad_compra": "<unidad_compra>",
      "factor_compra": 1,
      "costo_promedio_base": "<costo_promedio_base>",
      "ultimo_costo_base": "<ultimo_costo_base>",
      "minimo": 1,
      "maximo": 1,
      "proveedor_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
      "codigo_barras": "<codigo_barras>",
      "activo": true,
      "maestro_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
      "existencia": 1,
      "valor": "123.50",
      "valor_centavos": 12350,
      "bajo_minimo": true,
      "actualizado_at": "2026-09-29T14:05:00.000-06:00"
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

GET/insumos/{id}· Un insumo

Alcance: inventario:leer · módulo inventario

ParámetroTipoDescripción
id *en la rutauuid
curl y JavaScript
curl "https://kmand.mx/api/v1/insumos/:id" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch(`https://kmand.mx/api/v1/insumos/${id}`, {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos } = await r.json();
Respuesta 200 (UnInsumo)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "nombre": "<nombre>",
    "categoria": "<categoria>",
    "unidad_base": "<unidad_base>",
    "unidad_compra": "<unidad_compra>",
    "factor_compra": 1,
    "costo_promedio_base": "<costo_promedio_base>",
    "ultimo_costo_base": "<ultimo_costo_base>",
    "minimo": 1,
    "maximo": 1,
    "proveedor_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
    "codigo_barras": "<codigo_barras>",
    "activo": true,
    "maestro_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "existencia": 1,
    "valor": "123.50",
    "valor_centavos": 12350,
    "bajo_minimo": true,
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

GET/inventario/movimientos· Movimientos de inventario

Entradas, mermas, producción, transferencias, ajustes y el consumo teórico de cada venta.

Alcance: inventario:leer · módulo inventario

ParámetroTipoDescripción
restaurante_idconsultauuidUna sola sucursal (llaves de organización); por omisión, todas las que la llave alcanza.
updated_sinceconsultadate-timeSolo lo que cambió desde este instante (ISO con zona). Para sincronizar: guarda el actualizado_at más reciente que viste y vuelve a pedir con él (puede repetir filas; son idempotentes).
cursorconsultastringEl siguiente_cursor de la página anterior.
limiteconsultaintegerFilas por página (1–100, 50 por omisión).
insumo_idconsultauuid
tipoconsultaentrada | merma | produccion | transferencia | ajuste | consumo | devolucion
desdeconsultadateDesde esta fecha de negocio (incluida).
hastaconsultadateHasta esta fecha de negocio (incluida).
curl y JavaScript
curl "https://kmand.mx/api/v1/inventario/movimientos" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/inventario/movimientos", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaMovimientos)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "insumo_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
      "tipo": "entrada",
      "cantidad_base": 1,
      "costo_unitario_base": "<costo_unitario_base>",
      "valor": "123.50",
      "valor_centavos": 12350,
      "motivo": "<motivo>",
      "proveedor_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
      "referencia_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
      "evento_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
      "caducidad": "2026-09-29",
      "fecha": "2026-09-29T14:05:00.000-06:00",
      "fecha_negocio": "2026-09-29",
      "creado_at": "2026-09-29T14:05:00.000-06:00"
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

POST/inventario/entradas· Registrar una entrada (compra)

Emite entrada_registrada: sube existencias y recalcula el costo promedio ponderado.

Alcance: inventario:escribir · módulo inventario · pide Idempotency-Key

Cuerpo de ejemplo
{
  "partidas": [
    {
      "insumo_id": "0859c850-dc8a-4ea1-9984-e96b1db2255f",
      "cantidad": 5,
      "unidad": "compra",
      "costo_unitario": 28.5
    }
  ],
  "nota": "Compra de la central de abastos"
}
curl y JavaScript
curl -X POST "https://kmand.mx/api/v1/inventario/entradas" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"partidas":[{"insumo_id":"0859c850-dc8a-4ea1-9984-e96b1db2255f","cantidad":5,"unidad":"compra","costo_unitario":28.5}],"nota":"Compra de la central de abastos"}'
const r = await fetch("https://kmand.mx/api/v1/inventario/entradas", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "partidas": [
      {
        "insumo_id": "0859c850-dc8a-4ea1-9984-e96b1db2255f",
        "cantidad": 5,
        "unidad": "compra",
        "costo_unitario": 28.5
      }
    ],
    "nota": "Compra de la central de abastos"
  }),
});
const { datos } = await r.json();
Respuesta 201 (UnaEntrada)
{
  "datos": {
    "evento_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "entrada_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "movimientos": [
      {
        "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
        "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
        "insumo_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
        "tipo": "entrada",
        "cantidad_base": 1,
        "costo_unitario_base": "<costo_unitario_base>",
        "valor": "123.50",
        "valor_centavos": 12350,
        "motivo": "<motivo>",
        "proveedor_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
        "referencia_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
        "evento_id": "06f32b56-eae5-4219-b5a2-b7d0612bc3d0",
        "caducidad": "2026-09-29",
        "fecha": "2026-09-29T14:05:00.000-06:00",
        "fecha_negocio": "2026-09-29",
        "creado_at": "2026-09-29T14:05:00.000-06:00"
      }
    ]
  }
}

Contabilidad

GET/gastos· Gastos

Alcance: contabilidad:leer · módulo contabilidad

ParámetroTipoDescripción
restaurante_idconsultauuidUna sola sucursal (llaves de organización); por omisión, todas las que la llave alcanza.
updated_sinceconsultadate-timeSolo lo que cambió desde este instante (ISO con zona). Para sincronizar: guarda el actualizado_at más reciente que viste y vuelve a pedir con él (puede repetir filas; son idempotentes).
cursorconsultastringEl siguiente_cursor de la página anterior.
limiteconsultaintegerFilas por página (1–100, 50 por omisión).
desdeconsultadateDesde esta fecha de negocio (incluida).
hastaconsultadateHasta esta fecha de negocio (incluida).
categoriaconsultastring
curl y JavaScript
curl "https://kmand.mx/api/v1/gastos" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/gastos", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaGastos)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "fecha": "2026-09-29",
      "proveedor": "<proveedor>",
      "proveedor_rfc": "<proveedor_rfc>",
      "concepto": "<concepto>",
      "categoria": "<categoria>",
      "origen": "<origen>",
      "metodo_pago": "<metodo_pago>",
      "subtotal": "123.50",
      "subtotal_centavos": 12350,
      "descuento": "123.50",
      "descuento_centavos": 12350,
      "iva": "123.50",
      "iva_centavos": 12350,
      "ieps": "123.50",
      "ieps_centavos": 12350,
      "iva_retenido": "123.50",
      "iva_retenido_centavos": 12350,
      "isr_retenido": "123.50",
      "isr_retenido_centavos": 12350,
      "total": "123.50",
      "total_centavos": 12350,
      "a_credito": true,
      "vence_el": "2026-09-29",
      "pagado": "123.50",
      "pagado_centavos": 12350,
      "saldo": "123.50",
      "saldo_centavos": 12350,
      "cfdi_uuid": "<cfdi_uuid>",
      "activo": true,
      "creado_at": "2026-09-29T14:05:00.000-06:00",
      "actualizado_at": "2026-09-29T14:05:00.000-06:00"
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

Personal

GET/empleados· Empleados

Sin PIN ni datos fiscales; el salario diario solo con personal:salarios.

Alcance: personal:leer

ParámetroTipoDescripción
restaurante_idconsultauuidUna sola sucursal (llaves de organización); por omisión, todas las que la llave alcanza.
updated_sinceconsultadate-timeSolo lo que cambió desde este instante (ISO con zona). Para sincronizar: guarda el actualizado_at más reciente que viste y vuelve a pedir con él (puede repetir filas; son idempotentes).
cursorconsultastringEl siguiente_cursor de la página anterior.
limiteconsultaintegerFilas por página (1–100, 50 por omisión).
curl y JavaScript
curl "https://kmand.mx/api/v1/empleados" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/empleados", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaEmpleados)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "nombre": "<nombre>",
      "rol": "<rol>",
      "activo": true,
      "persona_id": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
      "puesto": "<puesto>",
      "fecha_ingreso": "2026-09-29",
      "periodicidad": "<periodicidad>",
      "tipo_jornada": "<tipo_jornada>",
      "fecha_baja": "2026-09-29",
      "salario_diario": "123.50",
      "salario_diario_centavos": 12350,
      "actualizado_at": "2026-09-29T14:05:00.000-06:00"
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

GET/jornadas· Jornadas (checador)

Alcance: personal:leer

ParámetroTipoDescripción
restaurante_idconsultauuidUna sola sucursal (llaves de organización); por omisión, todas las que la llave alcanza.
updated_sinceconsultadate-timeSolo lo que cambió desde este instante (ISO con zona). Para sincronizar: guarda el actualizado_at más reciente que viste y vuelve a pedir con él (puede repetir filas; son idempotentes).
cursorconsultastringEl siguiente_cursor de la página anterior.
limiteconsultaintegerFilas por página (1–100, 50 por omisión).
empleado_idconsultauuid
desdeconsultadateDesde esta fecha de negocio (incluida).
hastaconsultadateHasta esta fecha de negocio (incluida).
curl y JavaScript
curl "https://kmand.mx/api/v1/jornadas" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/jornadas", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaJornadas)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "empleado_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "fecha_negocio": "2026-09-29",
      "inicio": "2026-09-29T14:05:00.000-06:00",
      "fin": "2026-09-29T14:05:00.000-06:00",
      "estado": "<estado>",
      "minutos": 1,
      "minutos_descanso": 1,
      "descansos": [],
      "correcciones": 1,
      "actualizado_at": "2026-09-29T14:05:00.000-06:00"
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

Webhooks

GET/webhooks· Suscripciones

Alcance: webhooks:gestionar

ParámetroTipoDescripción
restaurante_idconsultauuidUna sola sucursal (llaves de organización); por omisión, todas las que la llave alcanza.
curl y JavaScript
curl "https://kmand.mx/api/v1/webhooks" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch("https://kmand.mx/api/v1/webhooks", {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos, siguiente_cursor } = await r.json();
Respuesta 200 (ListaWebhooks)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "url": "<url>",
      "descripcion": "<descripcion>",
      "eventos": [],
      "incluir_contacto": true,
      "secreto_prefijo": "<secreto_prefijo>",
      "activa": true,
      "desactivada_at": "2026-09-29T14:05:00.000-06:00",
      "desactivada_motivo": "<desactivada_motivo>",
      "fallos_seguidos": 1,
      "ultimo_exito_at": "2026-09-29T14:05:00.000-06:00",
      "creada_at": "2026-09-29T14:05:00.000-06:00",
      "actualizado_at": "2026-09-29T14:05:00.000-06:00"
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

POST/webhooks· Crear una suscripción

Solo eventos cuyos alcances tiene la llave. El secreto se muestra una sola vez.

Alcance: webhooks:gestionar · pide Idempotency-Key

Cuerpo de ejemplo
{
  "url": "https://mi-sistema.example.com/kmand",
  "eventos": [
    "orden.cerrada",
    "producto.agotado"
  ],
  "descripcion": "ERP"
}
curl y JavaScript
curl -X POST "https://kmand.mx/api/v1/webhooks" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://mi-sistema.example.com/kmand","eventos":["orden.cerrada","producto.agotado"],"descripcion":"ERP"}'
const r = await fetch("https://kmand.mx/api/v1/webhooks", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "url": "https://mi-sistema.example.com/kmand",
    "eventos": [
      "orden.cerrada",
      "producto.agotado"
    ],
    "descripcion": "ERP"
  }),
});
const { datos } = await r.json();
Respuesta 201 (UnWebhookCreado)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "url": "<url>",
    "descripcion": "<descripcion>",
    "eventos": [],
    "incluir_contacto": true,
    "secreto_prefijo": "<secreto_prefijo>",
    "activa": true,
    "desactivada_at": "2026-09-29T14:05:00.000-06:00",
    "desactivada_motivo": "<desactivada_motivo>",
    "fallos_seguidos": 1,
    "ultimo_exito_at": "2026-09-29T14:05:00.000-06:00",
    "creada_at": "2026-09-29T14:05:00.000-06:00",
    "actualizado_at": "2026-09-29T14:05:00.000-06:00",
    "secreto": "<secreto>"
  }
}

GET/webhooks/{id}· Una suscripción

Alcance: webhooks:gestionar

ParámetroTipoDescripción
id *en la rutauuid
curl y JavaScript
curl "https://kmand.mx/api/v1/webhooks/:id" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch(`https://kmand.mx/api/v1/webhooks/${id}`, {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos } = await r.json();
Respuesta 200 (UnWebhook)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "url": "<url>",
    "descripcion": "<descripcion>",
    "eventos": [],
    "incluir_contacto": true,
    "secreto_prefijo": "<secreto_prefijo>",
    "activa": true,
    "desactivada_at": "2026-09-29T14:05:00.000-06:00",
    "desactivada_motivo": "<desactivada_motivo>",
    "fallos_seguidos": 1,
    "ultimo_exito_at": "2026-09-29T14:05:00.000-06:00",
    "creada_at": "2026-09-29T14:05:00.000-06:00",
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

PATCH/webhooks/{id}· Cambiar una suscripción

activa: true la reenciende y limpia la racha de fallos.

Alcance: webhooks:gestionar · pide Idempotency-Key

ParámetroTipoDescripción
id *en la rutauuid
Cuerpo de ejemplo
{
  "activa": true
}
curl y JavaScript
curl -X PATCH "https://kmand.mx/api/v1/webhooks/:id" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"activa":true}'
const r = await fetch(`https://kmand.mx/api/v1/webhooks/${id}`, {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "activa": true
  }),
});
const { datos } = await r.json();
Respuesta 200 (UnWebhook)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "restaurante_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "url": "<url>",
    "descripcion": "<descripcion>",
    "eventos": [],
    "incluir_contacto": true,
    "secreto_prefijo": "<secreto_prefijo>",
    "activa": true,
    "desactivada_at": "2026-09-29T14:05:00.000-06:00",
    "desactivada_motivo": "<desactivada_motivo>",
    "fallos_seguidos": 1,
    "ultimo_exito_at": "2026-09-29T14:05:00.000-06:00",
    "creada_at": "2026-09-29T14:05:00.000-06:00",
    "actualizado_at": "2026-09-29T14:05:00.000-06:00"
  }
}

DELETE/webhooks/{id}· Borrar una suscripción

Alcance: webhooks:gestionar · pide Idempotency-Key

ParámetroTipoDescripción
id *en la rutauuid
curl y JavaScript
curl -X DELETE "https://kmand.mx/api/v1/webhooks/:id" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)"
const r = await fetch(`https://kmand.mx/api/v1/webhooks/${id}`, {
  method: "DELETE",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
});
const { datos } = await r.json();
Respuesta 200 (Borrado)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "borrado": true
  }
}

POST/webhooks/{id}/prueba· Mandar una entrega de prueba

Se envía al momento y regresa con su resultado.

Alcance: webhooks:gestionar · pide Idempotency-Key

ParámetroTipoDescripción
id *en la rutauuid
curl y JavaScript
curl -X POST "https://kmand.mx/api/v1/webhooks/:id/prueba" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{}'
const r = await fetch(`https://kmand.mx/api/v1/webhooks/${id}/prueba`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});
const { datos } = await r.json();
Respuesta 200 (UnaEntrega)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "suscripcion_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "evento": "<evento>",
    "estado": "pendiente",
    "intentos": 1,
    "es_prueba": true,
    "reenvio_de": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "ultimo_status": 1,
    "ultima_duracion_ms": 1,
    "ultimo_error": "<ultimo_error>",
    "siguiente_intento_at": "2026-09-29T14:05:00.000-06:00",
    "entregada_at": "2026-09-29T14:05:00.000-06:00",
    "creada_at": "2026-09-29T14:05:00.000-06:00",
    "cuerpo": {
      "efectivo": null
    }
  }
}

GET/webhooks/{id}/entregas· Bitácora de entregas

Las más recientes primero, con su cuerpo y el último resultado.

Alcance: webhooks:gestionar

ParámetroTipoDescripción
id *en la rutauuid
cursorconsultastringEl siguiente_cursor de la página anterior.
limiteconsultaintegerFilas por página (1–100, 50 por omisión).
curl y JavaScript
curl "https://kmand.mx/api/v1/webhooks/:id/entregas" \
  -H "Authorization: Bearer $KMAND_LLAVE"
const r = await fetch(`https://kmand.mx/api/v1/webhooks/${id}/entregas`, {
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
  },
});
const { datos } = await r.json();
Respuesta 200 (ListaEntregas)
{
  "datos": [
    {
      "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "suscripcion_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
      "evento": "<evento>",
      "estado": "pendiente",
      "intentos": 1,
      "es_prueba": true,
      "reenvio_de": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
      "ultimo_status": 1,
      "ultima_duracion_ms": 1,
      "ultimo_error": "<ultimo_error>",
      "siguiente_intento_at": "2026-09-29T14:05:00.000-06:00",
      "entregada_at": "2026-09-29T14:05:00.000-06:00",
      "creada_at": "2026-09-29T14:05:00.000-06:00",
      "cuerpo": {
        "efectivo": null
      }
    }
  ],
  "siguiente_cursor": null,
  "tiene_mas": false
}

POST/webhooks/entregas/{id}/reenviar· Reenviar una entrega

Crea una entrega nueva con el mismo cuerpo (id nuevo y reenvio_de) y la manda al momento.

Alcance: webhooks:gestionar · pide Idempotency-Key

ParámetroTipoDescripción
id *en la rutauuid
curl y JavaScript
curl -X POST "https://kmand.mx/api/v1/webhooks/entregas/:id/reenviar" \
  -H "Authorization: Bearer $KMAND_LLAVE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{}'
const r = await fetch(`https://kmand.mx/api/v1/webhooks/entregas/${id}/reenviar`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KMAND_LLAVE}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});
const { datos } = await r.json();
Respuesta 200 (UnaEntrega)
{
  "datos": {
    "id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "suscripcion_id": "b6152f21-3c67-4896-a4a5-ea72ec44601a",
    "evento": "<evento>",
    "estado": "pendiente",
    "intentos": 1,
    "es_prueba": true,
    "reenvio_de": "3f2a9c1e-7b1d-4c55-9e0a-2d3b4c5d6e7f",
    "ultimo_status": 1,
    "ultima_duracion_ms": 1,
    "ultimo_error": "<ultimo_error>",
    "siguiente_intento_at": "2026-09-29T14:05:00.000-06:00",
    "entregada_at": "2026-09-29T14:05:00.000-06:00",
    "creada_at": "2026-09-29T14:05:00.000-06:00",
    "cuerpo": {
      "efectivo": null
    }
  }
}