Authentication

API keys for server-to-server integrations, one-hour test keys for trying things out, customer tokens, and OAuth for AI assistants.

Plek has separate identities for staff and customers, and a credential for one never works on the other's routes.

Credential Looks like Works on Gets it
API key plek_live_… Staff API of its own organisation An Admin, under Settings > API & webhooks
Test key plek_live_… Staff API, for one hour Any staff member, from this portal
Staff access token a JWT Staff API The admin app, after sign-in (not for integrations)
Customer token a JWT Customer API of one organisation The customer, through the sign-in routes
OAuth access token a JWT The MCP server at https://api.plekbooking.com/mcp Claude, ChatGPT & co., after the staff member agrees

API keys

An API key belongs to one organisation and has the permissions of the role it was given. Send it on every request, in either header:

X-Api-Key: plek_live_3f9a…
Authorization: Bearer plek_live_3f9a…
  • Create a role for the integration with only what it needs (for example booking:read and customer:read) rather than giving it Admin. You can only give a key permissions you hold yourself.
  • The key is shown once. Plek stores a SHA-256 hash and shows when it was last used. Revoke it in the same place; it stops working at once.
  • A key only works on /api/org/{organisation_id}/… of its own organisation. It cannot sign in, reach another organisation, or manage API keys and webhooks.
  • What a key does is recorded as done by "API key " in the audit log.

Every staff operation in the reference names the permission it needs, for example booking:read. A permission has a scope: all, or assigned (only what is linked to a staff member, such as the sessions a coach teaches). An API key is not a staff member, so give its role all scopes; a test key's assigned scopes are yours. Without the permission the API answers 403.

Test keys

The "Get a test key" button on this portal sends you to the admin app (https://app.plekbooking.com/developer/test-key). After the normal sign-in, with two-step verification if you use it, you pick:

  • the organisation, if you belong to several;
  • read only (the default) or read and change. Read only keeps just the read permissions of your role; read and change has all of them. A role that can only read gets a read-only key.

The key acts for you: it never does more than your own role and locations allow, and a role change applies at once. It expires after one hour, shows under Settings > API & webhooks with its expiry, and can be revoked there. You can have three unexpired test keys at a time, and request ten an hour. Creating one is recorded in the audit log.

The admin app hands the key to this portal in the URL fragment (#key=…), which never reaches a server. The portal keeps it in this tab's sessionStorage only, removes it from the address bar, and forgets it when it expires or when you click "Forget key". Test keys have lower rate limits than normal keys.

Test keys reach real data. A read-and-change key really cancels a session if you ask it to.

Customer tokens

Customers are accounts of one organisation; the same person at two organisations has two accounts. They sign in passwordless (a code or link by email), with Google or Microsoft, or with a password, through the routes under /api/public/{org_slug}/auth. The token they get goes in Authorization: Bearer … on the Customer API. An unverified customer (who booked but never confirmed their email) can book and pay, but cannot see stored participants, booking history or passes.

OAuth and the MCP server

AI assistants connect to the MCP server through OAuth 2.1: Plek is its own authorization server (discovery at https://api.plekbooking.com/.well-known/oauth-authorization-server, PKCE required, dynamic client registration and client ID metadata documents). The staff member signs in and agrees to plek.read and optionally plek.write; the app then acts with the member's role narrowed to those scopes. The MCP server also takes an API key as a bearer token.

CORS

Browsers may call the API from the admin app, the booking sites, an organisation's own domain and the websites it allowed (Settings > Website & widgets), and from this portal (without cookies). Integrations with an API key run on a server: never put an API key in a web page.