Skip to main content

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

ResourceRecommended TTLNotes
Daily puzzleUntil midnight UTCChanges daily
Puzzle by ID24 hours+Never changes
Puzzle types1 hourRarely changes
Leaderboards1-5 minutesUpdates 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] } : undefined
19 );
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 = 3
11): 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 404s
23 }
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 requestId for 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