Read a company's live openings, and put a booking on their schedule from their own website. Five endpoints, one key, no SDK.
The owner or an admin makes it on their Gambrel dashboard, under Developer keys. Give it a name that says what it is for — "Website booking form" — and choose what it can do:
| Scope | What it can do |
|---|---|
read | Read the company, its openings, its jobs and its customers. |
write | All of the above, and create bookings. |
The key is shown once, at the moment it is made. It is stored as a hash, so nobody — including the shop and including us — can look it up afterwards. Lose it and you make another one.
Every request carries the key as a bearer token. Nothing goes in a query string — a key in a URL ends up in server logs and browser history.
curl https://getgambrel.com/api/v1/company \
-H "Authorization: Bearer gmb_your_key_here"
Answers are JSON. A refusal carries an error field written in
plain words — it is meant to be read by a person, and can be shown to one.
{ "error": "This key is read-only. Make a key with write access if you need to create bookings." }
600 requests an hour per key. Over that you get 429. The limit is
per key rather than per address, because a website calls from one server and a
per-address limit would be either useless or an outage you caused yourself.
Who the key belongs to — name, phone, time zone, trades, the ZIP codes they drive to, their arrival windows, and the booking URL you can link or embed.
Openings between two dates, YYYY-MM-DD. These are the same
openings the company's own booking page shows, from the same call — if the shop
runs a CRM, they come from the CRM live, so a booked-out afternoon disappears
here the moment it does there.
{
"days": [
{ "date": "2026-09-14", "weekday": "Monday", "display": "Sep 14",
"slots": [ { "id": "w1", "label": "8:00 AM - 11:00 AM",
"start": "08:00", "end": "11:00", "capacity": 2 } ] }
],
"lastBookableDay": "2026-09-28"
}
Puts a real job on the schedule. This is the same code path the company's own booking page uses, so a booking from your form and one made on the page are identical — same confirmation email to the customer, same alert to the office, same job in their CRM if they run one.
curl -X POST https://getgambrel.com/api/v1/bookings \
-H "Authorization: Bearer gmb_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"service": "Water heater",
"description": "No hot water since this morning",
"day": "2026-09-14",
"slot": "w1",
"source": "website",
"contact": {
"name": "Nadine Ellery",
"phone": "9405550142",
"email": "nadine@example.com",
"street": "12 Pine St",
"city": "Springtown",
"state": "TX",
"zip": "76082"
}
}'
Answers with a reference a person can read out on the phone, and the link the customer uses to move or cancel without ringing anybody:
{
"ok": true,
"reference": "GB-4F2A91C0",
"bookingId": "…",
"manageUrl": "https://getgambrel.com/booking/…"
}
| You'll get | When |
|---|---|
400 | No name or phone; a phone that isn't ten digits; no full service address; no five-digit ZIP. |
400 out_of_area | The address is outside the ZIP codes that company drives to. Your form is not a way around their service area — a job they can't reach is a wasted morning for somebody. |
409 | That day is past the end of their booking window, or the same customer already has that exact appointment. A duplicate returns the booking they already have rather than making a second one. |
429 | Too many bookings from one connection in an hour. |
Recent jobs, newest first, up to 200. Each carries its reference, status,
customer, address, arrival window and source — which is how you tell
a website booking from one taken on the phone.
The company's customers, optionally filtered by a search term.
/api/v1 will not change shape under you. The endpoints the Gambrel
screens use are not this API and are not stable — they change whenever a screen
does. Build against /api/v1 and nothing else.
If all you need is for a homeowner to book, the company's own booking page is already built, already mobile, and already handles photos, rescheduling and cancellation. Link to it or embed it in an iframe — it is the one Gambrel page allowed to be framed, for exactly this reason. Reach for the API when you need something that page cannot do.