TableFox Developer API

REST endpoints for partner integrations — POS systems, chat widgets, AI phone agents, anything that needs to read availability or write bookings on behalf of a restaurant.

Download OpenAPI 3.0 spec Request an API key

Overview

Base URL: https://tablefox.co.uk
Format: JSON in, JSON out. UTF-8.
Versioning: /api/v1/* — semver, breaking changes only on a major bump.
Errors: standard { "error": "...", "errors": ["...", "..."] } shape with the right HTTP status (400/401/403/404/409/500).

Each restaurant has its own API key, issued by TableFox. To integrate on behalf of a restaurant, ask them to generate a key from their TableFox dashboard, or email hello@tablefox.co.uk. Master keys (one key, many restaurants) are available for accredited partners — get in touch and we'll provision one.

Quick start

Check availability for a party of 4 on 5 April 2026:

# cURL
curl 'https://tablefox.co.uk/api/v1/availability?date=2026-04-05&covers=4' \
  -H 'X-API-Key: your-key-here'

Create a booking:

# cURL
curl 'https://tablefox.co.uk/api/v1/bookings' \
  -X POST \
  -H 'X-API-Key: your-key-here' \
  -H 'Content-Type: application/json' \
  -d '{"date":"2026-04-05","time":"19:00","covers":4,"first_name":"Alex","phone":"+447450000000"}'

Once you've got that working, download the OpenAPI spec and import it into Postman, Insomnia or your client generator of choice for the rest.

Authentication & endpoint reference

Three ways to send your key — pick whichever your HTTP client prefers. Click any endpoint below to see request fields, responses and error codes.

Heads-up — self-service endpoints.
Three endpoints (GET /bookings/lookup, POST /bookings/modify, POST /bookings/cancel) are tagged self-service in the sidebar — they're the customer-facing variants used by chat widgets and AI phone agents. They require the booking's phone number to match the request and respect the restaurant's edit/cancel cutoff window. If you're building an integration on behalf of the restaurant (POS, EPOS, CRM, etc.) you'll usually want the equivalent untagged endpoints instead: POST /bookings/:id/modify and POST /bookings/:id/status with CANCELLED.

All integration endpoints require authentication via one of:

X-API-Key headerX-API-Key: your-key-here
Query parameter?api_key=your-key-here
Bearer tokenAuthorization: Bearer your-key-here

Per-restaurant key: Identifies the restaurant automatically. No restaurant_id needed.

Master key: Requires restaurant_id parameter to identify which restaurant.

Check available time slots for a date and party size.

Query Parameters
ParamTypeRequiredDescription
datestringYesDate in YYYY-MM-DD format
coversintegerYesNumber of guests (1-30)
servicestringNoService code filter (e.g. LUNCH, DINNER)
restaurant_idintegerMaster key onlyRestaurant ID
Response
{ "success": true, "restaurant": "Viva Brazil", "date": "2026-04-05", "covers": 4, "slots": [{ "time": "12:00", "service": "LUNCH", "available": true }, ...], "count": 15 }

Create a new booking. Sends confirmation email/SMS if auto-accepted. Sends payment link if restaurant requires deposit/card hold.

Request Body (JSON)
FieldTypeRequiredDescription
datestringYesYYYY-MM-DD
timestringYesHH:MM (24-hour)
coversintegerYesNumber of guests (1-30)
first_namestringYesCustomer first name
last_namestringNoCustomer last name
phonestringConditionalPhone or email required
emailstringConditionalRequired if restaurant has payment mode enabled
notesstringNoSpecial requests
tagsstring/arrayNoComma-separated or array: BIRTHDAY, ANNIVERSARY, ALLERGY, HIGH_CHAIR, VIP
sourcestringNoONLINE, INTERNAL, PHONE, WALKIN, AI_PHONE. Default: PHONE
restaurant_idintegerMaster key onlyRestaurant ID
Response
{ "success": true, "booking": { "booking_id": 123, "booking_reference": "RB-20260405-A1B2C3", "status": "CONFIRMED", "date": "2026-04-05", "time": "19:00", "covers": 4, "customer_name": "John Smith" }, "payment": null, "message": "Booking confirmed successfully" }

Payment response (when deposit/hold required):

{ "success": true, "booking": { ... "status": "PENDING_PAYMENT" }, "payment": { "required": true, "mode": "DEPOSIT", "amount_formatted": "£20.00", "message": "A deposit of £20.00 is required. A payment link has been sent." } }

List bookings for a date with optional filters. Cancelled bookings are excluded unless you ask for them via status=CANCELLED.

Query Parameters
ParamTypeRequiredDescription
datestringNoYYYY-MM-DD (defaults to today)
statusstringNoFilter: PENDING, CONFIRMED, SEATED, COMPLETED, NO_SHOW, CANCELLED
servicestringNoService code (LUNCH, DINNER, …)
qstringNoSearch name / phone / email / reference (min 2 chars)
search_all_datesbooleanNoSet 1 with q to search across all dates
pageintegerNoPage number (default 1)
per_pageintegerNo1–50 (default 30)
restaurant_idintegerMaster key onlyRestaurant ID
Response
{ "success": true, "date": "2026-04-05", "bookings": [{ "booking_id": 123, "reference": "RB-...", "name": "John Smith", "phone": "+44...", "covers": 4, "time": "19:00", "status": "CONFIRMED", "service": "DINNER", "tables": ["T5"], "notes": "Window seat", "extras_count": 0, ... }], "pagination": { "page": 1, "per_page": 30, "total": 17, "total_pages": 1 } }

Full detail for a single booking — covers, tables, tags, voucher redemptions, extras, customer stats (VIP / blocked / total visits) and timestamps.

Path Parameters
ParamTypeRequiredDescription
idintegerYesBooking ID
restaurant_idintegerMaster key onlyRestaurant ID (query param)
Response (abridged)
{ "success": true, "booking": { "booking_id": 123, "reference": "RB-...", "status": "CONFIRMED", "date": "2026-04-05", "time": "19:00", "covers": 4, "customer": { "customer_id": 42, "name": "John Smith", "phone": "+44...", "email": "...", "is_vip": false, "total_bookings": 5, "total_no_shows": 0 }, "tables": [{ "table_id": 7, "name": "T5", "zone": "Window" }], "tags": ["BIRTHDAY"], "notes": "...", "internal_notes": "...", "vouchers": [...], "extras": [...] } }

Look up a customer's upcoming bookings by phone number. Only returns bookings matching the phone — no data leakage.

Query Parameters
ParamTypeRequiredDescription
phonestringYesCustomer phone number
restaurant_idintegerMaster key onlyRestaurant ID
Response
{ "success": true, "bookings": [{ "booking_id": 123, "booking_reference": "RB-...", "date": "2026-04-05", "time": "19:00", "covers": 4, "status": "CONFIRMED", "name": "John Smith", "editable": true, "editable_reason": null, "cancellable": true, "cancellable_reason": null }], "count": 1, "editing_allowed": true, "editing_cutoff_hours": 24 }

editable requires both customer editing to be enabled AND the booking to be outside the cutoff window. cancellable only requires the booking to be outside the cutoff window. The same editing_cutoff_hours applies to both.

Modify an existing booking. Requires phone match for security. Respects restaurant edit settings and cutoff.

Request Body (JSON)
FieldTypeRequiredDescription
booking_idintegerYesBooking ID from lookup
phonestringYesMust match booking's customer phone
new_datestringNoNew date YYYY-MM-DD (omit to keep same)
new_timestringNoNew time HH:MM (omit to keep same)
new_coversintegerNoNew party size (omit to keep same)
notesstringNoUpdated special requests (omit to keep same)
tagsstring/arrayNoUpdated tags: BIRTHDAY, ANNIVERSARY, ALLERGY, HIGH_CHAIR (omit to keep same)
restaurant_idintegerMaster key onlyRestaurant ID
Response
{ "success": true, "message": "Booking updated successfully", "booking": { "booking_id": 123, "booking_reference": "RB-...", "date": "2026-04-06", "time": "20:00", "covers": 4, "status": "CONFIRMED" } }
Error Responses
  • 403 — Editing not allowed or within cutoff period
  • 404 — Booking not found or phone doesn't match
  • 400 — Time conflict with another booking

Change a booking's date, time, covers, notes, tags, or assigned tables. Acts on behalf of the restaurant — no phone match, no cutoff window. Use this from POS, EPOS, CRM or any other restaurant-side integration. (The self-service /api/v1/bookings/modify is the customer-facing equivalent with phone-match + cutoff.)

Request Body (JSON)
FieldTypeRequiredDescription
datestringNoNew YYYY-MM-DD
timestringNoNew HH:MM
coversintegerNoNew party size
notesstringNoReplace customer-facing notes
internal_notesstringNoReplace staff-only notes
tagsarrayNoReplace tag list
table_idsarrayNoReplace table assignment (use GET /api/v1/tables/available for options)
restaurant_idintegerMaster key onlyRestaurant ID
Error Responses
  • 404 — Booking not found
  • 409OVERLAP_WARNING when the new time/tables conflict with another booking

Cancel an existing booking. Requires phone match for security. Respects the restaurant's customer edit/cancel cutoff (see editing_cutoff_hours from /bookings/lookup) — cancellations inside that window are rejected with 403.

Request Body (JSON)
FieldTypeRequiredDescription
booking_idintegerYesBooking ID from lookup
phonestringYesMust match booking's customer phone
restaurant_idintegerMaster key onlyRestaurant ID
Response
{ "success": true, "message": "Booking cancelled successfully", "booking_reference": "RB-..." }
Error Codes
  • 403 — Within the cutoff window; customer must speak to the restaurant directly
  • 404 — Booking not found or phone mismatch

Change a booking's status — e.g. SEATED when the host seats the guest, COMPLETED when the bill is closed, NO_SHOW after a grace window.

Request Body (JSON)
FieldTypeRequiredDescription
statusstringYesOne of: PENDING, CONFIRMED, SEATED, COMPLETED, NO_SHOW, CANCELLED
restaurant_idintegerMaster key onlyRestaurant ID
Response
{ "success": true, "booking": { "booking_id": 123, "reference": "RB-...", "status": "SEATED" }, "message": "Status updated to SEATED" }

Same as POST /api/v1/vouchers/redeem, but the redemption is automatically linked to the booking at :id — convenient when the POS already knows which check the voucher applies to.

Request Body (JSON)
FieldTypeRequiredDescription
codestringYesVoucher code
amount_penceintegerYesAmount to redeem, in pence
notestringNoFree-text note
restaurant_idintegerMaster key onlyRestaurant ID

Search customers by name, email or phone. Useful when a POS wants to surface "is this a returning guest?" before opening a tab.

Query Parameters
ParamTypeRequiredDescription
qstringYesSearch term (min 2 chars). Matches name / email / phone.
pageintegerNoPage number (default 1)
per_pageintegerNo1–50 (default 20)
restaurant_idintegerMaster key onlyRestaurant ID
Response
{ "success": true, "customers": [{ "customer_id": 42, "name": "John Smith", "email": "...", "phone": "+44...", "total_bookings": 5, "total_no_shows": 0, "last_visit": "2026-03-12", "is_vip": false, "blocked": false }], "pagination": { ... } }

Full customer record plus recent booking history (last 50 bookings most-recent first). Use this to show "this is their Nth visit" pop-ups in the POS.

Path Parameters
ParamTypeRequiredDescription
idintegerYesCustomer ID
restaurant_idintegerMaster key onlyRestaurant ID (query param)
Response (abridged)
{ "success": true, "customer": { "customer_id": 42, "first_name": "John", "last_name": "Smith", "email": "...", "phone": "+44...", "total_bookings": 5, "total_no_shows": 0, "is_vip": false, "blocked": false }, "bookings": [{ "booking_id": 123, "reference": "RB-...", "date": "2026-03-12", "time": "19:00", "covers": 4, "status": "COMPLETED" }] }

Returns every active table with an is_occupied flag for the requested time window and an is_suggested flag for the best-fit suggestion. Used to power POS floor plans.

Query Parameters
ParamTypeRequiredDescription
coversintegerNoParty size (default 2)
datestringNoYYYY-MM-DD (default today)
timestringNoHH:MM (default now)
restaurant_idintegerMaster key onlyRestaurant ID
Response
{ "success": true, "tables": [{ "table_id": 7, "name": "T5", "zone": "Window", "min_covers": 2, "max_covers": 4, "is_occupied": false, "is_suggested": true, "fits_party": true }], "suggested_ids": [7] }

Look up a voucher by exact code. Returns value, remaining balance, expiry, and a convenience can_redeem flag (active & not expired & positive balance). Always returns 200 with found: false when the code doesn't exist — no 404 — so POS can show a friendly "voucher not found" message.

Query Parameters
ParamTypeRequiredDescription
codestringYesVoucher code (case-insensitive)
restaurant_idintegerMaster key onlyRestaurant ID
Response
{ "success": true, "found": true, "voucher": { "voucher_id": 88, "code": "TF-ABC123", "status": "ACTIVE", "value_pence": 10000, "balance_pence": 6000, "expires_at": "2027-04-05 23:59:59", "is_expired": false, "recipient_name": "Alex", "product_name": "Gift £100", "can_redeem": true } }

Redeem (partially or fully) against a voucher's remaining balance. Standalone — pass booking_reference if you want the redemption linked to a specific booking.

Request Body (JSON)
FieldTypeRequiredDescription
codestringYesVoucher code
amount_penceintegerYesAmount to redeem, in pence. Can't exceed remaining balance.
booking_referencestringNoBooking to link the redemption to (e.g. RB-20260405-A1B2C3)
notestringNoFree-text note attached to the redemption
restaurant_idintegerMaster key onlyRestaurant ID
Response
{ "success": true, "redemption_id": 555, "new_balance_pence": 3000, "fully_redeemed": false, "voucher": { "voucher_id": 88, "code": "TF-ABC123", "balance_pence": 3000, "status": "ACTIVE" }, "message": "Redeemed £30.00" }

Get restaurant info and services for a given date.

Query Parameters
ParamTypeRequiredDescription
datestringNoDate in YYYY-MM-DD (defaults to today)
restaurant_idintegerMaster key onlyRestaurant ID
Response
{ "success": true, "restaurant": { "name": "Viva Brazil", "phone": "0330...", "email": "...", "max_online_covers": 8 }, "date": "2026-04-05", "services": [{ "name": "Lunch", "code": "LUNCH", "start_time": "12:00:00", "end_time": "16:00:00" }, ...] }

Submit a callback request (typically from an AI phone agent). Sends an email to the restaurant and a push notification to staff.

Body Parameters
ParamTypeRequiredDescription
phonestringRecommendedCaller's phone number
first_namestringNoCaller's first name
last_namestringNoCaller's last name
reasonstringNoReason for callback (e.g. "menu enquiry")
notesstringNoAdditional notes from the caller
restaurant_idintegerMaster key onlyRestaurant ID
Response
{ "success": true, "message": "Callback request sent to restaurant" }

Tools & clients

Point any of these at /developers/openapi.json to get an interactive sandbox or generated client SDK:

Support

Questions, missing fields, or want to integrate something we haven't published yet? Email hello@tablefox.co.uk — we actively support POS, EPOS, ticketing and CRM integrations.