Introduction
How the API is structured, how authentication works, and how multi-tenant requests are scoped
3 min readThe API is a multi-tenant REST service. Every endpoint speaks JSON, returns the same response envelope, and uses the same error contract. Tenant-scoped resources live under an organization id carried in the URL path. This page is the mental model you need before calling any endpoint.
Base URL
All examples in these docs use the following base URL. Replace it with your deployment host.
https://api.example.comHTTPS only: All requests must use HTTPS. The API sends HSTS with a one-year max-age and rejects mixed-content flows.
Authentication Methods
The API accepts three authentication methods. Pick based on who is calling.
Session cookie — browser / first-party app
Users sign in through one of the auth endpoints (email + password, magic link, passkey, social, or SSO). A successful sign-in sets an HTTP-only session cookie. Browsers send it automatically when you make requests with credentials: 'include'; a server acting on behalf of a signed-in user must echo the cookie back on each call.
Use this method for browser apps and any server-rendered UI calling the API on behalf of a signed-in user.
Personal Access Token — scripts, CI, integrations
A Personal Access Token (PAT) is a long-lived credential created while signed in (see Quick Start). Send it on every request as:
X-Api-Key: ba_AbCdEf0123456789...PATs carry an explicit scope list (a subset of the user's permissions) and can optionally be pinned to a single organization.
OAuth 2.1 access token — third-party apps
Third-party applications use the OAuth 2.1 Authorization Code flow against the built-in OIDC provider and call the API with the resulting access token:
Authorization: Bearer eyJhbGciOi...Use this method when your app acts on behalf of users who are not your own — i.e. a public OAuth integration. There is no password grant.
Organization Context
Most endpoints are tenant-scoped. The authenticated principal may belong to several organizations, so tenant routes carry the active organization id directly in the URL path:
/api/user/organizations/{organizationId}/projects- Account routes (
/api/user/me,/api/user/oauth-clients, ...) are not tenant-scoped. - Tenant routes (
/api/user/organizations/{organizationId}/...) require a valid organization id in the URL. Requests without it fail withTENANT_CONTEXT_MISSING. - Public routes (
/api/public/*) and auth routes (/api/auth/*) are not tenant-scoped. - An organization-pinned PAT rejects requests whose
:organizationIdURL segment does not match the pin.
See API Structure for the full request/response contract.
Route Tiers
Every route belongs to exactly one tier. The tier determines which auth it demands.
| Tier | Mount | Auth | Purpose |
|---|---|---|---|
| Public | /api/public/* | none | Sign-up forms, widgets, health, anonymous tracking |
| Auth | /api/auth/* | per endpoint | Sign-in, sign-up, MFA, passkeys, OAuth, SSO |
| User Account | /api/user/* | session, PAT, or OAuth token | /me, /oauth-clients, ... |
| User Tenant | /api/user/organizations/:organizationId/* | session, PAT, or OAuth token + org membership | Projects, payments, members, settings |
| Webhook | /api/webhook/* | provider-signed (inbound only) | Inbound provider callbacks — never called by you |
Request Envelope
Every JSON response uses the same shape:
{
"success": true,
"status": 200,
"code": "OK",
"message": "User fetched successfully",
"data": { "...": "..." },
"meta": { "...": "..." }
}success— boolean, mirrorsstatus < 400.status— HTTP status code as a number.code— machine-readable code (OKon success,VALIDATION_ERROR,NOT_FOUND,RATE_LIMIT_ERROR, ... on failure).message— human-readable summary.data— the resource or resource list on success.meta— pagination, validation error details, or other structured metadata.
See API Structure for pagination and query conventions and Error Handling for the full error code list.
Best Practices
- Pick the right credential: Sessions for first-party UIs, PATs for headless automation, OAuth Bearer tokens for third-party apps acting on behalf of other users' accounts.
- Put the organization id in the URL path: Every tenant-scoped route nests under
/api/user/organizations/{organizationId}/.... The API never guesses from a default. - Store credentials as secrets: Treat PATs and OAuth client secrets like passwords. Use environment variables or a secret manager — never commit them.
- Request the minimum scopes: PATs and OAuth clients take an explicit scope list. Ask only for what you actually need.
- Check
code, not just HTTP status: Thecodefield is stable; HTTP status classes can shift as the API evolves. - Handle 401 and 403 differently:
401means re-authenticate (session expired / token invalid);403means your credential cannot access this resource no matter how you retry.
Next Steps
- Make your first call: Follow Quick Start to sign in and issue a PAT.
- Learn the envelope: Read API Structure for pagination, headers, and request conventions.
- Handle failures: Review Error Handling before you ship.
- Budget your calls: Check Rate Limits to understand request budgets.
- Lock down scopes: See Scopes & Permissions before creating production keys.
Related Pages
Quick Start
Sign in, issue a Personal Access Token, and make your first authenticated call
API Structure
Request headers, response envelope, pagination, and the query conventions shared by every endpoint
Error Handling
Error envelope, full code list, and the retry strategies that actually work
Rate Limits
Per-IP and per-endpoint request limits, the headers that expose them, and how to retry safely