Besmi API · v1
Build on Besmi.
A small, clean API for building custom booking experiences on top of your Besmi business — a marketing site, an internal dashboard, a partner integration, anything. Same auth model, same data, just yours to compose.
Quick start
- i.Generate an API key. Sign in to Besmi, open Settings → Dev, click
New key. Copy the key the moment it appears — Besmi only stores a hash, so it can't be shown again. - ii.Make a request. Pass the key as a Bearer token. Every endpoint is scoped to your business — you never specify
businessId. - iii.Build whatever you want. Custom booking page, mobile app, agency dashboard, scheduled sync — all the same calls.
Your first request
curl https://besmi.com/api/v1/business \
-H "Authorization: Bearer bsk_live_your_key_here"Authentication
Every /api/v1/* endpoint accepts either an API key (recommended for server-to-server) or a Firebase ID token (used by the Besmi first-party UI). Both pass through the same auth pipeline. The businessId is derived from the token — never supplied as a parameter.
Authorization: Bearer bsk_live_…bsk_live_ prefix · 24 random bytes (url-safe base64) · ~40 characters totalread for GET endpoints · write for POST / PATCH / DELETE401 on the next call.Endpoints
Base URL: https://besmi.com
/api/v1/businessRead business profile
Returns name, slug, contact, hours, timezone, theme, landing-page modules, and notification preferences. Stripe / Twilio / partner identifiers are scrubbed.
curl https://besmi.com/api/v1/business \
-H "Authorization: Bearer bsk_live_…"Response · 200
{
"business": {
"id": "biz_xxx",
"name": "Your Esthi Bestie",
"slug": "mlc",
"timezone": "America/Los_Angeles",
"contact": { "email": "...", "phone": "..." },
"schedule": { /* working hours */ },
"theme": { /* colors + fonts */ },
"landingPage": { /* modules */ }
}
}/api/v1/servicesList services & categories
Returns all services and their categories, in display order. Use this to populate a custom service picker.
curl https://besmi.com/api/v1/services \
-H "Authorization: Bearer bsk_live_…"Response · 200
{
"categories": [
{ "id": "cat_xxx", "name": "Lashes", "order": 0, "color": "#C026D3", "services": [] }
],
"services": [
{
"id": "svc_xxx",
"categoryId": "cat_xxx",
"name": "Classic Full Set",
"price": 18000,
"durationMinutes": 120,
"bufferMinutes": 15,
"bookableOnline": true,
"addons": []
}
]
}/api/v1/availabilityGet available slots
Returns bookable time slots for a given date and service duration. Accounts for working hours, blocked windows, buffers, and existing appointments.
Query parameters
datestring | YYYY-MM-DD in the business's timezone |
durationMinutesnumber | Service duration. Default 60. Range 0–480. |
curl "https://besmi.com/api/v1/availability?date=2026-05-15&durationMinutes=120" \
-H "Authorization: Bearer bsk_live_…"Response · 200
{
"slots": [
{ "start": "2026-05-15T17:00:00.000Z", "end": "2026-05-15T19:00:00.000Z" },
{ "start": "2026-05-15T19:30:00.000Z", "end": "2026-05-15T21:30:00.000Z" }
]
}/api/v1/appointmentsList appointments
Lists appointments for the authenticated business, optionally filtered by date range and status. Cursored pagination via from / nextCursor.
Query parameters
fromstring | ISO 8601 — inclusive lower bound on startAt |
tostring | ISO 8601 — exclusive upper bound on startAt |
statusstring | Comma-separated subset of pending,confirmed,cancelled,noshow |
limitnumber | Default 50, max 200 |
curl "https://besmi.com/api/v1/appointments?from=2026-05-01&to=2026-06-01&status=confirmed,pending" \
-H "Authorization: Bearer bsk_live_…"/api/v1/appointmentsCreate an appointment
Books a new appointment on behalf of the authenticated business. Requires the write scope. Payment isn't handled here — use Besmi's built-in payment flow or your own Stripe Connect integration.
Request body
{
"serviceId": "svc_xxx",
"startAt": "2026-05-15T17:00:00.000Z",
"endAt": "2026-05-15T19:00:00.000Z",
"client": {
"firstName": "Jordan",
"lastName": "Lee",
"email": "jordan@example.com",
"phone": "+15555550100"
},
"addonIds": ["addon_xxx"],
"status": "confirmed",
"note": "Allergic to acrylic"
}curl -X POST https://besmi.com/api/v1/appointments \
-H "Authorization: Bearer bsk_live_…" \
-H "Content-Type: application/json" \
-d '{
"serviceId": "svc_xxx",
"startAt": "2026-05-15T17:00:00.000Z",
"endAt": "2026-05-15T19:00:00.000Z",
"client": { "firstName": "Jordan", "email": "jordan@example.com", "phone": "+15555550100" }
}'/api/v1/appointments/{id}Read one appointment
Fetches a single appointment by id.
curl https://besmi.com/api/v1/appointments/apt_xxx \
-H "Authorization: Bearer bsk_live_…"/api/v1/appointments/{id}Update an appointment
Patch status, time, addons, owner note, or client contact. Payment fields are intentionally NOT patchable — use the dedicated Stripe surfaces so Stripe stays the source of truth.
Request body (any subset)
{
"status": "cancelled",
"startAt": "2026-05-16T17:00:00.000Z",
"endAt": "2026-05-16T19:00:00.000Z",
"addonIds": ["addon_xxx"],
"note": "Client called to reschedule",
"client": { "phone": "+15555550101" }
}curl -X PATCH https://besmi.com/api/v1/appointments/apt_xxx \
-H "Authorization: Bearer bsk_live_…" \
-H "Content-Type: application/json" \
-d '{ "status": "cancelled" }'/api/v1/customersList customers
Returns customer records, optionally filtered by a name / email / phone substring.
Query parameters
qstring | Case-insensitive substring filter |
limitnumber | Default 100, max 500 |
curl "https://besmi.com/api/v1/customers?q=jordan&limit=20" \
-H "Authorization: Bearer bsk_live_…"Errors
Standard HTTP status codes. The response body is always JSON with an error field on failures.
400Bad Request — malformed body, invalid date, missing required field
401Unauthorized — missing, invalid, or revoked key
403Forbidden — key lacks the required scope
404Not Found — resource doesn't exist or belongs to another business
500Internal — something went wrong on our side. Safe to retry.
WebhooksComing soon
Subscribe to appointment.created, appointment.updated, and customer.created events. HMAC-SHA256 signed (Stripe-style). Email developers@besmi.com if you need this on a timeline.
Help
Question, bug report, or integration request? Email developers@besmi.com. Common questions live in the FAQ; this page is the source of truth for endpoint shapes.