Skip to content
API referenceAuthentication and scopes

Authentication and scopes

A key belongs to one restaurant and acts as the person who made it, cut down, endpoint by endpoint, to the scope that endpoint is filed under. It never acts as an owner or an admin, and it can do nothing its maker cannot do in the console.

Sending the key

Send it as a bearer token. x-api-key is accepted too, for clients that cannot send one; when both are sent, Authorization wins. Prefer Authorization: a proxy’s logs are more likely to keep a custom header.

Either header
Authorization: Bearer $TABLEBUDDY_API_KEY
# or
x-api-key: $TABLEBUDDY_API_KEY
Server-side only
A key is shown once, when it is made, and Table Buddy keeps only a SHA-256 hash of it. Keep it on your server: never in a browser, an app, a URL or a log. Browser cookies never authenticate an API call.

Who makes keys

Keys are made under API Keys in the console. Owners and admins make them, and so can anyone whose staff role has Create API keys (api.keys), for keys of their own. Someone who holds Change restaurant settings (settings.manage) sees and revokes every key in the restaurant. A maker may put on a key only the scopes their own role allows; the form shows the rest disabled, with the reason.

Scopes

A key’s scopes are chosen when it is made and never change: a new need is a new key. Calling an endpoint outside them answers 403 insufficient_scope. A scope with a caution is never ticked for you; a new key starts with the reads that carry none, so it starts read-only and holds no guest, staff or pay details.

  • Moves money
  • Guest details
  • Staff details
  • Pay and labor cost
  • Cancels or voids
  • Emails staff
  • menu:read
    Read the menu
    Ticked on a new key

    Its maker needs one of: Take orders on the POS (pos.use), Edit the menu (menu.manage)

    It grants, on its endpoints: Take orders on the POS (pos.use), Edit the menu (menu.manage)

  • menu:write
    Mark items sold out

    Its maker needs one of: Edit the menu (menu.manage)

    It grants, on its endpoints: Edit the menu (menu.manage)

  • tables:read
    Read tables
    Ticked on a new key

    Its maker needs one of: Manage tables and reservations (tables.manage), Take orders on the POS (pos.use)

    It grants, on its endpoints: Manage tables and reservations (tables.manage), Take orders on the POS (pos.use)

    Endpoints:
  • tables:write
    Set table status

    Its maker needs one of: Manage tables and reservations (tables.manage), Take orders on the POS (pos.use)

    It grants, on its endpoints: Manage tables and reservations (tables.manage), Take orders on the POS (pos.use)

  • orders:readGuest details
    Read orders, payments and tips

    Its maker needs one of: Take orders on the POS (pos.use), View reports (reports.view)

    It grants, on its endpoints: Take orders on the POS (pos.use), View reports (reports.view)

  • orders:write
    Create orders, send rounds and change unsent items

    Its maker needs one of: Take orders on the POS (pos.use)

    It grants, on its endpoints: Take orders on the POS (pos.use)

  • orders:cancelCancels or voids
    Cancel unpaid orders

    Its maker needs one of: Cancel orders and items (pos.void)

    It grants, on its endpoints: Cancel orders and items (pos.void)

  • inventory:read
    Read stock and costs
    Ticked on a new key

    Its maker needs one of: View stock (inventory.view)

    It grants, on its endpoints: View stock (inventory.view)

  • inventory:write
    Adjust stock

    Its maker needs one of: Adjust stock (inventory.manage)

    It grants, on its endpoints: Adjust stock (inventory.manage)

  • payroll:readPay and labor cost
    Read pay, labor cost and labor %

    Its maker needs one of: Pay rates and payroll (payroll.manage)

    It grants, on its endpoints: Pay rates and payroll (payroll.manage)

    Also counts on these, beside their own scope:
  • reports:read
    Read reports
    Ticked on a new key

    Its maker needs one of: View reports (reports.view)

    It grants, on its endpoints: View reports (reports.view)

  • no scope
    Any valid key

What a scope lets a key call grows only on purpose: a stronger power arrives as a new scope that no existing key carries, and an endpoint filed under a scope keys already hold is announced in the changelog first.

Endpoint by endpoint

On each request the API works out what the key may do on that endpoint alone: its maker’s permissions today, cut down to what the endpoint’s scope grants. Another scope on the same key adds nothing there. The one deliberate exception is written on the endpoint’s page: a scope such as payroll:read that widens it when the key carries both. Each endpoint page names the permission its maker needs, and the answer is 403 permission_required, naming it, when the key’s permissions there do not include it.

  • The maker’s permissions are read on every request, so taking a permission away takes it from their keys at once.
  • A key is never an owner or an admin to the engines, and never oversees a cash drawer: cash moves only through its maker’s own open drawer.
  • A write made with a key is recorded in the restaurant’s activity log as its maker’s act, marked as made through the API.

What ends a key

Revoked at once when
  • Someone revokes it under API Keys.
  • Its creator signs out everywhere.
  • Its creator resets a lost password.
  • The platform suspends its creator, or ends their sessions.
  • Its creator leaves the restaurant, or is removed from it. Being invited back does not revive it: make a new key.
Expires when
  • It reaches the end of the lifetime chosen when it was made.
Refused while
  • Its creator no longer holds any permission that could put one of its scopes on a key: those endpoints answer issuer_permission_changed until the permission is back.
Kept when
  • A routine password change keeps keys working.

A request already under way when a key is revoked may finish; the next one is refused.

401 and 403

A 401 carries WWW-Authenticate and no rate-limit headers: the key is not known yet, so it has no window to report. A missing or malformed key costs nothing; a well-formed key that is unknown, revoked or expired counts toward a limit per network (see Rate limits).

401missing_api_key
No Authorization: Bearer header and no x-api-key header.

Fix: Send the key as Authorization: Bearer <key>.

WWW-Authenticate: Bearer realm="Table Buddy API"

401invalid_api_key
The key is unknown, revoked or expired (answered alike).

Fix: Check the key on API Keys; make a new one if it was revoked or expired.

WWW-Authenticate: Bearer realm="Table Buddy API", error="invalid_token", error_description="The API key is invalid, expired or revoked"

403insufficient_scope
The key does not carry the endpoint's scope.

Fix: Scopes are fixed when a key is made: make a new key with the scope.

WWW-Authenticate: Bearer realm="Table Buddy API", error="insufficient_scope", scope="orders:read"

403issuer_access_ended
The key's creator has left the restaurant, was suspended, or was removed and invited back.

Fix: Make a new key from an active account.

403issuer_permission_changed
The key's creator no longer holds any permission that could put this scope on a key.

Fix: Ask an owner to restore the permission, or make a new key from an account that holds it.

403permission_required
The key's permissions for this endpoint (its creator's, cut down to the endpoint's scope) do not include what this endpoint, or this argument, needs. The message names it.

Fix: Use a key with the named scope, from a creator who holds the named permission.

Every error code