Authentication Guide
Understand the three supported authentication methods: OAuth2 client credentials for server-to-server integrations, Supabase JWT tokens for dashboard users, and API key + public client ID for public routes.
Environment tip: All examples use
v3.onsched.comfor production. Replace the host withapi-stage.onsched.comwhen calling the staging environment.
When to Use
- Secure server-to-server integrations that call the API directly.
- Configure dashboard-powered apps that rely on Supabase-issued JWTs.
- Enable public-facing booking flows that don't require user authentication.
- Rotate credentials without interrupting production traffic.
Auth Models
| Use Case | Headers Required | How to Obtain |
|---|---|---|
| OAuth2 Clients (recommended for API consumers) | Authorization: Bearer <access_token> | Exchange client_id and client_secret via POST /v3/oauth/token using the client_credentials grant. |
| Dashboard Users | Authorization: Bearer <user JWT> + x-api-key: <company key> | Retrieve from the v3 dashboard. Tokens map to specific users and expire according to Supabase settings. |
| Public Routes | x-api-key: <company key> + x-client-id: <public client id> | Obtain both from the v3 dashboard. Used for /v3/public/* endpoints that don't require user authentication. |
Once verified, verifyToken attaches req.user and (when applicable) req.company. verifyCompany then enforces that the supplied x-api-key belongs to the authenticated company unless the request originated from a machine token (client_credentials).
OAuth2 Client Credentials Flow
- Generate a client ID/secret pair in the dashboard (
POST /v3/clientId, see/api/routes/clientId.js). - Request an access token:
curl -X POST https://v3.onsched.com/v3/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "<client_id>:<client_secret>" \
-d "grant_type=client_credentials&scope=read write"- Use the
access_tokenas a Bearer token for one hour. Tokens embedcompany_id,grant_type=client_credentials, and optional scopes. - Rotate secrets periodically; revoke compromised credentials by deleting them via
DELETE /v3/clientId/:id.
Machine tokens do not require x-api-key or x-client-id headers—verifyToken resolves the company directly.
Dashboard Token Flow
- Authenticate via the v3 dashboard to receive a Supabase JWT.
- Include two headers on every API request:
Authorization: Bearer <JWT>x-api-key: <Company API key>
- The API cross-checks that the JWT user belongs to the company linked to the API key.
Use this flow when you need user-level auditing (for example, when exposing the API directly from your dashboard session). For backend integrations, prefer OAuth2.
Public Routes Flow
- Obtain your company's API key and public client ID from the v3 dashboard.
- Include both headers on every public API request:
x-api-key: <Company API key>x-client-id: <Public client ID>
- These credentials authenticate the company but do not identify a specific user. All public routes are scoped to
/v3/public/*endpoints.
Use this flow for customer-facing booking widgets, public availability displays, and other scenarios where end users don't have dashboard accounts.
Token Refresh
- OAuth2 tokens expire after one hour; request a new one with the same client credentials—no refresh token is issued.
- Dashboard users can call
POST /v3/auth/generateRefreshTokento mint a new refresh token when their session is about to expire.
Error Handling
- 401 Unauthorized: Missing or invalid headers, malformed Basic auth, expired JWT, or invalid public client ID.
- User not associated: Returned when
x-api-keybelongs to a company the current dashboard user is not a member of. - Invalid Client ID: Returned when the
x-client-idheader is missing, invalid, or expired (for public routes). - Scope violations: If you plan to enforce scopes later, read them from
req.scopes(client credentials tokens may include a space-delimitedscopestring).
Always store secrets in a secure vault and avoid embedding them in client-side code. Use short-lived OAuth2 tokens for any automation or integration work. For public routes, ensure your public client ID is properly configured in the dashboard and hasn't expired.
Updated 21 days ago
