Table Buddy API v1
Server-to-server access to one restaurant. The API uses the same order, stock and report engines as the console.
Your first request
Create a scoped key under API Keys. Store it as TABLEBUDDY_API_KEY on your server and set TABLEBUDDY_URL to this installation’s origin.
curl "$TABLEBUDDY_URL/api/v1/restaurant" \ -H "Authorization: Bearer $TABLEBUDDY_API_KEY"
Keys are shown once, stored as a SHA-256 digest, expire after the selected lifetime and can be revoked. Every request rechecks the creator’s membership, suspension status and current permissions. A key is revoked outright when its creator signs out everywhere, resets a lost password, is suspended or has their sessions ended by the platform, or leaves or is removed from the restaurant; being invited back does not revive it, so issue a new key. A routine password change keeps keys working. Browser cookies do not authenticate API calls.
Conventions
- Base path:
/api/v1. Send JSON withContent-Type: application/json. Maximum body: 1 MiB. - Money is integer minor units; each response carries
currencyandminor_digits. Rates ending in_bpare basis points (750 means 7.5%). Stock quantities ending in_milliare thousandths of the material unit. - Instants are ISO timestamps. Report days use the restaurant’s IANA time zone.
- Lists accept
limit(1–100, default 50) andcursor. Responses containdata,has_moreandnext_cursor. Copy the last response’s cursor. Categories, items, tables and materials use ID order; orders and stock movements are newest first. The report catalogue is a complete, unpaginated list. - Keys allow 60 requests per minute in a shared fixed window. A 429 response includes
Retry-After; all authenticated responses include rate-limit headers and arequest-id. - Errors use
{"error":{"code":"...","message":"..."}}. Expect 401 for invalid keys, 403 for missing scopes or lost issuer access, 404 for unknown resources, 409 for a business-rule refusal, 413 for large bodies, 415 for non-JSON, 422 for invalid fields and 429 for limits. - Requests begun before a revocation may finish. Keep keys out of URLs, browser code and logs.
Endpoints
Select a section below for request examples. {id} is a resource ID; for reports it is the report slug.
| Method and path | Scope | Purpose |
|---|---|---|
| GET /api/v1/restaurant | Any valid key | Restaurant profile and currency |
| GET /api/v1/menu/categories | menu:read | List menu categories |
| GET /api/v1/menu/items | menu:read | List menu items and add-ons |
| GET /api/v1/menu/items/{id} | menu:read | Get a menu item |
| PATCH /api/v1/menu/items/{id}/availability | menu:write | Set menu availability |
| GET /api/v1/tables | tables:read | List tables |
| PATCH /api/v1/tables/{id}/status | tables:write | Set an unoccupied table status |
| GET /api/v1/orders | orders:read | List orders (newest first) |
| GET /api/v1/orders/{id} | orders:read | Get an order and its lines |
| POST /api/v1/orders | orders:write | Create an order |
| POST /api/v1/orders/{id}/items | orders:write | Add a round to an order |
| POST /api/v1/orders/{id}/send | orders:write | Send unsent items to the kitchen |
| POST /api/v1/orders/{id}/cancel | orders:cancel | Cancel an unpaid order |
| GET /api/v1/inventory/materials | inventory:read | List materials and stock balances |
| GET /api/v1/inventory/materials/{id} | inventory:read | Get a material |
| GET /api/v1/inventory/materials/{id}/movements | inventory:read | Get a stock card |
| POST /api/v1/inventory/materials/{id}/adjustments | inventory:write | Adjust stock |
| GET /api/v1/reports | reports:read | List available reports |
| GET /api/v1/reports/{id} | reports:read | Run a report; id is its catalogue slug |
Restaurant profile and currency
GET /api/v1/restaurant
Required scope: any valid key.
No request body.
List menu categories
GET /api/v1/menu/categories
Required scope: menu:read.
No request body.
Set menu availability
PATCH /api/v1/menu/items/{id}/availability
Required scope: menu:write.
{
"available": false
}List tables
GET /api/v1/tables
Required scope: tables:read.
No request body.
Set an unoccupied table status
PATCH /api/v1/tables/{id}/status
Required scope: tables:write.
{
"status": "CLEANING"
}status: AVAILABLE, RESERVED or CLEANING. Tables with open orders cannot be changed by hand.
List orders (newest first)
GET /api/v1/orders
Required scope: orders:read.
No request body.
Get an order and its lines
GET /api/v1/orders/{id}
Required scope: orders:read.
No request body.
Create an order
POST /api/v1/orders
Required scope: orders:write.
{
"type": "COUNTER",
"lines": [
{
"menu_item_id": "ITEM_ID",
"quantity": 1,
"addon_ids": []
}
],
"send": false
}type: DINE_IN, TAKEAWAY, COUNTER or DELIVERY. lines: 1–200 items; quantity: 1–999; up to 40 addon_ids per line. Optional table_id, customer_name (100 characters), customer_phone (40), delivery_address (500), guests (1–999), note (500). send defaults to false. Dine-in requires a table when table ordering is enabled; delivery requires delivery_address. An item whose category is hidden from the POS (is_active false under menu/categories) is refused with 409, as it is at the till — here and when adding a round.
Add a round to an order
POST /api/v1/orders/{id}/items
Required scope: orders:write.
{
"lines": [
{
"menu_item_id": "ITEM_ID",
"quantity": 1,
"addon_ids": []
}
],
"send": false
}Send unsent items to the kitchen
POST /api/v1/orders/{id}/send
Required scope: orders:write.
{}Cancel an unpaid order
POST /api/v1/orders/{id}/cancel
Required scope: orders:cancel.
{
"reason": "Duplicate order"
}List materials and stock balances
GET /api/v1/inventory/materials
Required scope: inventory:read.
No request body.
Get a material
GET /api/v1/inventory/materials/{id}
Required scope: inventory:read.
No request body.
Get a stock card
GET /api/v1/inventory/materials/{id}/movements
Required scope: inventory:read.
No request body.
Adjust stock
POST /api/v1/inventory/materials/{id}/adjustments
Required scope: inventory:write.
{
"mode": "count",
"quantity_milli": 1500,
"reason": "Physical count"
}mode: in, out, wastage or count. quantity_milli: non-negative integer. Optional unit_cost is minor currency units per whole material unit. reason is required (up to 300 characters). Stock out and wastage cannot exceed on-hand.
List available reports
GET /api/v1/reports
Required scope: reports:read.
No request body.
Run a report; id is its catalogue slug
GET /api/v1/reports/{id}
Required scope: reports:read.
No request body.
Use day=YYYY-MM-DD, month=YYYY-MM, or from/to day keys according to the catalogue’s span. Presets: today, yesterday, 7d, 30d, month, lastMonth, 90d, year. The resolved span is returned; future or out-of-range dates follow the console’s clamping rules. Pending settlement always reports now. Report results retain the console’s column keys and raw values for consistent rendering.