API Design Best Practices: 9 Principles with Examples
Nine habits of a clean API: nouns not verbs, consistency, safe GETs, statelessness, safe retries, pagination, secure defaults, non-breaking changes and…
Related chapters
- Start here in System Design
- How a system design interview is graded
- The delivery framework: five phases and a clock
- Numbers to know: what one machine can really do
- System Design Concepts: CAP, SQL vs NoSQL, Message Queues
- SQL vs NoSQL: How to Choose a Database (System Design)
- Traffic Jumps 10×: What Breaks First? (System Design)
- Proxy vs Load Balancer vs API Gateway (System Design)
- CAP Theorem Explained Simply, with Examples
- Why Use a Message Queue? System Design Explained
- Message Queue vs Pub/Sub vs Kafka: Differences
- Polling vs Long Polling vs SSE vs Webhooks (System Design)
- API design in System Design
- REST vs GraphQL vs gRPC: Choosing an API (System Design)
- API Goals Canvas: Design APIs from the Consumer
- REST API Design: Resources, Methods, Status Codes
- HTTP Semantics, Richardson Maturity Model and HATEOAS
- GraphQL Explained: Over-fetching, Schema, N+1 Problem
- RPC and gRPC Explained: Protobuf, HTTP/2, When to Use
- API Payload Design: Names, Types, Links and Errors
- Mapping Database Tables to API Resources, Step by Step
- API Design for Complex Schemas: Trees, Polymorphism, Bookings
- API Pagination, Idempotency Keys, Errors and Versioning
- Network-Efficient APIs: HTTP Caching, ETags, Field Selection
- Async APIs: 202 Accepted, Webhooks and Bulk Operations
- API Versioning and Evolution Without Breaking Clients
- API Contracts: OpenAPI, Contract Testing and Docs
- API Security: Authentication, Authorization, Rate Limiting
- OAuth 2, OpenID Connect and Scopes for APIs
- OWASP API Top 10 Explained: BOLA, SSRF and More
- Running APIs: Gateways, Mesh, Rate Limits, Canaries
- API Troubleshooting Interview: Slow APIs and Unexpected Errors
- API Design Review: A Staff-Level Capstone
- Spotify Web API: Resources, IDs, Payloads and Paging
- Spotify Web API: OAuth PKCE, Scopes, Quotas, Rate Limits
- Spotify Web API Changes: Real API Evolution Lessons
- Database-heavy designs in System Design
- Design a Distributed Key-Value Store (System Design Interview)
- Design a Hotel Reservation System (System Design Interview)
- Design a Digital Wallet (System Design Interview)
- Design S3-like Object Storage (System Design Interview)
- Games in System Design
- Shard City: Learn Database Sharding by Playing a Game
- System Design Case Studies: Flash Sale, Chat, ChatGPT
- Flash Sale System Design: Who Gets the Last Item
- Food Delivery App System Design: Which Database?
- Cache Stampede: Why the Database Fell Over and the Fix
- Live Streaming System Design: Scaling for a Final
- ChatGPT System Design: Streaming LLM Responses
- RAG System Design: Product Q&A on Sale Day
- IRCTC Tatkal System Design: Booking Under Extreme Load
- Group Chat System Design: WebSockets and Fan-Out
- Authentication in System Design: Sessions, JWT, OAuth
- Authentication Methods Compared: Sessions, JWT, OAuth
- JWT in System Design: Sessions, Revocation, Refresh Tokens
- JWT Interview Questions and Answers
- Life of a session, step by step
- JWT Structure Explained: Header, Payload, Signature
- Forge lab: why verification must be strict
- JWT vs Session Authentication: Which to Use
- The validation pipeline: where a bad request dies
- How to Revoke a JWT: Blocklists and Short Expiry
- Refresh Tokens and Rotation Explained
- Logout in depth: one device, all devices, SSO
- JWT Security Best Practices
- OAuth 2.0 and OpenID Connect Explained
- Where to Store JWT: localStorage vs HttpOnly Cookie
- JWT in Microservices: API Gateway vs Service Validation
- Microservices, keys, and trust boundaries
- Sender-constrained tokens: making a stolen token useless
- Authentication vs Authorization Middleware
- Failure explorer: what breaks when X fails
- Capacity planner: sessions vs JWT vs hybrid
- Edge cases catalog
- Test it, measure it, migrate to it
- Anti-patterns to reject in a design review
- Design checklist and cheat sheet
Keep learning
Overview
Name things, not actions POST /createBooking POST /events/123/bookings Be consistent everywhere Pick one way to name fields, page lists and report errors, and use it on every endpoint. A developer who learns one endpoint then knows them all. event_id everywhere No surprises: GET never changes anything Browsers, link previews and search bots call GET links freely. If a GET link cancels a booking, a chat app showing a preview of it could cancel it. GET /bookings/9/cancel DELETE /bookings/9 Stateless: each request carries what it needs The server should not remember “what page this user was on”. Behind a load balancer the next request may land on a different server that never saw the last one. GET /events/next-page\n(server remembers where you were) GET /events?cursor=evt_456 Safe to retry POST /bookings sent twice → 2 bookings POST /bookings + Idempotency-Key → 1 booking Paginate anything that can grow GET /events → all 2,000,000 GET /events?limit=20 (max 100) Secure by default Every endpoint needs a login unless you decide it is public. Check that the user owns what they touch. Only HTTPS, so nobody on the café wifi can read the token. GET /bookings/9 works for anyone only the owner (or an admin) gets booking 9 Grow without breaking old apps rename date → starts_at keep date, add starts_at Errors that say what to do An error should tell the developer what went wrong and how to fix it: a stable code for programs to check, a message for humans, and which field was wrong. 400 Bad Request GET /getAllEvents GET /events?limit=20 The verb moves into the method, and a list that can grow gets a page size (rule 6 too). GET must never change data. A link preview bot could have cancelled this booking. POST /events/123/bookings (user from the token) Anyone could put another user’s ID in the body. Take the user from the login token. GET /events → 2,000,000 rows GET /events?limit=20&cursor=… One page at a time, with a maximum page size. 500 “Something went wrong” (seat already sold) It is not a server crash, it is a conflict the user can fix by picking another seat. Say so. v1 renames price → amount v1 keeps price, adds amount Old apps still read price. Add, don’t rename. Lab: each of these breaks a rule. Guess which, then press Fix. Fix →
Nine principles of a clean API
You now know the three styles. Whichever you pick, the same habits decide whether the API is easy to use and hard to misuse. Here are nine, each with a bad and a good example from the ticket site.
Why habits matter more than style
An API is a promise. Once phone apps and other companies depend on it, changing it is slow and painful. So a few choices made in the first five minutes stay with you for years. The nine principles below are grouped by what they protect: the developer using the API (1–3), the servers running it (4–6), and the future (7–9).
Practise: fix the bad endpoints
Each line below is a real kind of mistake. Try to name the broken rule before you press Fix.
In the interview
You won’t recite nine rules. You show them by how you write the endpoints, and mention one or two out loud where they matter: “GET /events is paginated with a cursor since it can grow without limit. The user ID comes from the token, not the body. And booking takes an idempotency key so a retry can’t double-book.” Three of these rules need a little machinery to work: pagination, safe retries and good errors. Pagination, idempotency keys, errors and versioning builds each one, right after the payload chapter shapes what goes inside each request and response. Spotify keeps one ID format everywhere and adds a typed URI where items can be mixed. IDs, URIs and URLs Its /me endpoints make the token, not the URL, say whose data it is. Access control on Spotify
More courses
- Jobs, linked to lessons — Browse jobs where every requirement links to the chapter that teaches it. See how ready you are, how long the gap takes to close, and which listings look stale.
- Match a job post to courses — Paste a job post. Each skill is matched to a track here and put in learning order, foundations first.
- React from open source with patterns — Patterns extracted from Material UI, Radix, React Aria, React Hook Form, Redux Toolkit, TanStack, and Next.js — not slides about hooks.
- Database in depth — How a query becomes work. Indexes, isolation, locks, and the plans that explain why a page is slow — not an ORM tour.
- Build a real API with NestJS — One ticket-booking API, built in order: a plain Node server first, then NestJS modules, validation, a real database, and the features real clients lean on.
- Microservices — Microservice patterns one diagram at a time: how to split a monolith, how services talk, and how data stays consistent without distributed transactions.
- Kafka — A beginner-to-senior path through event logs, reliable delivery, production operations, and disaster recovery.
- AI engineering for software engineers — Eight free reads, in order, for software engineers moving into AI: when to build an agent, how to build one, how to test it, and how the model works underneath.
- Frontend system design — How a UI is sliced when it is a product, not a page: ownership of state, cache, routes, and what happens when the network lies.
- TypeScript in depth — The type system as a design tool. Inference, narrowing, generics, and the errors that mean the model is wrong — not a catalog of utility types.
- CSS in depth — See the box, then the page. Visual chapters from the box model through Flexbox surprises, Grid, selectors, and units, then backgrounds, shapes, and visual effects, each with a playground.
- Accessibility — Foundations first (WCAG in plain words, semantic HTML, lists, alt text), then hands-on HTML labs, a full pass of WAI-ARIA 1.3, and a final fix-the-page challenge.
- Docker — What an image is, why layers cache, and how containers find each other on a network.
- Redis — Fifteen Redis patterns, one picture each: cache, session, lock, counter, rate limiter, queue, and when Redis is the wrong tool.
- Kubernetes — Kubernetes from zero to operators: why it exists, Pods, Deployments and Services, then configuration, networking, storage, scheduling, scaling and security.