OpenAPI (Swagger) as the contract
OpenAPI 3.x describes paths, operations, schemas, security schemes, and examples. Becomes:
- Documentation (Swagger UI, Redoc)
- Codegen (clients, servers, types)
- Validation (request/response middleware)
- Gateway config (Kong, Apigee import)
Staff practice: contract-first for public APIs — design YAML, review in PR, generate server stubs. Code-first acceptable for fast-moving internal services if CI regenerates spec and breaks on drift.
Key components: components/schemas, responses, reusable parameters, securitySchemes (Bearer, OAuth2, API key).
Error models — RFC 7807 Problem Details
{
"type": "https://api.example.com/errors/insufficient-funds",
"title": "Insufficient funds",
"status": 402,
"detail": "Account 123 balance 4.50, required 10.00",
"instance": "/payments/req-abc",
"balance": 4.50
}type is a stable URI (not necessarily dereferenceable). Extension members allowed. Prefer over ad-hoc { "error": "something went wrong" }.
For validation errors, common pattern: errors[] array with field, code, message alongside Problem Details envelope.
Pagination
Offset/limit
GET /items?offset=100&limit=20 — simple, poor performance on large offsets (DB scans skipped rows). Inconsistent under concurrent inserts/deletes.
Cursor/keyset
GET /items?cursor=eyJpZCI6MTIzfQ&limit=20 — encode last-seen sort key; stable under churn. Required for high-volume feeds (Twitter, Stripe).
Response pattern:
{
"data": [...],
"pagination": {
"next_cursor": "...",
"has_more": true
}
}Link headers
Link: <...?cursor=abc>; rel="next" — RFC 5988; works without JSON envelope.
Filtering, sorting, sparse fieldsets
?filter[status]=active&sort=-created_at?fields[users]=name,email— reduce payload (also GraphQL's core idea)
Document limits: max limit, max filter complexity, timeout for expensive queries.
Rate limiting headers
Common conventions (no single RFC winner):
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-ResetRetry-Afteron 429
Token bucket vs sliding window — implementation in gateway; API contract documents limits per tier/key.
Idempotency-Key header
Stripe/GitHub pattern: Idempotency-Key: <uuid> on POST. Server stores response for key TTL; duplicate requests return cached response. Essential for payment and order APIs with retries.
Content negotiation
Accept: application/json vs application/xml — rare today. More relevant: Accept-Language, compression (Accept-Encoding: gzip, br — handled at HTTP layer per Networking).
Long-running operations
Google pattern: POST returns 202 + Operation resource with done: false; client polls GET /operations/{id} or receives webhook. Alternative: 202 + Location to status URL.
Further Reading
Hands-On Tasks (Optional)
API design drills and whiteboard exercises — protocol selection, contract design, and bulk-transfer architecture. Assumes Networking and sibling tracks on the hub page (Distributed Systems, Databases, Concurrency, LLD).
- Design an error response schema15m
Define Problem Details JSON for: validation error (multiple fields), rate limit, conflict (409), and internal error. Include machine-readable `type` URIs and stable `code` fields.