Changelog
Every change to the API, dated to the release it shipped in. A correction says what the reference used to say. What may change within v1, and what will not, is on Versioning.
September 30, 2026
get-current-key (GET /key) describes the key making the request: its name, prefix, scopes, expiry, who made it, and the endpoints it may call now.
get-current-key answers every key, whatever its scopes: it tells a key only about itself.
run-report takes view=display: the report as its page prints it, every value formatted. A table's rows are its data rows, stopping at 200, and its totals line is totals, apart from them, so a column summed over rows counts nothing twice. view=raw, the default, is the answer it always gave.
list-menu-items filters by q (name or code), category_id, available and active. list-orders filters by status, channel, opened_from and opened_to (business days, sent together), table_id and q (the order number or an outside system's check code). list-materials filters by q and below_reorder.
get-restaurant answers tax_label (the same value as vat_label), day_starts_at_minute, today (the business day) and tips_enabled. list-reports lists the query parameters each report takes. list-stock-movements answers each movement's reference: the record it came from, such as a purchase's number (PO-200) or an order's (Order #142).
The whole API is described as OpenAPI 3.1 at /api/v1/openapi.json, with no key needed, and every endpoint has its own page under the API reference.
A new scope, payroll:read, lets a key read pay and labor cost where an endpoint offers them.
Endpoints have verb-first ids (list-orders, create-order), which are also their reference pages' addresses. Paths and methods did not change.
Every query is checked: a parameter an endpoint does not take, or one sent twice, is 422 invalid_request, naming it and listing the ones it takes. Before, an unknown parameter was ignored, so ?rnage=30d ran the default span.
adjust-stock publishes the stockroom's own limit on quantity_milli and unit_cost, 100,000,000: a larger value is 422 invalid_request, where the stockroom refused it 409 refused. Its reason is trimmed: a blank one is 422 invalid_request, before the Idempotency-Key is claimed, where the stockroom refused it 409 refused.
A request that sends a body with GET or HEAD is 422 invalid_request, where the body was ignored. A path id (order_id, item_id, table_id, material_id) is 1 to 100 letters, digits, - or _: any other is 422 invalid_request naming that pattern, where it was 404 not_found.
run-report's report_id is one of the report ids list-reports lists: an unknown one is 422 invalid_request naming the accepted values, where it was 404 not_found. A report takes only the parameters its span uses; range beside from or to is refused, where range used to win.
run-report refuses, 422 invalid_request, a span it used to change without saying so: from without to (it ran from from to today), to without from (it ran from the first day of the report's default span to to), from after to (the two were swapped), a day, month or from in the future (it ran for today, this month or today alone), a day or month more than 366 days back (it ran for today, or this month), a from more than 366 days back (it ran as asked, or from 366 days before to), and from and to more than 366 days apart (from was moved to 366 days before to). A to after today is still clipped to today.
Report 24, Labor (labor), needs payroll:read on the key as well as reports:read. A key without it is answered 404 not_found, as for any report it may not see, and list-reports leaves it out.
A key acts as its maker cut down, endpoint by endpoint, to the scope each endpoint is filed under, and never as an owner. So another scope on the same key never changes what an endpoint does. See Authentication.
run-report costs 5 of a key's 60 units a minute; every other request still costs 1. From one network, more than 30 requests a minute with a well-formed key that is unknown, revoked or expired are answered 429 rate_limited. See Rate limits.
- GETGet the restaurant
- GETList menu categories
- GETList menu items
- GETGet a menu item
- PATCHMark an item sold out or back on sale
- GETList tables
- PATCHSet a table's status
- GETList orders
- GETGet an order
- POSTCreate an order
- POSTAdd a round to an order
- POSTSend an order to the kitchen
- POSTCancel an unpaid order
- GETList materials
- GETGet a material
- GETGet a stock card
- POSTAdjust stock
- GETList reports
- GETRun a report
A 401 sends WWW-Authenticate: Bearer realm="Table Buddy API" and no RateLimit-* headers: before, it reported an exhausted limit for a key it had not identified. x-api-key is documented as the alternative to Authorization: Bearer, which wins when both are sent.
HEAD runs the GET and answers its status and headers with no body, where it answered 404. OPTIONS answers 204 with the path's Allow; PUT and DELETE answer 405 method_not_allowed with Allow. A path no endpoint has answers 404 unknown_endpoint with request-id and x-error-code, where it answered not_found with neither.
Three error codes are new: permission_required (403), unknown_endpoint (404) and method_not_allowed (405). Errors lists all twenty with what to do about each; the old page named five.
A line's note (at most 200 characters, a note for the kitchen) is documented on create-order and add-order-items; the old page left it out.
Text the database cannot store, U+0000 (NUL) or an unpaired UTF-16 surrogate, in any query parameter or request string is 422 invalid_request naming the field, before an Idempotency-Key is claimed, where it was 500 internal_error. Every text field publishes the rule as its pattern.
September 24, 2026
The API's first release: the restaurant; the menu and taking an item off sale; tables and their status; orders, from opening one to sending rounds and cancelling; raw materials, their stock cards and stock adjustments; and the reports. Keys are made under API Keys, one restaurant each, with scopes chosen when a key is made.
- GETGet the restaurant
- GETList menu categories
- GETList menu items
- GETGet a menu item
- PATCHMark an item sold out or back on sale
- GETList tables
- PATCHSet a table's status
- GETList orders
- GETGet an order
- POSTCreate an order
- POSTAdd a round to an order
- POSTSend an order to the kitchen
- POSTCancel an unpaid order
- GETList materials
- GETGet a material
- GETGet a stock card
- POSTAdjust stock
- GETList reports
- GETRun a report