Skip to main content
The Restaurante API tracks two types of inventory: ingredientes (raw ingredients used in recipes) and productos (standalone items sold directly). Understanding the difference is key to setting up automatic stock deduction.

Two inventory types

Ingredientes

Raw ingredients with a floating-point cantidad, a unidad of measure, and a cantidad_minima threshold for low-stock alerts. Their stock is reduced when a plato that uses them is sold.

Productos

Standalone items (drinks, packaged goods, etc.) with an integer stock. Their stock is reduced directly when the product is included as a line item in a closed transaction.

Managing ingredientes

Create an ingredient

curl -X POST http://localhost:3000/api/ingredientes \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "nombre": "Tomate",
    "unidad": "kg",
    "cantidad": 50.5,
    "cantidad_minima": 10
  }'
{
  "id": "abc123xyz0",
  "nombre": "Tomate",
  "unidad": "kg",
  "cantidad": 50.5,
  "cantidad_minima": 10
}
The id is a 10-character nanoid generated by the server.

Update stock manually

Use PATCH /api/ingredientes/:id to adjust the quantity — for example after a delivery:
curl -X PATCH http://localhost:3000/api/ingredientes/abc123xyz0 \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "cantidad": 75.0
  }'

List all ingredients

curl http://localhost:3000/api/ingredientes \
  -H "Authorization: Bearer $TOKEN"
This returns all active (non-deleted) ingredients. To find items below their minimum threshold, filter client-side where cantidad < cantidad_minima.

Delete an ingredient

Deletion is a soft delete — the record is retained in the database with borrado_en set:
curl -X DELETE http://localhost:3000/api/ingredientes/abc123xyz0 \
  -H "Authorization: Bearer $TOKEN"
Only users with the admin role can create, update, or delete ingredientes.

Managing platos and recipes

A plato represents a cooked dish on the menu. Its price is set when you create it. The recipe (which ingredients it uses and in what quantities) is defined by linking ingredientes to the plato.

Create a plato

curl -X POST http://localhost:3000/api/platos \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "nombre": "Sopa de Maní",
    "precio": 25.00
  }'
{
  "id": "plato_xyz789",
  "nombre": "Sopa de Maní",
  "precio": "25.00"
}
After creating the plato, define its recipe by adding ingredients. The cantidad here is the amount of the ingredient consumed per serving of the plato.
curl -X POST http://localhost:3000/api/platos/plato_xyz789/ingredientes \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "ingrediente_id": "abc123xyz0",
    "cantidad": 0.2
  }'
This means every time one unit of “Sopa de Maní” is sold, 0.2 kg of “Tomate” is deducted from inventory.

View a plato’s ingredients

curl http://localhost:3000/api/platos/plato_xyz789/ingredientes \
  -H "Authorization: Bearer $TOKEN"

Update ingredient quantity in a recipe

curl -X PATCH http://localhost:3000/api/platos/plato_xyz789/ingredientes/abc123xyz0 \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "cantidad": 0.25
  }'

Remove an ingredient from a recipe

curl -X DELETE http://localhost:3000/api/platos/plato_xyz789/ingredientes/abc123xyz0 \
  -H "Authorization: Bearer $TOKEN"

How automatic stock deduction works

Stock is deducted only when a transaction closes (estado: cerrado). The deduction runs once at closure:
  1. For each detalle_item in the transaction:
    • If the item is a producto: stock is decremented by item.cantidad.
    • If the item is a plato: for each entry in plato_ingredientes, the ingredient’s cantidad is decremented by plato_ingredientes.cantidad × item.cantidad.
  2. For each detalle_item_extra with an ingrediente_id: the ingredient’s cantidad is decremented by extra.cantidad.
Extras with only a descripcion (free-text extras) do not affect inventory.
A transaction only closes when both estado_cocina = terminado and monto_pendiente = 0. Stock is never deducted twice — the deduction is guarded by a check of the previous estado value.

Checking low stock

There is no dedicated low-stock endpoint. To identify ingredients below their minimum threshold, retrieve the full list and filter:
curl http://localhost:3000/api/ingredientes \
  -H "Authorization: Bearer $TOKEN"
Then filter client-side:
const lowStock = ingredientes.filter(
  (i) => i.cantidad < i.cantidad_minima
);
The cantidad_minima field is set per ingredient when you create or update it. Set it to 0 to disable the threshold for that ingredient.

Build docs developers (and LLMs) love