Docs
Ctrl+K

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.
TypeDescriptionRevocation
personalDelegated user permissions. The key acts on behalf of the creating user.Automatically revoked if the user's access is terminated.
integrationIndependent 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#

CapabilityLeírás
availability.readSearch available slots
booking.createCreate a booking
booking.readRead a booking
booking.cancelCancel a booking
services.readList services
staff.readList staff
webhook.manageManage webhook configuration (get, set, rotate-secret, delete)
subscription.readRead 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 configuration
  • POST /webhooks/config/rotate-secret -- rotate webhook secret
  • GET /webhooks/deliveries -- query delivery logs

Optional (validated based on key + booking resource):

  • GET /bookings/{bookingId}
  • GET /bookings/{bookingId}/events
  • POST /bookings/{bookingId}/cancel
  • GET /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.

PropertyValue
HeaderIdempotency-Key
FormatUUID v4
TTL24 hours
Fingerprinttenant 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 groupStandardElevatedEgység
catalog120600kérés / perc
availability30150kérés / perc
booking30150kérés / perc
webhook1050kérés / perc
subscription60300ké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#

ActionDescription
CreationIn the Bokko dashboard, under Settings > API keys.
RevocationImmediate invalidation. Requests sent with a revoked key will receive a 401.
ExpirationOptional 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.