Developers
Schedulr API
Check availability and create bookings from your own website or app.
Introduction
The Schedulr API powers the booking widget and is open for you to build your own booking flow. It is organised around REST, accepts and returns JSON, and uses standard HTTP status codes.
Every request is scoped to one business through its slug, the last part of its widget URL: /widget/my-salon.
💡 Note
Endpoints are rate-limited per IP and business. See Rate limits. Need help? Email support@schedulr.com.https://schedulr.haomaytech.com
Authentication
These endpoints are public. No API key is needed, so they are safe to call from a browser. The only requirement is that the business has an active Schedulr subscription; otherwise bookings return 403.
Rate limits
Limits apply per IP address and business. Going over returns 429 Too Many Requests.
GET /api/availability/{slug}60 / minutePOST /api/book/{slug}20 / minuteGet availability
Returns the open time slots for a service on a date, along with the service details and any deposit requirement.
Headers
Acceptstring- Set to
application/json
Query parameters
datestring required- Date to check, as
YYYY-MM-DD. Today or later. service_idinteger required- ID of a service that belongs to the business.
Response
slotsstring[]- Available start times,
HH:MM. Pass one astimewhen booking. serviceobject- The service:
id,name,duration(minutes),price,pricing_type,rate_per_hour. depositobject | nullnullwhen no deposit is required, otherwiserequired,amountandtype.
curl -G "https://schedulr.haomaytech.com/api/availability/my-salon" \
-H "Accept: application/json" \
-d date=2026-11-05 \
-d service_id=3
const res = await fetch(
"https://schedulr.haomaytech.com/api/availability/my-salon?date=2026-11-05&service_id=3",
{ headers: { Accept: "application/json" } }
);
const data = await res.json();
$res = Http::acceptJson()->get(
'https://schedulr.haomaytech.com/api/availability/my-salon',
['date' => '2026-11-05', 'service_id' => 3]
);
$data = $res->json();
import requests
res = requests.get(
"https://schedulr.haomaytech.com/api/availability/my-salon",
params={"date": "2026-11-05", "service_id": 3},
headers={"Accept": "application/json"},
)
data = res.json()
{
"slots": ["09:00", "09:30", "10:00"],
"service": {
"id": 3,
"name": "Haircut",
"duration": 30,
"price": "50.00",
"pricing_type": "fixed",
"rate_per_hour": null
},
"deposit": {
"required": true,
"amount": 10,
"type": "percentage"
}
}
Create a booking
Books an appointment and sends the client an SMS confirmation. Overlapping bookings are rejected based on the service duration.
Headers
Content-Typestring- Set to
application/json Acceptstring- Set to
application/json
Body parameters
service_idinteger required- The service being booked.
datestring required- Appointment date, YYYY-MM-DD. Today or later.
timestring required- A slot returned by the availability endpoint.
namestring required- Client full name. Max 255 characters.
phonestring required- Client phone number, used for SMS. Max 20 characters.
emailstring optional- Client email address.
Deposits
If the business requires a deposit, the booking is created as pending and the response contains requires_deposit: true, the deposit_amount and a Paystack payment_url. Redirect the client there to pay.
curl -X POST "https://schedulr.haomaytech.com/api/book/my-salon" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"service_id": 3,
"date": "2026-11-05",
"time": "09:30",
"name": "Ama Mensah",
"phone": "0241234567",
"email": "ama@example.com"
}'
const res = await fetch("https://schedulr.haomaytech.com/api/book/my-salon", {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({
service_id: 3,
date: "2026-11-05",
time: "09:30",
name: "Ama Mensah",
phone: "0241234567",
email: "ama@example.com",
}),
});
const data = await res.json();
$res = Http::acceptJson()->post('https://schedulr.haomaytech.com/api/book/my-salon', [
'service_id' => 3,
'date' => '2026-11-05',
'time' => '09:30',
'name' => 'Ama Mensah',
'phone' => '0241234567',
'email' => 'ama@example.com',
]);
$data = $res->json();
import requests
res = requests.post(
"https://schedulr.haomaytech.com/api/book/my-salon",
headers={"Accept": "application/json"},
json={
"service_id": 3,
"date": "2026-11-05",
"time": "09:30",
"name": "Ama Mensah",
"phone": "0241234567",
"email": "ama@example.com",
},
)
data = res.json()
{
"message": "Appointment booked successfully!",
"requires_deposit": false,
"appointment": {
"id": 42,
"date": "2026-11-05",
"time": "09:30",
"service": "Haircut"
}
}
{
"message": "Deposit payment required.",
"requires_deposit": true,
"deposit_amount": 10,
"payment_url": "https://checkout.paystack.com/...",
"appointment": { "id": 42, "date": "2026-11-05", "time": "09:30", "service": "Haircut" }
}
Errors
Schedulr uses conventional HTTP status codes. Codes in the 4xx range indicate a problem with the request.
The business's subscription is inactive; bookings are unavailable.
Unknown business slug.
The slot overlaps another booking. The message may suggest the next free time.
Validation failed, or the service does not belong to the business.
Rate limit exceeded. Retry after a minute.
{
"error": "This time slot is unavailable as it overlaps with another booking. The next available time for this service is 10:00."
}
Validation errors (422) use Laravel's standard message + errors object, keyed by field.
Embeddable widget
Don't need a custom UI? Embed the ready-made booking widget on any page. It uses your branding, services and business hours.
<iframe src="https://schedulr.haomaytech.com/widget/my-salon" width="100%" height="600" frameborder="0"></iframe>
Building something with Schedulr?
Tell us what you need.