API keys
Every request must include an API key in theX-Api-Key header:
Both work with every storefront endpoint. Admin keys (
sk_) are for admin integrations such as Zapier and aren’t accepted by the storefront API.
Forward the buyer’s IP
When your server calls the API for its visitors, every request comes from your server’s IP. Rate limits and sign-up, login and email protection then can’t tell your visitors apart. With a private key, send each visitor’s IP inX-Opencals-Buyer-Ip, and the API counts per buyer instead:
x-real-ip or the first x-forwarded-for entry on Vercel), never from the request body. With the SDK, use the buyerIp option.
Customer authentication
Endpoints that read or modify a specific customer’s data — their appointments, orders, and profile — additionally require a customer access token as a Bearer token:Sign in
Exchange a customer’s credentials for a token pair:Refresh tokens
Access tokens expire. Get a fresh pair by calling the refresh endpoint with the refresh token as the Bearer token:All auth endpoints
See the API reference for full request and response shapes.
Which endpoints need a customer token?
Customer-scoped endpoints — appointments, orders, and self-service profile management — require a customer Bearer token. Catalog endpoints (products, availability, staff members, locations, collections, store settings) need only the API key.Cart and checkout endpoints accept an optional customer token: guests can book without an account, and checkout can return auth tokens for new customers so they’re signed in automatically after their first booking. Checkout never returns tokens for an existing customer identified only by the email in the request; that customer signs in themselves to see the booking.
Error responses
Errors use conventional HTTP status codes with a JSON body:Security checklist
- Use a private key (
spk_) on your server and keep it in environment variables, never in client bundles or repositories. - Forward the buyer’s IP (
X-Opencals-Buyer-Ip) from your server so each visitor gets their own rate limits. - If your server has fixed outgoing IPs, add them to the private key’s allowed IPs.
- Use a public key (
sfk_) only in browser code, and set its allowed origins to your domains. - Store customer refresh tokens in
httpOnlycookies rather thanlocalStoragewhere possible. - Rotate API keys from the dashboard if a key is ever exposed.