What are the best practices for API design?
Good API design is a contract between producers and consumers. A poorly designed API is expensive to change once clients depend on it. The following practices, applied consistently, produce APIs that are predictable, evolvable, and safe to build on.
**Resource-oriented URLs**: Use nouns, not verbs. `/orders` and `/orders/42` are correct; `/getOrder` is not. Nest resources only one level deep to avoid URL fragility—prefer `/orders/42/items` over `/users/1/orders/42/items`.
**Correct HTTP semantics**: Map CRUD to HTTP methods precisely (POST/GET/PUT/PATCH/DELETE). Return semantically correct status codes (201 for create, 204 for delete, 422 for validation errors, 409 for conflicts). Never return 200 with an error payload.
**Versioning**: Version from day one, before you have clients. URL versioning (`/v1/`) is the most visible and easiest to route at the gateway layer. Header versioning (`Accept: application/vnd.api.v2+json`) is cleaner but harder to test. Additive changes (new fields, new optional parameters) are non-breaking; removing or renaming fields is breaking.
**Pagination, filtering, sorting**: For collections, always paginate. Prefer cursor-based pagination over offset for large or frequently-updated datasets—offset pagination is inconsistent when items are inserted mid-page. Expose filtering via query parameters (`?status=active&sort=-created_at`).
**Authentication and authorization**: Use OAuth 2.0 / JWT for stateless auth. Never put credentials in URLs. Validate authorization at the resource level, not just the endpoint level—users should not be able to access other users' resources by ID manipulation (IDOR).
**Rate limiting**: Return `429 Too Many Requests` with `Retry-After` and `X-RateLimit-*` headers. Limit by API key or user identity, not just IP.
**Idempotency keys**: For non-idempotent POST operations that have significant side effects (payments, email sends), accept an `Idempotency-Key` header and deduplicate server-side.
**Error responses**: Return structured, consistent error bodies with a machine-readable code, a human-readable message, and optionally a documentation link. Never expose stack traces.
**Documentation**: Use OpenAPI (Swagger) to generate interactive docs and client SDKs. Treat the spec as the source of truth, not an afterthought.
Covers resource naming, HTTP method semantics, status codes, versioning, and pagination with trade-offs.
Covers all the above plus idempotency keys, IDOR prevention, cursor pagination trade-offs, structured error bodies, and rate limiting headers.
Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.
Get Graded — Free Assessment