API Derivation Cheat Sheet
API Derivation Cheat Sheet #
Use this note as the bridge between:
- functional requirements
- entities
- write shapes
- HLD
The goal is not to design perfect REST. The goal is to make the system concrete and interview-friendly.
Why APIs matter #
APIs force you to answer:
- who calls the system
- what the main objects are
- what the core write paths are
- whether the path is sync or async
- where idempotency matters
- where pagination or conditional updates matter
So the delivery flow becomes:
- functional requirements
- NFRs
- entities
- APIs
- HLD
- deep dives
Mental model #
Derive APIs from paths.
- path tells you the operation
- entity tells you the resource
- write shape tells you the endpoint style
Then add the few semantics that matter:
- idempotency
- pagination
- conditional versioning
- async job status
- projection reads
Path -> API Shape #
1. Create Target #
Examples:
- create post
- create order
- create profile
- upload file metadata
Typical API:
POST /postsPOST /ordersPOST /profiles
Mention when needed:
- idempotency key if duplicate create is dangerous
- request id if retry ambiguity matters
Good interview line:
This is a
create targetpath, so I’d expose aPOSTon the primary resource and add an idempotency key if duplicate creation is harmful.
2. Overwrite Current Value #
Examples:
- edit profile
- rename file
- update feature flag
- update listing
Typical API:
PATCH /profiles/:idPATCH /files/:idPUT /flags/:id
Mention when needed:
- version / etag /
If-Match - partial vs full update
Good interview line:
This is an overwrite path, so I’d use
PATCHorPUTwith a version token to avoid lost updates.
3. State Transition #
Examples:
- cancel booking
- accept suggestion
- revoke share
- follow/unfollow
- restore file
Typical API styles:
- action-style:
POST /bookings/:id/cancelPOST /suggestions/:id/accept
- relation-style:
PUT /follows/:target_user_idDELETE /follows/:target_user_id
Mention when needed:
- guarded transition from current state
- idempotent retry behavior
- expected no-op vs conflict
Good interview line:
This is a lifecycle transition, so I’d use either an action endpoint or relation add/remove endpoint, and I’d make the transition conditional on the current state.
4. Append Child Object #
Examples:
- comment on post
- reply to thread
- leave review
- append message
Typical API:
POST /posts/:id/commentsPOST /comments/:id/repliesPOST /businesses/:id/reviews
Mention when needed:
- request id if duplicate append is harmful
- cursor pagination for reads
Good interview line:
This is an append child path, so I’d model it as
POSTon the parent collection.
5. Read Source #
Examples:
- view profile
- view order status
- view seat map
- view current document
Typical API:
GET /profiles/:idGET /orders/:idGET /events/:id/seatsGET /documents/:id
Mention when needed:
- strong vs bounded-stale source read
- actor-specific authorization
Good interview line:
This is a source read path, so I’d expose a direct
GETon the canonical resource.
6. Read Projection #
Examples:
- search
- feed
- top K
- recommendations
- dashboards
Typical API:
GET /search?...GET /feed/homeGET /hashtags/:tag/postsGET /leaderboards/globalGET /recommendations
Mention when needed:
- cursor pagination
- freshness bounds
- eventual consistency acceptable
Good interview line:
This is a projection read, so I’d expose it as a dedicated query endpoint and explicitly call out freshness and pagination.
7. Claim / Lease / Worker Path #
Examples:
- worker claims job
- scheduler creates due run
- worker marks run success/failure
Typical API:
- internal queue contract
POST /internal/jobs/claimPOST /internal/jobs/:id/completePOST /internal/jobs/:id/fail
Mention when needed:
- claim token / lease id
- worker ownership
- retry semantics
Good interview line:
This is an internal claim path, so I’d treat it as a worker API or queue contract rather than a public user API.
Archetype -> Typical APIs #
Current-Value Entity #
POST /resourceGET /resource/:idPATCH /resource/:id
Examples:
- profile
- listing
- document metadata
Relation / Edge #
PUT /follows/:target_idDELETE /follows/:target_idGET /users/:id/followersGET /users/:id/following
Examples:
- follows
- likes
- bookmarks
- subscriptions
Append Child Object #
POST /posts/:id/commentsGET /posts/:id/comments?cursor=...
Examples:
- comments
- messages
- reviews
Workflow / Lifecycle #
POST /ordersPOST /orders/:id/cancelGET /orders/:id
Examples:
- orders
- bookings
- refunds
Inventory / Constrained Resource #
GET /events/:id/seatsPOST /seat-holdsPOST /bookingsPOST /bookings/:id/cancel
Examples:
- seats
- rooms
- stock
- slots
Search / Projection #
GET /searchGET /feed/homeGET /leaderboards/globalGET /hashtags/trending
Control Plane #
POST /flagsPATCH /flags/:idGET /flags/:idPOST /flags/:id/rollout
Examples:
- feature flags
- config
- policy
The extra semantics to mention #
Do not over-design the API section. Usually mention only the semantic knobs that matter.
1. Idempotency #
Mention for:
- payments
- purchases
- creates where duplicates hurt
- retries on unstable networks
Example:
Idempotency-Keyheader onPOST /bookings
2. Conditional update / versioning #
Mention for:
- overwrites
- guarded transitions
- shared mutable state
Example:
If-Match: version- or request body field
expected_version
3. Pagination #
Mention for:
- lists
- feeds
- history
- followers
- comments
- search results
Default:
- cursor pagination, not offset, for large moving datasets
4. Async workflow status #
Mention for:
- long-running jobs
- uploads
- indexing
- batch processing
- payout/refund workflows
Example:
POST /exportsGET /exports/:id
5. Projection freshness #
Mention for:
- search
- feed
- leaderboard
- trending
Example line:
This endpoint is served from a projection, so results may lag source truth by a few seconds.
Public API vs internal API #
Separate these clearly in interviews.
Public / product-facing #
Examples:
- create post
- follow user
- search businesses
- hold seat
Internal / system-facing #
Examples:
- claim reminder job
- complete campaign batch
- push feed fanout task
- projection updater writes
You usually do not need to expose internal APIs unless:
- they are central to the design
- they explain correctness
- they explain async workflow boundaries
Example derivations #
Example 1: Follow system #
Paths:
- follow user
- unfollow user
- view followers list
- view follower count
Entities:
FollowRelationFollowerCountView
APIs:
PUT /follows/:target_user_idDELETE /follows/:target_user_idGET /users/:id/followers?cursor=...GET /users/:id/follower-count
What to mention:
- follow/unfollow is guarded add/remove
- followers list may come from source index
- count comes from projection and may lag
Example 2: Ticketmaster #
Paths:
- browse events
- seat map
- hold seat
- buy seat
Entities:
EventSeatInventorySeatHoldBooking
APIs:
GET /eventsGET /events/:id/seatsPOST /seat-holdsPOST /bookings
What to mention:
POST /seat-holdsneeds strong validationPOST /bookingsshould use idempotency key- seat map may be slightly stale, but hold/buy revalidates strongly
Example 3: Google Docs suggestions #
Paths:
- edit document
- create suggestion
- accept suggestion
- comment on range
- view history
Entities:
DocumentSuggestionCommentDocumentHistoryView
APIs:
PATCH /documents/:idPOST /documents/:id/suggestionsPOST /suggestions/:id/acceptPOST /documents/:id/commentsGET /documents/:id/history
What to mention:
- edit and accept may require document version checks
- history is a projection
- comment is append child
What not to do #
- do not invent dozens of endpoints
- do not spend time on perfect REST purity
- do not design every internal RPC unless it matters
- do not skip pagination on large list endpoints
- do not forget idempotency on dangerous create/commit paths
Interview one-liner #
I derive APIs directly from the critical paths:
POSTfor create and append,PATCH/PUTfor overwrite, action endpoints or guarded add/remove for lifecycle transitions,GETon canonical objects for source reads, and dedicated query endpoints for projections like feed, search, and top K.