Skip to main content

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:

MechanismHeaderPurpose
Tenant API KeyX-API-KeyIdentifies your tenant. Required on all /api/v1 endpoints (except health and docs).
User TokenX-User-TokenIdentifies an end-user within your tenant. Issued by the Auth API on registration or login.
Admin JWTAuthorization: BearerAuthenticates 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_*Production

Returns real puzzles. Activity is tracked for analytics.

ps_test_*Sandbox

Returns sample puzzles for development and testing.

Using API Keys with the SDK

The TypeScript SDK handles the X-API-Key header automatically:

TypeScript
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 request
const { data } = await client.puzzles.getDaily();

Using API Keys with Raw HTTP

bash
curl -X GET "https://api.puzzlesection.app/api/v1/puzzles/daily/2026-03-05" \
-H "X-API-Key: ps_live_xxxxxxxxxxxx"

Alternative: Bearer token

The API also accepts the key as 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

TypeScript
1// Register or login via the Auth API to obtain a user token
2const 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-Token

Using 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:

TypeScript
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

API keys grant full tenant-level access. Never include them in client-side code, commit them to version control, or share them publicly.
  • Environment variables — Store keys in PUZZLE_SECTION_API_KEY or 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 and ps_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:

  1. Navigate to Dashboard → API Keys
  2. Select "Create New Key" and choose the environment (live/test)
  3. Copy the key immediately — it is only displayed once
  4. Use "Rotate" to generate a new key while keeping the old one active temporarily
  5. Revoke keys that are no longer needed

Authentication Error Codes

StatusCodeDescription
401MISSING_API_KEYNo X-API-Key header provided
401INVALID_API_KEYAPI key is malformed, does not exist, or has been revoked
401TENANT_AUTH_REQUIREDEndpoint requires tenant authentication
401MISSING_USER_TOKENUser-scoped endpoint called without X-User-Token
401INVALID_USER_TOKENUser token is invalid or expired
403TENANT_SUSPENDEDTenant account has been suspended
403INSUFFICIENT_TIERFeature requires a higher plan tier

Next Steps