Driving-School Bookings
The Bookings API powers an online booking experience on your own website: customers find an instructor who services their suburb, pick a lesson or package, choose an available time, and book — with optional online payment. All data comes from your Laabam One account (service locations, instructors, availability, products).
- Base path:
https://api.laabam.one/v1/schools/{company}(also reachable athttps://laabam.app/api/v1/schools/{company}). {company}is your company slug.- For an instant embeddable UI on top of these endpoints, see the Booking Widget guide.
Authentication
These endpoints accept either key type:
| Key | Header(s) | Use |
|---|---|---|
Secret (lk_id_… + secret) | X-Client-Id + X-Client-Secret | Server-to-server (your backend). Full access. |
Publishable (pk_…) | X-Client-Id only | In-browser / widget. No secret. Origin-locked. |
Create keys in Settings → API Keys. A publishable key sends no secret, so it is safe to
put in page source — but it only works from the origins you allow-list on the key (the
browser's Origin/Referer must match). See Authentication and
Security.
# Server-to-server (secret key)
curl https://api.laabam.one/v1/schools/darshan-driving/locations \
-H "X-Client-Id: lk_id_xxx" -H "X-Client-Secret: lk_secret_xxx"
# Browser (publishable key) — Origin must be allow-listed on the key
curl https://api.laabam.one/v1/schools/darshan-driving/instructors?postcode=3029 \
-H "X-Client-Id: pk_xxx" -H "Origin: https://yourschool.com"
The booking flow
- Locations — list your pickup points / test centres (optional).
- Instructors — find instructors who service the customer's suburb/postcode.
- Courses — list lessons & packages with prices.
- Availability — get bookable time slots for an instructor on a date.
- Create booking — match/create the customer and create the booking; optionally start payment.
- Status — read the booking back (e.g. after returning from payment).
List service locations
GET /schools/{company}/locations
{
"success": true,
"locations": [
{ "id": 3, "name": "VicRoads Bundoora", "type": "test_center",
"city": "Bundoora", "state": "VIC", "postcode": "3083",
"latitude": -37.70, "longitude": 145.06, "operating_hours": null }
]
}
Find instructors
GET /schools/{company}/instructors
Filter by one of (most specific first):
| Query | Match |
|---|---|
lat + lng | Instructors whose service area centre is within its radius_km of the point (distance match). |
postcode | Instructors who service that postcode. |
suburb | Instructors who service that suburb. |
location_id | Instructors mapped to that service location. |
| (none) | All bookable instructors. |
curl "https://api.laabam.one/v1/schools/darshan-driving/instructors?postcode=3029" \
-H "X-Client-Id: pk_xxx" -H "Origin: https://yourschool.com"
{
"success": true,
"instructors": [
{ "id": 189, "name": "Hafeez Mohammed Abdul", "gender": null,
"languages": ["English"], "transmission": "both",
"bio": "5+ years experience.", "photo_url": null,
"service_areas": [ { "suburb": "Tarneit", "postcode": "3029", "state": "VIC", "radius_km": 20 } ] }
]
}
transmission is auto, manual, or both.
List courses (lessons & packages)
GET /schools/{company}/courses — optional ?transmission=auto|manual and ?type=lesson|package.
{
"success": true,
"courses": [
{ "id": 6356, "name": "AUTO - 2 HOUR LESSON", "price": 120, "currency": "AUD",
"duration_minutes": 120, "transmission": "auto", "is_package": false,
"product_type": "service" }
]
}
Get availability
GET /schools/{company}/availability?instructor_id={id}&date=YYYY-MM-DD[&duration_minutes=]
Returns bookable start/end slots, honouring the instructor's weekly schedule, date overrides, existing bookings, and your booking settings (slot length, buffer, min-notice, advance window).
{ "success": true, "available": true, "reason": null,
"slots": [ { "start": "09:00", "end": "11:00" }, { "start": "11:15", "end": "13:15" } ] }
When unavailable: { "available": false, "reason": "No availability set for this day", "slots": [] }.
Create a booking
POST /schools/{company}/bookings
{
"customer": { "name": "Jane Doe", "email": "jane@example.com", "phone": "0400000000",
"postcode": "3029", "city": "Tarneit" },
"instructor_id": 189,
"product_id": 6356,
"service_location_id": 3,
"booking_date": "2026-07-01",
"start_time": "10:00",
"end_time": "12:00",
"pickup_address": "1 Example St, Tarneit",
"student_notes": "First lesson",
"booking_package_id": null,
"return_url": "https://yourschool.com/booking/success",
"cancel_url": "https://yourschool.com/booking/cancel"
}
end_timeis optional — if omitted, it's derived fromduration_minutes, the product's duration, or your default slot length.booking_package_id(optional) books against a customer's pre-paid package (a session is decremented and the booking is confirmed without payment).return_url+cancel_url(optional) — when supplied and payment is due, payment is initiated immediately (see below).
Response (201):
{
"success": true,
"booking": { "id": 12, "booking_number": "BK-000012", "status": "pending",
"payment_status": "unpaid", "total_amount": 120, "currency": "AUD",
"booking_date": "2026-07-01", "start_time": "10:00", "end_time": "12:00" },
"payment": { "required": true, "amount": 120, "currency": "AUD",
"gateway": "stripe", "payment_url": "https://checkout.stripe.com/...",
"status": "unpaid" }
}
Pricing is always taken from your catalogue server-side (the client can't set the price).
Pay for a booking
POST /schools/{company}/bookings/{id}/pay — start (or retry) payment for a pending booking.
{ "return_url": "https://yourschool.com/booking/success",
"cancel_url": "https://yourschool.com/booking/cancel" }
Returns payment.payment_url (Stripe/PayPal) or payment.payment_data (Razorpay client
fields). Redirect the customer there. The booking is automatically confirmed and marked
paid by the gateway webhook once payment completes.
Online payment requires an active payment gateway for AUD in Settings → Payment
Gateways, and the gateway's webhook pointed at
https://laabam.app/api/v1/storefront/{company}/webhook/{stripe|razorpay|paypal}. If no
gateway is configured, the booking is still created as pending and the response carries
payment.online_payment_enabled: false — fall back to "we'll contact you to arrange payment".
Get booking status
GET /schools/{company}/bookings/{id}
{ "success": true,
"booking": { "id": 12, "booking_number": "BK-000012", "status": "confirmed",
"payment_status": "paid", "total_amount": 120, "currency": "AUD",
"instructor": { "id": 189, "name": "Hafeez Mohammed Abdul" } } }
Errors
| Status | Meaning |
|---|---|
401 | Missing/invalid key (or missing secret for a secret key). |
403 | Origin not allowed (publishable key from a non-allow-listed site). |
404 | Company or booking not found. |
409 | The chosen slot conflicts with an existing booking. |
422 | Validation failed, or online payment not enabled. |
429 | Rate limit exceeded. |
See the full API Reference for schemas, and the Booking Widget for a drop-in UI.