Home / Developers
API Developers

Build on GrillTab.

Read sales, checks, menus, labor and inventory, send orders in, keep the menu in sync, and get signed webhooks the moment something happens. The API is part of every plan.

Getting started

The restaurant owner makes a key in the owner dashboard (API keys), picks the locations and what it can read or change, and gives it to you. The key is shown once. Send it on every call:

curl https://hq.grilltab.com/api/v1/locations \
  -H "Authorization: Bearer gt_live_…"

Every call is relayed live to the location's own POS computer, so data is always current. If that computer is offline the call answers 502; try again later. Limit: 120 calls a minute per key (429 past that). Errors are JSON, in plain English: {"error": "…"}.

Try it now: the sandbox

This public test key works on a made-up bar, Demo Taproom (location 1), with realistic sales, checks, menu, labor and inventory. Every call answers exactly like the real API; writes are checked and echoed back, never kept. Up to 60 calls a minute.

curl "https://hq.grilltab.com/api/v1/locations/1/sales?from=2026-10-24&to=2026-10-30" \
  -H "Authorization: Bearer gt_test_demo_taproom_public_sandbox"

Read

CallScopeReturns
GET /locationsanyThe key's locations: id, name, address, online
GET /locations/{id}/sales?from&tosalesTotals, by category and by business day (up to 92 days)
GET /locations/{id}/checks?from&to&after&limitchecksPaid checks with items and payments; page with after = next_after (up to 31 days, 200 a page)
GET /locations/{id}/menumenuItems with ids, groups, prices, sizes, 86 status and counts; choices
GET /locations/{id}/labor?from&tolaborClock-ins with job, hours and rate
GET /locations/{id}/inventoryinventoryOn hand, par, unit cost, vendor
GET /locations/{id}/employeesemployeesNames, roles, active (never PINs or pay)

Dates are business days (YYYY-MM-DD); a business day ends at the location's day-end time, not midnight. Times are the store's local time. Money is in dollars.

Write

Only keys the owner gave a write scope can change anything, and every change shows in the location's activity log.

CallScopeDoes
POST /locations/{id}/menu/items/{item}menu_write{"stock": "out" | "today" | "in" | "count", "count": 6} for 86s and counts; {"price": 12.5, "size_id": 3} for a price (size optional)
POST /locations/{id}/ordersorders_writeSends an order to the POS Orders hub, like an online order. Priced from the POS menu; the guest pays at the POS.
GET /locations/{id}/orders/{external_id}orders_writeIts status: pending, accepted (with check_number) or failed (with error)

Send an order

POST /api/v1/locations/12/orders
{
  "external_id": "A-1001",          // your order number: a retry never makes a second order
  "type": "pickup",                 // pickup | delivery | dine_in (with "table")
  "pickup_at": "2026-11-01 18:30",  // optional, store time: the kitchen fires it on time
  "customer": { "name": "Pat", "phone": "5551234567" },
  "items": [ { "menu_item_id": 534, "qty": 2, "notes": "extra crispy",
               "modifiers": [ { "name": "Ranch" } ] } ],
  "notes": "Leave at the bar"
}

The location picks orders up within a minute while it's online, prints the ticket and sends it to the kitchen screens.

Webhooks

A manager adds your https address in the POS back office (Integrations → Webhooks) and gives you its secret. Each event is a POST of { id, event, created_at, location, data } with the headers X-GrillTab-Event, X-GrillTab-Delivery and X-GrillTab-Signature: t=<unix seconds>,v1=<hex>. Answer with a 2xx. Failed deliveries are retried after 1 min, 5 min, 30 min, 2 h, 6 h and 24 h, and every delivery can be sent again from the POS.

EventWhen
order.paidA check is paid in full
payment.createdA payment is taken (cash, card, gift card…)
payment.refundedA payment is refunded
item.86An item or choice is 86'd or set to a count
item.backAn item or choice is back in stock
menu.changedThe menu was changed
punch.inSomeone clocks in
punch.outSomeone clocks out
drawer.closedA cash drawer is closed
keg.changedA keg is tapped, kicked or changed
activity.*Every line of the activity log: voids, comps, discounts, no-sales, refunds, settings changes…

Check the signature

const crypto = require('crypto');
function valid(rawBody, header, secret) {
  const { t, v1 } = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  const want = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
  return Math.abs(Date.now() / 1000 - Number(t)) < 300 && v1.length === want.length && crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(want));
}

Nightly export

Each morning a location can send the business day as CSV files in one .zip to a folder, an https address or an SFTP server (Settings → Providers → Nightly export). Each .zip has a FIELDS.txt with the list below. The owner can also download every table at any time (Settings → Providers → Your data).

OrderDetails.csv

ColumnWhat it is
idCheck number (the same number on the receipt and in every other file)
tab_nameTab or guest name
table_noTable
guestsNumber of guests
dining_optionDine in, to go, delivery…
sourcepos, online, kiosk, qr, phone, app…
statusopen, closed or void
opened_atOpened (store time)
closed_atPaid and closed
serverEmployee who owns the check

ItemSelectionDetails.csv

ColumnWhat it is
order_idCheck number
item_idThis line's own number
nameItem as rung in
qtyQuantity
unit_pricePrice of one with its choices, before discounts
revenue_classFood, Beer, Liquor, Wine…
modifier_textChoices and notes
statusordered, sent, made, void
comp1 if comped
sent_atSent to the kitchen or bar

PaymentDetails.csv

ColumnWhat it is
order_idCheck number
payment_idThis payment's own number
methodcash, card, gift, house account…
amountPaid toward the check, without tip
tipTip
card_feeSurcharge or convenience fee charged to the guest
created_atWhen it was taken
employeeWho took it

TimeEntries.csv

ColumnWhat it is
idShift number
employeeEmployee
jobJob worked
clock_inClock in (store time)
clock_outClock out (blank if still on)
rateHourly rate for that job

Changelog

  • 2026-10-31: Write API (86s, counts and prices; orders in, with status). A field guide in every nightly export.
  • 2026-10-31: Read API v1 (sales, checks, menu, labor, inventory, employees) and signed webhooks.

Questions or a partnership? Get in touch.

Ready to run a tighter bar?

Sign up in a few minutes. Your equipment ships configured for your bar, ready to plug in and take orders.