Integration Guide
Best practices for integrating The Puzzle Section API into production applications. Fetching puzzles, content generation, caching strategies, error handling, and observability.
Architecture Overview
We recommend a server-side integration where your backend communicates with The Puzzle Section API. This keeps your API key secure and allows you to add caching, logging, and custom business logic.
Never expose your API key
Always make API calls from your backend. Client-side API calls expose your key and allow abuse.
Caching Strategy
Puzzles don't change after generation, making them ideal for caching. We recommend caching at multiple levels:
Cache TTLs by Resource Type
| Resource | Recommended TTL | Notes |
|---|---|---|
| Daily puzzle | Until midnight UTC | Changes daily |
| Puzzle by ID | 24 hours+ | Never changes |
| Puzzle types | 1 hour | Rarely changes |
| Leaderboards | 1-5 minutes | Updates frequently |
Example: Redis Caching (Node.js)
TypeScript
1import { Redis } from 'ioredis';2import { PuzzleSectionClient } from '@puzzle-section/sdk';3
4const redis = new Redis();5const client = new PuzzleSectionClient({6 apiKey: process.env.PUZZLE_SECTION_API_KEY!,7});8
9async function getDailyPuzzles(type?: string) {10 const cacheKey = `puzzle:daily:${type ?? 'all'}`;11 12 const cached = await redis.get(cacheKey);13 if (cached) {14 return JSON.parse(cached);15 }16 17 const { data: puzzles } = await client.puzzles.getDaily(18 type ? { types: [type as any] } : undefined19 );20 21 const now = new Date();22 const midnight = new Date(now);23 midnight.setUTCHours(24, 0, 0, 0);24 const ttl = Math.floor((midnight.getTime() - now.getTime()) / 1000);25 26 await redis.setex(cacheKey, ttl, JSON.stringify(puzzles));27 28 return puzzles;29}Error Handling
Implement robust error handling for production reliability:
TypeScript
1import {2 RateLimitError,3 NotFoundError,4 ServerError,5 ApiError,6} from '@puzzle-section/sdk';7
8async function withRetry<T>(9 fn: () => Promise<T>,10 maxRetries = 311): Promise<T> {12 for (let attempt = 1; attempt <= maxRetries; attempt++) {13 try {14 return await fn();15 } catch (error) {16 if (error instanceof RateLimitError) {17 await new Promise(r => setTimeout(r, error.retryAfter * 1000));18 continue;19 }20 21 if (error instanceof NotFoundError) {22 throw error; // Don't retry 404s23 }24 25 if (error instanceof ServerError && attempt < maxRetries) {26 await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000));27 continue;28 }29 30 throw error;31 }32 }33 throw new Error('Max retries exceeded');34}Monitoring & Observability
Track API usage and performance in your application:
- Log request IDs — Every response includes a
requestIdfor debugging - Track response times — Monitor latency to identify issues
- Alert on errors — Set up alerts for elevated error rates
- Monitor activity — Check your dashboard for usage trends