Authentication
API keys, Bearer authentication, capability model, key lifecycle and rate limiting.
Overview#
Every request to the Bokko Public API requires Bearer token authentication. The API key must be sent in the Authorization header.
Authorization: Bearer bk_live_<key>- Each key is tied to a single tenant (provider).
- Keys have an explicit set of capabilities -- they only allow operations they have been granted permissions for.
- The key alone does not grant full access: capabilities and the tenant scope together determine authorization.
Tipp
A Bokko Pro subscription is required to use the Public REST API and manage API keys. For Free or Starter plans, requests will be rejected with a
403 auth.plan_insufficient error.Figyelmeztetés
Never use API keys on the client side (browser, mobile app frontend). Keys are intended for server-to-server communication. Client-side exposure can lead to security breaches.
API Key Types#
Tipp
You can create API keys in the Bokko dashboard under Integrations → API keys. Detailed UI guide: Help: Managing API keys.
| Type | Description | Revocation |
|---|---|---|
| personal | Delegated user permissions. The key acts on behalf of the creating user. | Automatically revoked if the user's access is terminated. |
| integration | Independent permissions. Not tied to a user, works autonomously. | Only through manual revocation or expiration. |
Tipp
We recommend the integration type for automations and integrating separate systems. This way, the key does not depend on the account status of a single user.
Capabilities#
| Capability | Leírás |
|---|---|
availability.read | Search available slots |
booking.create | Create a booking |
booking.read | Read a booking |
booking.cancel | Cancel a booking |
services.read | List services |
staff.read | List staff |
webhook.manage | Manage webhook configuration (get, set, rotate-secret, delete) |
subscription.read | Read subscription state (plan, quota, features) |
Keys have capabilities that define which operations they can perform. Capabilities must be configured when the key is created.
Tenant Scope#
API keys are tied to a single provider (salon). Tenant scope is enforced in the following ways:
Mandatory salonSlug parameter:
POST /availability/search-- query available slots (in request body)POST /bookings-- create a booking (in request body)GET /bookings-- list bookings (in query string)GET /services-- list services (in query string)GET /staff-- list staff members (in query string)GET /webhooks/config,PUT /webhooks/config,DELETE /webhooks/config-- manage webhook configurationPOST /webhooks/config/rotate-secret-- rotate webhook secretGET /webhooks/deliveries-- query delivery logs
Optional (validated based on key + booking resource):
GET /bookings/{bookingId}GET /bookings/{bookingId}/eventsPOST /bookings/{bookingId}/cancelGET /subscription(the key's tenant inherently determines the provider)
If the provided salonSlug does not match the tenant assigned to the key:
HTTP 403
{
"error": {
"code": "auth.scope_mismatch",
"message": "The key is not authorized for this provider."
}
}Figyelmeztetés
The system intentionally returns
403 instead of 404 to prevent tenant ID discovery (tenant enumeration protection).Idempotency#
Write operations support the Idempotency-Key header to protect against duplicate submissions.
| Property | Value |
|---|---|
| Header | Idempotency-Key |
| Format | UUID v4 |
| TTL | 24 hours |
| Fingerprint | tenant scope + operationId + path params + canonical body |
Behavior:
- Same key + matching fingerprint --> the original response is returned (
meta.idempotent: true) - Same key + different fingerprint -->
409 idempotency.payload_mismatch
Rate Limiting#
| Route group | Standard | Elevated | Egység |
|---|---|---|---|
catalog | 120 | 600 | kérés / perc |
availability | 30 | 150 | kérés / perc |
booking | 30 | 150 | kérés / perc |
webhook | 10 | 50 | kérés / perc |
subscription | 60 | 300 | kérés / perc |
- Per-key, per-route-group restriction with a 1-minute rolling window.
- In case of exceeding the limit, the response is:
HTTP 429
Retry-After: 30
{
"error": {
"code": "rate_limit.exceeded",
"message": "Rate limit exceeded.",
"retryable": true,
"details": {
"retryAfterSeconds": 30
}
}
}Key Lifecycle#
| Action | Description |
|---|---|
| Creation | In the Bokko dashboard, under Settings > API keys. |
| Revocation | Immediate invalidation. Requests sent with a revoked key will receive a 401. |
| Expiration | Optional expiresAt field. After expiration, the key is automatically invalid. |
Code Examples#
cURL#
bash
curl -X GET "https://api.bokko.io/v1/services?salonSlug=example-salon" \
-H "Authorization: Bearer bk_live_abc123def456"JavaScript (fetch)#
javascript
const response = await fetch(
'https://api.bokko.io/v1/services?salonSlug=example-salon',
{
headers: {
'Authorization': 'Bearer bk_live_abc123def456',
'Content-Type': 'application/json',
},
}
);
const data = await response.json();Python (requests)#
python
import requests
response = requests.get(
'https://api.bokko.io/v1/services',
params={'salonSlug': 'example-salon'},
headers={
'Authorization': 'Bearer bk_live_abc123def456',
'Content-Type': 'application/json',
},
)
data = response.json()Tipp
The
bk_live_abc123def456 key used in the examples is for illustration only. You can find your own key in the Bokko dashboard under Settings > API keys.