SimpleERB Booking API
Check availability, create, change and cancel restaurant bookings from your own website, app or back-office system.
01 Before you start
Getting your credentials
API access is issued per restaurant by the SimpleERB team. Credentials are not self-service — contact SimpleERB support and ask for API access for your restaurant(s). You will be given:
| Item | What it is |
|---|---|
| API Key | Your API username |
| API Secret | Your API password |
| Restaurant ID | The numeric ID of each restaurant you may access |
One set of credentials can be linked to one or more restaurants. Every request that names a restaurantId must name a restaurant linked to your credentials — anything else is rejected with 401 Unauthorized.
Never embed the API Key or Secret in a browser, mobile app, or any client you do not control. If your secret is exposed, ask support to regenerate it — regenerating invalidates the old secret immediately.
02 Authentication
The API uses an OAuth-style resource owner password flow and returns a JWT bearer token.
Step 1 — request a token
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=password&username={API Key}&password={API Secret} curl -X POST https://book.simpleerb.com/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=password&username=YOUR_API_KEY&password=YOUR_API_SECRET"
Success
{
"access_token": "eyJhbGciOiJI...",
"token_type": "Bearer",
"expires_in": 7200,
"userName": "YOUR_API_KEY",
"issued": "...",
"expires": "..."
} Invalid credentials
{
"error": "invalid_grant",
"error_description": "The user name or password is incorrect."
} A failed login is returned with the JSON body above. Decide success by checking whether access_token is present (or whether error is present), rather than relying on the HTTP status code alone.
Step 2 — call the API
Send the token on every request:
Authorization: Bearer {access_token} Token lifetime
Tokens are valid for 2 hours (expires_in = 7200 seconds).
Cache and reuse your token for its lifetime. Do not request a new token per API call — the token endpoint is rate limited, and a token-per-call pattern will lock you out. Keep the token in memory, refresh it when it is within ~5 minutes of expiry, and refresh immediately on a 401.
03 Bookings API
Base path /api/Bookings/v1. All routes require Authorization: Bearer. Request and response bodies are JSON with PascalCase property names.
Common response wrapper
Every Bookings endpoint returns:
| Field | Type | Notes |
|---|---|---|
| IsSuccessFull | boolean | true when the operation succeeded |
| CallResults | string | Human-readable result or error message |
| data | object / boolean / null | The payload — note the lowercase data |
Always check IsSuccessFull before reading data.
Connectivity and credential check. Returns 200 OK with an empty body when your token is valid — a good first integration test and health probe.
curl https://book.simpleerb.com/api/Bookings/v1/CheckStatus \
-H "Authorization: Bearer $TOKEN" Check whether a specific time can be booked, before attempting to create it.
{
"RestaurantId": 4339,
"BookingDateTime": "2026-07-20T19:30:00",
"Covers": 4
} Response
{
"IsSuccessFull": true,
"CallResults": "Timeslot is available for booking",
"data": true
} data is true when the slot can be booked, false when it cannot.
Creates a booking and the customer record behind it.
{
"RestaurantId": 4339,
"BookingDateTime": "2026-07-20T19:30:00",
"Covers": 4,
"Adults": 4,
"Childs": 0,
"Infants": 0,
"CustomerTitle": "Mr",
"CustomerFirstName": "John",
"CustomerLastName": "Smith",
"CustomerEmail": "john@example.com",
"CustomerPhonePrefix": "+44",
"CustomerPhone": "7700900123",
"CustomerPhoneType": "Mobile",
"CustomerSubscribedToNotifications": true,
"OfferId": null,
"SpecialRequests": "Window seat",
"Notes": "Anniversary"
} | Field | Required | Notes |
|---|---|---|
| RestaurantId | yes | Must be a restaurant linked to your credentials |
| BookingDateTime | yes | Restaurant-local time (see §5) |
| Covers | yes | Total number of guests |
| Adults, Childs, Infants | recommended | Should add up to Covers |
| CustomerFirstName, CustomerLastName | yes | Guest name |
| CustomerEmail | yes | Confirmation emails are sent here |
| CustomerPhonePrefix, CustomerPhone | recommended | Dialling code separate from the number |
| CustomerPhoneType | optional | e.g. Mobile |
| CustomerTitle | optional | e.g. Mr, Ms |
| CustomerSubscribedToNotifications | optional | Marketing consent flag |
| OfferId | optional | Set when booking against a published offer |
| SpecialRequests, Notes | optional | Free text shown to the restaurant |
CustomerFirstname / CustomerLastname (lowercase n) are accepted as aliases for backward compatibility.
Behaviour
- Availability is re-validated before saving. If the slot has gone, the response is
IsSuccessFull: falseand no booking is created. - Tables are assigned automatically.
- The booking is rejected if the restaurant has reached its online cover allowance.
- The confirmation email is sent to the customer automatically.
- If the restaurant's rules require a deposit, the deposit workflow takes over the customer email and the response carries a
DepositDueDate.
Success returns the created booking as a RestaurantBookingResponse in data.
Change the date, time or party size of an existing booking.
{
"BookingId": 12345,
"RestaurantId": 4339,
"BookingDateTime": "2026-07-20T20:00:00",
"Covers": 6
} Availability is re-checked, the booking's time and turn time are recalculated, and an updated confirmation email is sent to the customer. Returns the updated booking.
BookingId is the Uid returned by createBooking or by the booking-list endpoints.
{
"BookingId": 12345,
"RestaurantId": 4339,
"CancellationReason": "Customer request"
} Marks the booking cancelled, records the reason against it, and sends the cancellation email to the customer.
04 Restaurant API
Base path /api/Restaurant/v1. All routes require Authorization: Bearer, and parameters are passed on the query string. These endpoints return their payload directly — they are not wrapped in IsSuccessFull / data, except for validation errors, which do use the wrapper.
| Method & route | Purpose |
|---|---|
| GET /CheckStatus | Connectivity check → 200 OK |
| GET /getBasicInfo | Details of every restaurant your credentials can access |
| GET /getAvaialbillityForDate?requestdate=&restaurantId=&covers=2 | Bookable slots for one date |
| GET /getAvailabillityForDateRange?startDate=&endDate=&restaurantId=&covers=2 | Bookable slots across a range |
| GET /getBookingsForDate?requestdate=&restaurantId= | Bookings taking place on a date |
| GET /getBookingsForDateRange?startDate=&endDate=&restaurantId= | Bookings taking place in a range |
| GET /getBookingsAddedForDate?requestdate=&restaurantId= | Bookings created on a date (includes cancelled) |
| GET /getBookingsAddedForDateRange?startDate=&endDate=&restaurantId= | Bookings created in a range (includes cancelled) |
getAvaialbillityForDate and getAvailabillityForDateRange are spelled exactly as shown. The misspellings are intentional and preserved for backward compatibility — copy them literally.
Dates are passed as yyyy-MM-dd (or a full ISO date-time), and covers defaults to 2 if omitted:
?requestdate=2026-07-20&restaurantId=4339&covers=2
Start here: getBasicInfo
Call this first. It returns the restaurants your credentials are linked to, so you can confirm which IDs to use:
curl "https://book.simpleerb.com/api/Restaurant/v1/getBasicInfo" \ -H "Authorization: Bearer $TOKEN"
Each entry contains RestaurantUID (the value to send as restaurantId / RestaurantId), Name, address fields, TelNo1, EmailAddress and WebAddress.
Date range limits
To protect response times, ranges are capped:
| Endpoint group | Maximum span |
|---|---|
| Availability — getAvaialbillityForDate, getAvailabillityForDateRange | 92 days |
| Bookings — getBookingsForDate…, getBookingsAddedForDate… | 366 days |
Dates must fall between 2000-01-01 and 2100-01-01. A request outside these limits returns 400 Bad Request:
{
"IsSuccessFull": false,
"CallResults": "Date range must start on or after 2000-01-01, end on or
before 2100-01-01, and span at most 92 days.",
"data": null
} Split longer periods into several calls.
05 Dates & times
Bookings are stored internally in UTC, but the API speaks restaurant-local time for everything a guest would recognise as a booking time. Audit timestamps stay in UTC.
| Field / parameter | Time zone |
|---|---|
| BookingDateTime, BookingEndDateTime (requests and responses, both APIs) | restaurant-local |
| Availability slot BookingStartDateTime / BookingEndDateTime | restaurant-local |
| requestdate / startDate / endDate on getBookingsForDate / …ForDateRange | restaurant-local |
| requestdate / startDate / endDate on getBookingsAddedForDate / …ForDateRange | UTC |
| DateCreated, DateModified, CancellationDate, DepositDueDate | UTC |
Values carry no offset suffix (2026-07-20T19:30:00), so treat them as wall-clock times in the zone above rather than parsing them as UTC instants. In practice:
- A slot returned by an availability call can be posted straight back to
createBookingunchanged. - A booking returned by
getBookingsForDateshows the same time you booked it for. - Do not apply your own time-zone conversion to booking times.
06 Rate limits
Limits apply per API user — per calling IP for the token endpoint — in a rolling one-minute window:
| Endpoint | Limit |
|---|---|
| POST /token | 10 requests / minute |
| getAvaialbillityForDate, getAvailabillityForDateRange | 60 requests / minute |
| All other /api/Bookings/v1 and /api/Restaurant/v1 routes | 300 requests / minute |
Exceeding a limit returns 429 Too Many Requests with a Retry-After header giving the number of seconds to wait.
Recommendations
- Cache your token for its full 2 hours.
- Cache availability results for short periods rather than re-querying per page view.
- Prefer one range call over many single-date calls.
- On
429, wait for theRetry-Afterinterval and retry — do not retry immediately.
07 Errors
| Status | Meaning | What to do |
|---|---|---|
| 200 OK | Request processed. For the Bookings API, still check IsSuccessFull. | — |
| 400 | Invalid input (bad date range, invalid booking request). CallResults explains why. | Fix the request |
| 401 | Missing, expired or invalid token — or a restaurantId your credentials cannot access. | Refresh the token; verify the ID via getBasicInfo |
| 429 | Rate limit exceeded. | Wait for Retry-After, then retry |
| 500 | Unexpected server error. | Retry once; if it persists, send support the RequestId |
Unexpected server errors return JSON:
{
"IsSuccessFull": false,
"CallResults": "An unexpected error occurred.",
"RequestId": "00-4bf92f3577b34da6a3ce929d0e0e4736-01"
} Quoting RequestId in a support ticket lets us find the exact request in our logs.
08 Response reference
RestaurantBookingResponse
Returned by createBooking, modifyBooking, cancelBooking and the booking-list endpoints.
| Field | Type | Notes |
|---|---|---|
| Uid | int | Booking ID — use as BookingId in later calls |
| RestaurantId | int | |
| BookingDateTime | date-time | Restaurant-local |
| BookingEndDateTime | date-time | Restaurant-local |
| ArrivalTime | date-time / null | Set when the guest is marked as arrived |
| StayTime | int | Turn time in minutes |
| Covers, Adults, Childs, Infants | int | Party breakdown |
| BookingReference | string | Reference shown to the guest |
| BookingStatus | int | See the status table below |
| Customer | object | CustomerId, CustomerTitle, CustomerFirstName, CustomerLastName, CustomerEmail, CustomerPhonePrefix, CustomerPhone, CustomerPhoneType, CustomerSubscribedToNotifications |
| Deposit | object / null | Deposit record when one applies |
| TableReserved | string | Assigned tables, e.g. "T4 T5" |
| Notes | string | |
| IsManagerBooking | bool | true when entered by restaurant staff |
| BookingInformation | array | Notes / history entries against the booking |
| DepositHistory | array | Deposit history entries |
| DateCreated, DateModified | date-time | UTC |
| Deleted, NoShow, Cancelled, UserCancelled | bool | |
| CancellationDate | date-time / null | UTC |
| CancelledBy | string | |
| BookingSource | string | Channel the booking came from |
| DepositDueDate | date-time / null | UTC — set when a deposit is outstanding |
BookingStatus values
| Value | Meaning |
|---|---|
| 1 | Open |
| 2 | Seated |
| 3 | Check dropped |
| 4 | Not yet seated |
| 5 | No show |
| 6 | Table dirty |
Cancelled bookings are flagged by the Cancelled field, not by BookingStatus.
Booking-list response
{
"startDate": "2026-07-20T00:00:00",
"endDate": "2026-07-21T00:00:00",
"RestaurantName": "The Example Kitchen",
"RestaurantId": 4339,
"restaurantBookingResponses": [ { "Uid": 12345, … } ]
} Availability response
{
"startDate": "2026-07-20T00:00:00",
"endDate": "2026-07-20T00:00:00",
"restaurant": { "RestaurantUID": 4339, "Name": "The Example Kitchen", … },
"availableSlots": [
{
"BookingStartDateTime": "2026-07-20T19:30:00",
"BookingEndDateTime": "2026-07-20T21:30:00",
"BookingDuration": 120,
"Covers": 4,
"MaxCovers": 8,
"BookingTables": [
{ "AreaId": 12, "AreaName": "Main Restaurant",
"TableIds": [101, 102], "TableNo": "4" }
]
}
]
} startDate, endDate, restaurant, availableSlots and restaurantBookingResponses are lowercase-initial; all other properties are PascalCase.
09 Typical flow
- POST /tokenObtain and cache a token.
- GET /api/Restaurant/v1/getBasicInfoConfirm your restaurant IDs.
- GET /api/Restaurant/v1/getAvaialbillityForDateShow bookable times to the guest.
- POST /api/Bookings/v1/isAvailableRe-check the chosen slot at the moment of booking.
- POST /api/Bookings/v1/createBookingCreate the booking; store the returned
Uid. - POST /api/Bookings/v1/modifyBooking · cancelBookingHandle later changes.
- GET /api/Restaurant/v1/getBookingsForDateRangeReconcile bookings into your system.
Go-live checklist
- Token cached and refreshed on expiry, never requested per call
429handled withRetry-Afterback-off401triggers a token refresh and one retry- Booking times sent and read as restaurant-local, with no extra conversion
- Date ranges kept within the 92-day / 366-day caps
IsSuccessFullchecked on every Bookings API callRequestIdlogged from any500response- API Secret stored server-side only
10 Support
For credentials, restaurant IDs, quota changes, or help with a failing request, contact SimpleERB support. When reporting a problem please include:
- The endpoint and full request, with the secret redacted
- The UTC timestamp of the request
- The full response body, including
RequestIdif present - Your API Key — never your API Secret