Why APIs get five minutes, not fifty
Candidates lose more interviews by over-engineering the API surface than by under-designing it. You have roughly five minutes: pick a protocol, sketch resources, mention auth and pagination in a sentence each, then move to the part of the system that's actually hard. This page is calibrated to that budget — run through one booking flow so you can see the whole shape at once.
REST default · GraphQL / RPC when signaled
Resources · verbs · path/query/body
Pagination · versioning
AuthN/AuthZ · JWT/keys · rate limits
Say "I'll use REST," sketch the core resources, note auth and pagination in one breath each, then move on — unless the prompt forces GraphQL, RPC, or realtime.
API types — REST, GraphQL, RPC
- REST — HTTP methods on URL resources. Maps cleanly to CRUD. Your default.
- GraphQL — one endpoint; clients specify exact fields. Reach for it when the interviewer says "flexible fetching," or you're staring down real over-fetching or under-fetching across mobile vs. web.
- RPC (e.g. gRPC) — action-oriented, binary, HTTP/2. Reach for it on microservices and internal calls like
checkPermission(userId, resource), where performance is the point.
Default to REST unless you have a specific reason not to — it covers roughly 90% of interview prompts. If you're unsure, say "I'll use REST APIs" and keep moving.
Realtime — notifications, chat, live seat maps — isn't a request API at all; it needs a persistent connection. See Networking essentials for SSE vs. WebSockets.
REST unless signaled otherwise. Don't invent a GraphQL layer for a fixed CRUD whiteboard just to show you know the word.
REST — resource modeling
Since REST is the default, it earns most of your five minutes. Good REST starts with correct resources — your core entities, named as nouns.
A Ticketmaster-style surface: events, venues, tickets, bookings.
GET /events·GET /events/{id}GET /venues/{id}GET /events/{id}/ticketsPOST /events/{id}/bookings·GET /bookings/{id}
Resources are things, not actions — plural nouns, not verbs. Some interviewers dock points for singular resource names; it's free credit either way.
Nesting vs. flat + query: nest when the parent is required for the child to make sense (/events/{id}/tickets). Use query params when the filter is optional (/tickets?event_id=123§ion=VIP). That's the whole rule — required goes in the path, optional goes in the query string.
Identify entities first. Nesting vs. query is a required-vs-optional decision, not a style preference.
HTTP methods and idempotency
- GET — read; safe; idempotent
- POST — create (server assigns id); not safe; not idempotent — retries can duplicate
- PUT — full replace (or create); idempotent
- PATCH — partial update; idempotent only if your semantics are (set email=X, yes; append-to-list, no)
- DELETE — remove; idempotent (resource stays gone even if a later call 404s)
Mobile networks drop a real slice of requests, and clients retry. A POST /bookings that retries naively means one tap can book two seats and charge one card twice. Say the retry risk out loud when you draw the booking endpoint — it's the detail that separates "knows REST" from "has shipped a payment flow."
Map CRUD to verbs, then flag exactly one thing unprompted: POST on a booking endpoint needs an idempotency key, or a retry becomes a double charge.
Passing data — path, query, body
- Path — which resource (
/events/123); required identity - Query — optional filter/sort/paginate (
?city=NYC&date=2024-01-01&page=2);?then& - Body — create/update payload (tickets, payment method); complex or sensitive data
Booking two VIP seats and one general seat for event 123:
POST /events/123/bookings?notify=true
{
"tickets": [
{"section": "VIP", "quantity": 2},
{"section": "General", "quantity": 1}
],
"payment_method": "credit_card"
}The event id is required, so it's path. notify is optional behavior, so it's query. The ticket lines are what you're creating, so they're body.
Path is who/what, query is optional how, body is the data. If you're arguing about which one a field belongs in, check whether it's required first.
Returning data — status + body
A response carries a status code and usually a JSON body.
- 200 OK · 201 Created
- 400 bad request · 401 auth required · 404 not found · 429 rate limited
- 500 server error
Name the three buckets — success, client error, server error — and skip the trivia codes entirely.
GraphQL — when flexibility is the problem
GraphQL (Facebook, ~2012) exists because mobile and web needed different shapes of the same data, and REST's answer was either endpoint sprawl or shipping megabytes the screen never rendered.
query {
event(id: "123") {
name
date
venue { name address }
tickets { section price available }
}
}Mobile asks for name and date only; the box-office dashboard asks for venue and live availability — same schema, same endpoint, different query.
Reach for it when clients genuinely diverge, the interviewer uses the words over-fetching or under-fetching, or frontend needs to iterate without backend deploys. Pay for it with parser and schema-validation overhead, harder caching, and the N+1 trap — 100 events fetched naively becomes 101 queries without dataloader batching. Auth also moves from the endpoint to the field.
Bring up GraphQL when fetch-shape pain is the stated problem. Don't default to it just because it sounds more sophisticated than REST.
RPC / gRPC — actions between services
RPC lets a client call a procedure on a server and wait, with the network abstracted away. gRPC pairs protobuf with HTTP/2 and is meaningfully faster than JSON-over-REST for service-to-service calls. (Thrift is another polyglot option, less common in interviews.)
Action-oriented, not resource-oriented:
getEvent(eventId)instead ofGET /events/123createBooking(...)instead ofPOST /events/123/bookingsgetAvailableTickets(eventId, section)
A .proto file is the contract; codegen produces typed clients per language, so a mismatch fails at compile time instead of in production.
Use it when performance, type safety, or streaming actually matter, and it's between services you own — booking talking to payment talking to inventory. Pattern: REST at the edge, gRPC inside. In the API step, stay focused on the user-facing surface; "internal services use RPC" is usually enough unless the interviewer asks you to go deeper.
Public surface is REST; internal hot paths are gRPC. Don't design the internal RPCs in detail unless the interviewer explicitly asks.
Common patterns — pagination & versioning
You can't return every event in one response. Two approaches:
- Offset —
?offset=20&limit=10. Simple, easy page jumps; inserts while paging cause duplicates or skipped rows. - Cursor — a pointer to the last item (
next_cursor); stable under inserts; can't jump straight to page 5.
Offset is the right default unless the prompt is realtime or high-volume enough to make skipped rows a real problem. Remembering pagination exists at all matters more than which algorithm you pick.
Versioning: URL versioning (/v1/events) is explicit and easy to talk through out loud — prefer it in interviews. Header versioning keeps URLs cleaner but is less obvious to a listener. Most breakdowns skip versioning entirely because it's rarely graded — know it exists, don't design a migration strategy unprompted.
Put pagination on every list endpoint. Mention URL versioning once, if at all, and move on.
Security — auth, RBAC, rate limits
You don't need a fortress here — just clear boundaries. Authentication is who's asking. Authorization is what they're allowed to touch: the user can cancel their own booking, not everyone's.
API keys are long-lived secrets checked via header lookup — right for service-to-service calls and third-party integrators, wrong for end users. JWTs carry claims (user_id, role, exp) and verify by signature with no session-store round trip — right for mobile, web, and distributed gateways that can't all hit the same session DB.
Interview hygiene: mark which endpoints require auth, say "JWT" or "server session" and move on — don't design OAuth from scratch unless explicitly asked. Mention RBAC roles (customer, venue_manager, admin) only where the endpoint actually depends on them.
Rate limiting — per-user, per-IP, or endpoint-specific (10 booking attempts/min against scalpers) — returns 429. "We rate-limit at the gateway" is a complete answer unless the interviewer wants the algorithm.
State auth on mutating endpoints, JWT for users, keys for services, and a one-line rate-limit story — in that order, in one breath.
API design studio
Error & versioning mini-standard
4xxclient mistakes;5xxserver; include stableerror_code.- Version via URL
/v1or header; never break existing clients silently. - Rate limit headers:
X-RateLimit-Remaining,Retry-After.
Failure modes to mention
Call out at least one dependency failure (DB down, cache stampede, queue lag, region outage) and your mitigation (timeouts, retries with jitter, degraded mode, circuit breaker).
Cost and performance levers
Interview Q&A by level
Practice saying these out loud for API design. Interviewers grade clarity and judgment more than buzzwords.
Match depth to the bar: define → trade off → operate. Don't dump principal answers in an entry-level screen.
Wrapping up
API design in interviews rewards judgment, not a perfect spec. Pick the right protocol — usually REST — model resources as nouns, show you understand auth at a glance, and leave before the clock eats your real budget.
A reasonable API you can defend in one sentence beats a memorized status-code table every time. Spend the saved minutes on the system that's actually hard.