tabsettleDEVELOPERS
Overview

Quickstart.

Two calls: list a restaurant’s locations, then push a POS check’s state so it appears on the table’s QR code.

# List a restaurant's locations
curl https://api.tabsettle.com/v1/locations \
  -H "Authorization: Bearer ts_live_XXXXXXXXXXXXXXXXXXXXXXXX"

# Push a POS check's current full state (idempotent — safe to replay)
curl -X PUT https://api.tabsettle.com/v1/checks/external/order_123 \
  -H "Authorization: Bearer ts_live_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
        "table": { "number": "12" },
        "status": "open",
        "items": [
          { "external_id": "li_1", "name": "Burrata", "quantity": 1, "price_cents": 1600, "note": "no basil" }
        ],
        "totals": { "subtotal_cents": 1600, "tax_cents": 142, "total_cents": 1742 }
      }'
const BASE = 'https://api.tabsettle.com/v1';
const KEY = 'ts_live_XXXXXXXXXXXXXXXXXXXXXXXX';

// List a restaurant's locations
const locations = await fetch(`${BASE}/locations`, {
  headers: { Authorization: `Bearer ${KEY}` },
}).then((r) => r.json());

// Push a POS check's current full state (idempotent — safe to replay)
await fetch(`${BASE}/checks/external/order_123`, {
  method: 'PUT',
  headers: { Authorization: `Bearer ${KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    table: { number: '12' },
    status: 'open',
    items: [
      { external_id: 'li_1', name: 'Burrata', quantity: 1, price_cents: 1600, note: 'no basil' },
    ],
    totals: { subtotal_cents: 1600, tax_cents: 142, total_cents: 1742 },
  }),
});
Every response carries an X-Request-Id header — include it when contacting support so we can trace the exact request.

How ingestion works.

Send the check’s complete current state every time anything changes. The endpoint is built so you never have to reason about deltas:

  • Replays are no-ops — the call is idempotent.
  • Out-of-order updates converge on the same state.
  • Items are diffed by your external_id.
One guard: removing or price-decreasing an item that guests have already claimed is rejected with 409 conflict_with_paid_items — a live bill-split is never silently changed underneath the guests. See Errors.