Token Authentication
Last updated: Phase 8.5
Overview
Bearer tokens authenticate requests to the Tenant API, Admin API, and Billing Portal. Tokens are issued via the login endpoint and carry ability scopes.
Obtaining a Token
Endpoint: POST /api/auth/login
json
{
"email": "admin@example.com",
"password": "your-password"
}Response (200):
json
{
"data": {
"token": "1|abc123def456...",
"admin": {
"id": 1,
"name": "Ian Holt",
"email": "admin@example.com",
"created_at": "2026-03-30T00:00:00.000000Z",
"updated_at": "2026-03-30T00:00:00.000000Z"
}
},
"meta": {
"api_version": "1",
"request_id": "uuid"
}
}Using a Token
Include the token in the Authorization header:
GET /api/v1/admin/tenants
Authorization: Bearer 1|abc123def456...
Content-Type: application/jsonToken Abilities
| Ability | Issued to | Grants access to |
|---|---|---|
admin | Admin users | /api/v1/admin/*, /api/auth/logout, /api/auth/me |
tenant | Tenant users | /api/v1/tenant/*, /api/v1/billing/* |
Admin tokens cannot access tenant routes. Tenant tokens cannot access admin routes.
Multi-Tenant Header
If your user belongs to multiple tenants, include the X-Tenant-ID header:
GET /api/v1/tenant/products
Authorization: Bearer {token}
X-Tenant-ID: tenant-uuid-hereIf your user belongs to only one tenant, this header is optional — the tenant is auto-selected.
Logging Out
Endpoint: POST /api/auth/logoutAuth: Bearer token
Revokes the current token. Returns 204 No Content.
Token Lifecycle
- Tokens do not expire by default (Sanctum default behavior)
- Tokens are revoked on logout
- A 401 response indicates the token is invalid or revoked
- Rate limiting on login: 5 attempts per 60 seconds
Error Codes
| Code | HTTP | Description |
|---|---|---|
AUTH.INVALID_CREDENTIALS | 401 | Wrong email or password |
AUTH.UNAUTHENTICATED | 401 | Missing or invalid token |
AUTH.INSUFFICIENT_PERMISSIONS | 403 | Token lacks required ability |
AUTH.TOKEN.REQUIRED | 401 | No authentication provided |
AUTH.TOKEN.INVALID_SCOPE | 403 | Token missing required scope (e.g., tenant) |