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_…"MCP connector
Besmi ships an MCP connector. MCP (Model Context Protocol) is the open standard AI assistants use to call external tools, so an assistant such as Claude or ChatGPT can work directly against a Besmi account: read the schedule, book, reschedule and cancel appointments, look up clients, pull stats, manage discounts, and edit the public page.
This is separate from the REST API above. The REST API is for code you write; the MCP connector is for an AI assistant acting on the owner's behalf. It does not use API keys. Connection is authorized by the business owner through OAuth 2.1, and can be revoked at any time from Settings → Connect.
Endpointhttps://besmi.com/api/mcp
AuthOAuth 2.1 with PKCE. No API key. The owner approves the connection once.
Tools32 tools across schedule, clients, appointments, availability, stats, reviews, discounts, page design, and audiences and campaigns
Scopesread, book, design, manage
Owners add the connector from Settings, then Connect. If a new tool or scope ships after you connect, reconnect once to pick it up.
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.