LESSON 2.3
Designing the API
One endpoint per functional requirement, with clear resources, inputs and outputs, and the identity coming from auth rather than the body.
5 min read
The API is the contract between your system and its clients. In a design, it also does something more useful: it is a checklist. Every endpoint must be served by the high-level design you draw next.
One endpoint per requirement
Go through your functional requirements and write the call that satisfies each one. For the URL shortener:
POST /links
{ "url": "https://example.com/a/very/long/path", "alias": "launch", "expiresAt": "2027-01-01" }
→ 201 { "code": "launch", "shortUrl": "https://sho.rt/launch" }
GET /{code}
→ 302 Location: https://example.com/a/very/long/pathThat is the whole API. Two endpoints, two requirements.
REST conventions that keep you out of trouble
- Resources are nouns, methods are verbs.
POST /links,GET /links/{code},DELETE /links/{code}. NotPOST /createLink. - Plural collections.
/events/{id}/seats, not/event/{id}/seat. - Correct status codes.
201 Created,302 Foundfor redirects,404for an unknown code,409 Conflictwhen a custom alias is taken,429when rate limited. - Paginate collections.
GET /feed?cursor=abc&limit=20. A cursor (an opaque pointer to the last item seen) stays correct when new items arrive at the top, unlike?page=3.
REST, RPC or real time?
REST over HTTP is the default for public APIs. Two alternatives come up often:
REST (HTTP + JSON)
- Universal, cacheable, easy to debug
- Request/response only
- Verbose payloads
Pick it when: Public and client-facing APIs; most CRUD.
gRPC
- Compact binary encoding
- Typed contracts
- Streaming
- Harder for browsers
- Less human-readable
Pick it when: Service-to-service calls inside your system.
WebSocket / SSE
- Server can push instantly
- Long-lived connections to manage
- Harder to load balance
Pick it when: Chat, live scores, collaborative editing, notifications.
Webhooks
A chat system, for example, typically uses REST for history (GET /chats/{id}/messages?cursor=…) and a WebSocket for live messages.
Keep it high level
In a design discussion, the API does not need every field and header. You need:
- the method and path (or the message type for real-time APIs),
- the important inputs,
- the important outputs,
- anything that affects the design: pagination, idempotency keys, rate limits.
POST /payments
Idempotency-Key: 7f3c… ← lets the client retry safely without double-charging
{ "orderId": "o_123", "amount": 4999, "currency": "INR" }That idempotency key is exactly the kind of detail worth including: it changes the design, because the server now needs to remember which keys it has already processed.
Try it
Chat Service HLD
Design an API that mixes request/response history with real-time delivery.