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 service provider business.
  • 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 key's business scope together determine authorization.
Tip
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.
Warning
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#

Tip
You can create API keys in the Bokko dashboard under Integrations → API keys. In the current dashboard UI, the normal create flow issues integration keys and lets you choose the key kind (owner or guest_partner). 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.
Tip
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.

API Key Kinds#

In addition to the key type, Bokko v1 also uses a key kind to further restrict what an integration key may do.

KindDescriptionCapability Scope
ownerFull owner-side integration key.Can use the full capability set assigned to the key.
guest_partnerExternal booking partner key acting on behalf of guests.Limited to guest-facing booking capabilities only.

For guest_partner keys, the allowed capability set is restricted to:

  • services.read
  • staff.read
  • availability.read
  • booking.create

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
subscription.readRead subscription state

Keys have capabilities that define which operations they can perform. Capabilities must be configured when the key is created.

CapabilityDescriptionAffected Endpoints
services.readList servicesGET /services
staff.readList staff membersGET /staff
availability.readSearch available time slotsPOST /availability/search
booking.createSubmit a new bookingPOST /bookings
booking.readList bookings and detailsGET /bookings, GET /bookings/{bookingId}, GET /bookings/{bookingId}/events
booking.cancelCancel a bookingPOST /bookings/{bookingId}/cancel
webhook.manageManage webhook configurationGET/PUT/DELETE /webhooks/config, GET /webhooks/deliveries
subscription.readQuery subscription planGET /subscription

Business Scope#

API keys are tied to a single service provider business. This business scope is enforced in the following ways:

Mandatory salonSlug and locationSlug parameters:

  • POST /availability/search -- query available slots (in request body)
  • POST /bookings -- create a booking (in request body)
  • GET /services -- list services (in query string)
  • GET /staff -- list staff members (in query string)

Mandatory salonSlug parameter:

  • GET /bookings -- list bookings (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 itself inherently determines the service provider business)

If the provided salonSlug does not match the service provider business assigned to the key, or the locationSlug is not found:

HTTP 403
{
  "error": {
    "code": "auth.scope_mismatch",
    "message": "The key is not authorized for this service provider or location."
  }
}
Warning
The system intentionally returns 403 instead of 404 to prevent business ID discovery through key-scope probing.

Idempotency#

Write operations support the Idempotency-Key header to protect against duplicate submissions.

PropertyValue
HeaderIdempotency-Key
FormatRFC 4122 UUID (v1-v5, v4 recommended)
TTL24 hours
Fingerprintbusiness 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

The Bokko Public API applies a separate limit per route group and API key, with a 1-minute rolling window. There are two limit tiers: standard and elevated.

Route GroupAffected EndpointsStandard (req/min)Elevated (req/min)
catalogGET /services, GET /staff120600
availabilityPOST /availability/search30150
bookingPOST /bookings, GET /bookings, POST /bookings/{bookingId}/cancel30150
webhookGET/PUT/DELETE /webhooks/config, GET /webhooks/deliveries1050
subscriptionGET /subscription60300

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 Integrations → 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-business&locationSlug=downtown" \
  -H "Authorization: Bearer bk_live_abc123def456"

JavaScript (fetch)#

javascript
const response = await fetch(
  'https://api.bokko.io/v1/services?salonSlug=example-business&locationSlug=downtown',
  {
    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-business', 'locationSlug': 'downtown'},
    headers={
        'Authorization': 'Bearer bk_live_abc123def456',
        'Content-Type': 'application/json',
    },
)

data = response.json()
Tip
The bk_live_abc123def456 key used in the examples is for illustration only. You can find your own key in the Bokko dashboard under Integrations → API keys.