Skip to content

Authentication

Use bearer token for user-scoped internal routes.

Header:

Authorization: Bearer <access_token>

Token lifecycle endpoints:

  • POST /api/v1/auth/login
  • POST /api/v1/auth/refresh
  • POST /api/v1/auth/logout

Use API key header for public audience routes:

X-API-Key: <raw_api_key>

Requirements for API key auth:

  • Route must be tagged as public audience.
  • tenant_id and workspace_id must be resolvable (typically in path).
  • Key must be active, not expired, not revoked.
  • Key scopes must allow the requested permission.

Create keys via JWT-authenticated endpoint:

POST /api/v1/tenants/{tenant_id}/workspaces/{workspace_id}/integrations/api-keys

Key facts:

  • raw_key is returned once at creation.
  • Key scopes are validated against allowed public resources.
  • Default scopes: invoice:read, party:read, product:read, report:read, webhooks:read.
  • Allowed resources: invoice, party, product, report, webhooks.
  • Optional rate_limit_per_minute overrides the subscription tier default.

Each API key is rate-limited based on your subscription tier:

TierRequests/minute
Starter60
Professional300
Enterprise1,000

Exceeding the limit returns 429 Too Many Requests with a Retry-After: 60 header.

You can set a custom per-key limit (via rate_limit_per_minute at creation) to override the tier default.

A request is allowed when either:

  • exact scope exists (e.g., invoice:read), or
  • wildcard for resource exists (e.g., invoice:*).

Otherwise, API returns 403 scope denial.

If X-API-Key is supplied on non-public routes, auth is rejected.

See Public vs Internal Routes.