Error Codes
The API uses standard HTTP status codes and returns a consistent JSON error envelope.
Error Response Format
JSON
1{2 "success": false,3 "error": {4 "code": "VALIDATION_ERROR",5 "message": "Invalid request parameters",6 "details": {7 "field": "difficulty",8 "reason": "must be one of: easy, medium, hard, expert"9 }10 }11}Error Codes Reference
Authentication (401)
| Status | Code | Description | Resolution |
|---|---|---|---|
| 401 | MISSING_API_KEY | No X-API-Key header provided | Include your tenant API key in the X-API-Key header |
| 401 | INVALID_API_KEY | API key is malformed or does not exist | Verify the key in your dashboard |
| 401 | TENANT_AUTH_REQUIRED | Endpoint requires tenant authentication | Add a valid X-API-Key header |
| 401 | MISSING_USER_TOKEN | User-scoped endpoint called without X-User-Token | Authenticate the user and pass the token |
| 401 | INVALID_USER_TOKEN | User token is invalid or expired | Refresh the token via /auth/refresh |
| 401 | TOKEN_EXPIRED | JWT has expired | Refresh using the refresh token |
| 401 | INVALID_CREDENTIALS | Wrong email or password | Verify credentials |
Authorization (403)
| Status | Code | Description | Resolution |
|---|---|---|---|
| 403 | TENANT_SUSPENDED | Tenant account is suspended | Contact support |
| 403 | TENANT_CANCELLED | Tenant subscription cancelled | Reactivate subscription |
| 403 | ADMIN_ONLY | Endpoint requires admin role | Use an admin account |
| 403 | INSUFFICIENT_TIER | Feature requires a higher plan | Upgrade your plan |
| 403 | FEATURE_NOT_AVAILABLE | Feature is disabled for this tenant | Enable the feature in dashboard settings |
Validation (400)
| Status | Code | Description | Resolution |
|---|---|---|---|
| 400 | VALIDATION_ERROR | Request body/params failed validation | Check the details field for specifics |
Not Found (404)
| Status | Code | Description | Resolution |
|---|---|---|---|
| 404 | NOT_FOUND | Requested resource does not exist | Verify the ID or path |
| 404 | PUZZLE_NOT_FOUND | Puzzle with this ID does not exist | Check the puzzle UUID |
| 404 | USER_NOT_FOUND | User not found in this tenant | Register the user first via /auth/register |
Rate Limiting (429)
| Status | Code | Description | Resolution |
|---|---|---|---|
| 429 | TOO_MANY_REQUESTS | Rate limit exceeded | Wait for Retry-After seconds then retry |
Server Errors (5xx)
| Status | Code | Description | Resolution |
|---|---|---|---|
| 500 | INTERNAL_SERVER_ERROR | Unexpected server error | Retry the request; contact support if persistent |
Handling Errors with the SDK
TypeScript
1import {2 ApiError,3 AuthenticationError,4 RateLimitError,5 NotFoundError,6 ValidationError,7 ServerError,8} from '@puzzle-section/sdk';9
10try {11 const { data } = await client.puzzles.getById('nonexistent');12} catch (error) {13 if (error instanceof RateLimitError) {14 await new Promise(r => setTimeout(r, error.retryAfter * 1000));15 } else if (error instanceof NotFoundError) {16 console.log(error.message); // "Puzzle with ID 'nonexistent' not found"17 } else if (error instanceof AuthenticationError) {18 console.error('Check your API key');19 } else if (error instanceof ValidationError) {20 console.error('Validation:', error.details);21 } else if (error instanceof ServerError) {22 console.error('Server error after retries');23 } else if (error instanceof ApiError) {24 console.error(error.code, error.statusCode, error.message);25 }26}