Authentication
The Puzzle Section uses a layered authentication model. Every API request requires a tenant API key. The Auth API lets tenants register and authenticate end-users. Dashboard operations use admin JWTs.
Authentication Model
There are three authentication mechanisms, each serving a different layer:
| Mechanism | Header | Purpose |
|---|---|---|
| Tenant API Key | X-API-Key | Identifies your tenant. Required on all /api/v1 endpoints (except health and docs). |
| User Token | X-User-Token | Identifies an end-user within your tenant. Issued by the Auth API on registration or login. |
| Admin JWT | Authorization: Bearer | Authenticates tenant administrators for dashboard API endpoints. |
Tenant API Keys
API keys are scoped to your tenant and determine your plan capabilities. Pass the key via the X-API-Key header on every request.
Key Formats
ps_live_*ProductionReturns real puzzles. Activity is tracked for analytics.
ps_test_*SandboxReturns sample puzzles for development and testing.
Using API Keys with the SDK
The TypeScript SDK handles the X-API-Key header automatically:
import { PuzzleSectionClient } from '@puzzle-section/sdk';
const client = new PuzzleSectionClient({ apiKey: process.env.PUZZLE_SECTION_API_KEY!,});
// The SDK sends X-API-Key on every requestconst { data } = await client.puzzles.getDaily();Using API Keys with Raw HTTP
curl -X GET "https://api.puzzlesection.app/api/v1/puzzles/daily/2026-03-05" \ -H "X-API-Key: ps_live_xxxxxxxxxxxx"Alternative: Bearer token
Authorization: Bearer ps_live_xxx. However, the X-API-Key header is the canonical method and avoids ambiguity with user/admin JWTs.User Tokens
User tokens are JWTs that identify an end-user within your tenant. They are obtained by registering or logging in a user via the Auth API. Pass the token via the X-User-Token header.
Obtaining a User Token
1// Register or login via the Auth API to obtain a user token2const response = await fetch('https://api.puzzlesection.app/api/v1/auth/register', {3 method: 'POST',4 headers: {5 'Content-Type': 'application/json',6 'X-API-Key': process.env.PUZZLE_SECTION_API_KEY!,7 },8 body: JSON.stringify({9 email: 'user@example.com',10 username: 'puzzlefan42',11 externalUserId: 'your-system-user-id',12 }),13});14
15const { user, userToken, refreshToken } = await response.json();16// userToken is a JWT to pass as X-User-TokenUsing User Tokens
User tokens issued by the Auth API are JWTs that your client application should store securely and pass to any downstream services that need to identify the end-user. The platform API itself does not require user tokens for puzzle content endpoints — those are authenticated solely with the tenant API key.
Refreshing Tokens
User tokens expire. Use the refresh token to obtain a new pair:
1const response = await fetch('https://api.puzzlesection.app/api/v1/auth/refresh', {2 method: 'POST',3 headers: {4 'Content-Type': 'application/json',5 'X-API-Key': process.env.PUZZLE_SECTION_API_KEY!,6 },7 body: JSON.stringify({ refreshToken: storedRefreshToken }),8});9
10const { userToken, refreshToken: newRefreshToken } = await response.json();Security Best Practices
Never expose API keys
- Environment variables — Store keys in
PUZZLE_SECTION_API_KEYor a secrets manager. - Server-side only — API keys must only be used from your backend. User tokens can be passed to the client.
- Rotate regularly — Use the dashboard to rotate keys. Old keys can be revoked without downtime by rotating first.
- Separate environments — Use
ps_test_*keys in development/staging andps_live_*in production. - IP allowlisting — API keys support optional IP allowlists for additional security.
Managing API Keys
API keys are managed via the tenant dashboard:
- Navigate to Dashboard → API Keys
- Select "Create New Key" and choose the environment (live/test)
- Copy the key immediately — it is only displayed once
- Use "Rotate" to generate a new key while keeping the old one active temporarily
- Revoke keys that are no longer needed
Authentication Error Codes
| Status | Code | Description |
|---|---|---|
401 | MISSING_API_KEY | No X-API-Key header provided |
401 | INVALID_API_KEY | API key is malformed, does not exist, or has been revoked |
401 | TENANT_AUTH_REQUIRED | Endpoint requires tenant authentication |
401 | MISSING_USER_TOKEN | User-scoped endpoint called without X-User-Token |
401 | INVALID_USER_TOKEN | User token is invalid or expired |
403 | TENANT_SUSPENDED | Tenant account has been suspended |
403 | INSUFFICIENT_TIER | Feature requires a higher plan tier |