| name | api-patterns |
| description | API design mastery. REST, GraphQL, tRPC, and gRPC selection. Request/response design, pagination (cursor/offset), filtering, versioning, rate limiting, error formats (RFC 9457), authentication (JWT/OAuth2/API keys), idempotency, file uploads, webhooks, and OpenAPI documentation. Use when designing APIs, choosing protocols, or implementing API standards. |
| allowed-tools | Read, Write, Edit, Glob, Grep |
| version | 3.1.0 |
| last-updated | "2026-04-07T00:00:00.000Z" |
| applies-to-model | gemini-3-1-pro, claude-3-7-sonnet |
| routing | {"domain":"general","tier":"basic"} |
API Patterns — Design & Protocol Mastery
Hallucination Traps (Read First)
- ❌ JWT in URL query params → ✅
Authorization: Bearer header only. Query params get logged in server access logs.
- ❌ Assuming JWT is encrypted → ✅ JWT is base64-encoded (NOT encrypted). Anyone can decode it. Never put secrets/PII in the payload.
- ❌ Offset pagination on large tables → ✅
OFFSET 100000 scans and discards 100K rows. Use cursor pagination for tables > 10K rows.
- ❌ Verbs in REST URLs (
/api/getUsers) → ✅ Nouns only (GET /api/users). HTTP method IS the verb.
- ❌
POST is idempotent → ✅ POST is NOT idempotent — requires Idempotency-Key header for safe retries.
- ❌ GraphQL has no security risks → ✅ Deeply nested queries are a DoS vector. Set max depth, query cost limits. Disable introspection in production.
Protocol Selection Matrix
| Protocol | Use When |
|---|
| REST | Public APIs, 3rd-party consumers, standard CRUD, HTTP caching |
| GraphQL | Complex nested data, multiple clients, flexible queries, mobile bandwidth sensitivity |
| tRPC | Full-stack TypeScript (Next.js monorepo), shared types, no codegen |
| gRPC | Internal microservices, high-throughput, streaming, binary protocol |
| WebSocket | Bidirectional real-time (chat, gaming, live collaboration) |
| SSE | Server-to-client streaming only (AI token streaming, live feeds) |
REST Design
URL Conventions
✅ GET /api/v1/users list users
✅ GET /api/v1/users/123 get user by ID
✅ POST /api/v1/users create user
✅ PATCH /api/v1/users/123 partial update
✅ DELETE /api/v1/users/123 delete user
✅ GET /api/v1/users/123/posts nested resource
❌ /api/getUsers /api/createUser /api/user (singular) /api/Users (uppercase)
HTTP Status Codes
200 OK → GET / PUT / PATCH success
201 Created → POST success (include Location: /api/v1/users/123 header)
204 No Content → DELETE success
400 Bad Request → Malformed request / missing fields
401 Unauthorized → Missing or invalid authentication
403 Forbidden → Authenticated but not authorized
404 Not Found → Resource does not exist
409 Conflict → Duplicate resource (email already exists)
422 Unprocessable → Valid JSON, semantically invalid data
429 Too Many Req → Rate limit exceeded
500 Internal → Unhandled server error — NEVER expose stack traces
Response Envelope
interface ApiResponse<T> {
data: T;
meta?: Record<string, unknown>;
}
interface ApiError {
error: {
code: string;
message: string;
details?: Array<{ field: string; message: string }>;
requestId?: string;
};
}
Pagination
const posts = await db.post.findMany({
where: { id: { lt: decodeCursor(req.query.cursor).id } },
orderBy: { id: "desc" },
take: limit + 1,
});
const hasMore = posts.length > limit;
if (hasMore) posts.pop();
return { data: posts, meta: { hasMore, nextCursor: encodeCursor(posts.at(-1)) } };
Idempotency
app.post("/api/v1/payments", async (req, res) => {
const key = req.headers["idempotency-key"];
if (!key) return res.status(400).json({ error: "Missing Idempotency-Key" });
const cached = await redis.get(`idempotency:${key}`);
if (cached) return res.status(200).json(JSON.parse(cached));
const result = await processPayment(req.body);
await redis.set(`idempotency:${key}`, JSON.stringify(result), "EX", 86400);
return res.status(201).json(result);
});
Webhooks
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(payload: string, signature: string, secret: string): boolean {
const expected = createHmac("sha256", secret).update(payload).digest("hex");
return timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
app.post("/webhooks", (req, res) => {
if (!verify(JSON.stringify(req.body), req.headers["x-webhook-signature"] as string, WEBHOOK_SECRET)) return res.status(401).send("Invalid signature");
res.status(200).send("OK");
processWebhookAsync(req.body);
});
Versioning
URL path (recommended): /api/v1/users → simplest, most common, cache-friendly
Header: Accept: application/vnd.api.v1+json
Query param: /api/users?version=1 → messy, avoid
Rules:
- Start at v1, never v0
- Breaking changes = new major version (v2)
- Non-breaking additions (new optional fields) do NOT need a version bump
- Deprecate before removing — give consumers 6+ months notice
Rate Limiting
Strategy How When
Token bucket → Burst allowed, refills Most APIs (recommended)
Sliding window → Smooth distribution Strict fairness required
Fixed window → Simple counter per period Basic needs only
Response headers to always include:
X-RateLimit-Limit (max requests in window)
X-RateLimit-Remaining (requests left)
X-RateLimit-Reset (Unix timestamp when limit resets)
Retry-After (seconds to wait on 429)
GraphQL Security
Protect against:
Depth attacks → Set max query depth (typically 7–10)
Cost attacks → Calculate query complexity score, reject > threshold
Batch abuse → Limit batch size / alias count
Introspection → Disable in production (exposes full schema to attackers)
Authentication Selection
| Pattern | Best For |
|---|
| JWT (short-lived access + httpOnly refresh) | Stateless services, microservices |
| Session | Traditional server-rendered apps |
| OAuth 2.0 / OIDC | Third-party login, delegated access |
| API Key | Server-to-server, public API consumers |
| Passkey (WebAuthn) | Modern passwordless (2026+) |
AI coding assistants often fall into specific bad habits when dealing with this domain. These are strictly forbidden:
- Over-engineering: Proposing complex abstractions or distributed systems when a simpler approach suffices.
- Hallucinated Libraries/Methods: Using non-existent methods or packages. Always
// VERIFY or check package.json / requirements.txt.
- Skipping Edge Cases: Writing the "happy path" and ignoring error handling, timeouts, or data validation.
- Context Amnesia: Forgetting the user's constraints and offering generic advice instead of tailored solutions.
- Silent Degradation: Catching and suppressing errors without logging or re-raising.
Slash command: /review or /tribunal-full
Active reviewers: logic-reviewer · security-auditor
❌ Forbidden AI Tropes
- Blind Assumptions: Never make an assumption without documenting it clearly with
// VERIFY: [reason].
- Silent Degradation: Catching and suppressing errors without logging or handling.
- Context Amnesia: Forgetting the user's constraints and offering generic advice instead of tailored solutions.
Review these questions before confirming output:
✅ Did I rely ONLY on real, verified tools and methods?
✅ Is this solution appropriately scoped to the user's constraints?
✅ Did I handle potential failure modes and edge cases?
✅ Have I avoided generic boilerplate that doesn't add value?
🛑 Verification-Before-Completion (VBC) Protocol
CRITICAL: You must follow a strict "evidence-based closeout" state machine.
- ❌ Forbidden: Declaring a task complete because the output "looks correct."
- ✅ Required: You are explicitly forbidden from finalizing any task without providing concrete evidence (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended.
Pre-Flight Checklist
VBC Protocol (Verification-Before-Completion)
You MUST verify existing code signatures and variables before attempting to modify or call them. No hallucination is permitted.
🤖 LLM-Specific Traps
AI coding assistants often fall into specific bad habits when dealing with this domain. These are strictly forbidden:
- Over-engineering: Proposing complex abstractions or distributed systems when a simpler approach suffices.
- Hallucinated Libraries/Methods: Using non-existent methods or packages. Always
// VERIFY or check package.json / requirements.txt.
- Skipping Edge Cases: Writing the "happy path" and ignoring error handling, timeouts, or data validation.
- Context Amnesia: Forgetting the user's constraints and offering generic advice instead of tailored solutions.
- Silent Degradation: Catching and suppressing errors without logging or re-raising.
🏛️ Tribunal Integration (Anti-Hallucination)
Slash command: /review or /tribunal-full
Active reviewers: logic-reviewer · security-auditor
❌ Forbidden AI Tropes
- Blind Assumptions: Never make an assumption without documenting it clearly with
// VERIFY: [reason].
- Silent Degradation: Catching and suppressing errors without logging or handling.
- Context Amnesia: Forgetting the user's constraints and offering generic advice instead of tailored solutions.
✅ Pre-Flight Self-Audit
Review these questions before confirming output:
✅ Did I rely ONLY on real, verified tools and methods?
✅ Is this solution appropriately scoped to the user's constraints?
✅ Did I handle potential failure modes and edge cases?
✅ Have I avoided generic boilerplate that doesn't add value?
🛑 Verification-Before-Completion (VBC) Protocol
CRITICAL: You must follow a strict "evidence-based closeout" state machine.
- ❌ Forbidden: Declaring a task complete because the output "looks correct."
- ✅ Required: You are explicitly forbidden from finalizing any task without providing concrete evidence (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended.