Grokking Modern API Design Interview
Vote

0% completed

​

A Framework for API Design Answers

  1. The 45-Minute Framework
  1. Why the Order Matters

Choice one: Start from the caller

Choice two: Design one operation completely

  1. Step 1: Identify the Consumers and the Jobs They Need to Finish, 5 Minutes
  1. Step 2: Model the Resources, 5 Minutes

Resource test

  1. Step 3: List the Operations, 10 Minutes

Prioritize instead of expanding

  1. Step 4: Design One Operation in Complete Detail, 10 Minutes

Request

Success response

Named failures

Retry behavior

  1. Step 5: Address the Hard Parts, 10 Minutes

Prioritize by risk

  1. Step 6: State the Trade-offs Taken and the Options Rejected, 5 Minutes

Trade-off 1: Expanded task response versus separate assignee reads

Trade-off 2: Explicit assign operation versus patching an ID array

Trade-off 3: Cursor versus offset pagination

Trade-off 4: Full created resource versus identifier-only response

A final summary pattern

  1. Compressing the Framework for a 30-Minute Round

What compression changes

What compression must not change

  1. Staying Oriented When the Interviewer Interrupts

A practical whiteboard layout

Key Takeaways

API design questions feel open-ended because the interviewer can ask about almost anything: resources, URLs, field types, status codes, pagination, retries, permissions, rate limits, or versions.

Without a clear structure, it is easy to move between endpoints, authentication, requirements, and errors without fully defining any operation.

The solution is a fixed sequence.

Every complete answer in this course follows six steps, in this exact order:

  1. Identify the consumers and the tasks they need to complete.
  2. Model the resources.
  3. List the operations.
  4. Design one operation in complete detail.
  5. Address the hard parts, such as paging, retries, versioning, authentication, and rate limits.
  6. State the trade-offs taken and the options rejected.

Each step provides information for the next. First identify the clients and their tasks. Then define resources and operations that support those tasks. Design one operation in detail to identify important issues such as retries and permissions. Finally, explain the advantages and disadvantages of your choices.

1. The 45-Minute Framework

Use this budget when the entire 45-minute session is available for API design.

The total is 45 minutes.

Use these times as a guide, not a strict schedule. The interviewer may ask questions or spend longer on one operation. Answer those questions, then return to the unfinished part of your plan when appropriate.

The six steps with their minute budget and the artifact each one produces: consumers and jobs 5, resources 5, operations 10, one operation in full 10, the hard parts 10, and trade-offs 5. Step four is marked never cut. The total is 45 minutes.
The six steps with their minute budget and the artifact each one produces: consumers and jobs 5, resources 5, operations 10, one operation in full 10, the hard parts 10, and trade-offs 5. Step four is marked never cut. The total is 45 minutes.

2. Why the Order Matters

The framework makes two important structural choices.

Choice one: Start from the caller

The API is a promise to the caller, so the caller should shape it.

Suppose a service stores customer information in separate profile, address, preference, and subscription tables. A mobile application may need one account-summary response. A billing partner may need only the subscription and billing contact. An internal fraud service may need a stable customer identifier and a few risk-relevant fields.

If you start from the tables, all three callers inherit the storage layout. If you start from the jobs, each contract can expose the information required for its task while storage remains free to change.

This creates a useful separation:

Caller job -> Stable API promise -> Replaceable implementation

The implementation may later denormalize data, split a service, merge tables, add a cache, or change databases. Those changes should not require every caller to rewrite its code.

Choice two: Design one operation completely

Operation names contain almost no decisions. CreateTask and ListTasks do not say what creation requires, which fields are optional, whether duplicate creation is safe, what success returns, which failures exist, or how authorization differs between reading and deleting. One complete operation forces all of those decisions, which is why Step 4 keeps its ten minutes in both the 45-minute and 30-minute versions.

3. Step 1: Identify the Consumers and the Jobs They Need to Finish, 5 Minutes

Gather enough context to choose a useful contract. You do not need to collect every possible requirement before starting the design.

Ask:

  • Who calls this API?
  • Is the caller first-party, internal, public, or automated?
  • What are the two or three most important jobs?
  • Which job should we optimize and design in depth?
  • Is the API new, or do existing callers constrain us?

For a team task-management API, your visible output might be:

ConsumerJobImportant consequence
First-party web and mobile clientsCreate, assign, and display tasksCommon screens should require few calls; responses should be compact and predictable.
Internal automationCreate tasks from alerts and workflowsWrites need stable external identifiers and safe retries.
Public partner integrationRead and update selected tasksCompatibility, explicit permissions, rate limits, and documentation matter.

You do not need to design for all three equally. State the scope:

"I'll optimize the initial design for the first-party application and internal automation. I'll keep the contract compatible with a later public API, but I will not design partner onboarding in detail unless you want to discuss it."

Stating the scope gives the interviewer a chance to correct your assumptions before you continue.

4. Step 2: Model the Resources, 5 Minutes

Resources are the stable concepts a caller reads, creates, changes, or refers to later.

For the task-management example, the first model might include:

  • Project
  • Task
  • User
  • Comment

The model is not a database schema, so it needs no indexes, no partition keys, and not every field you store. It needs just enough structure to answer:

  • What has a stable identity?
  • What has its own lifecycle?
  • Which resource contains or refers to another?
  • Which relationships must the API expose?
  • Which object can become large and therefore needs separate paging?

A simple relationship sketch might be:

Project contains Tasks Task references Assignees (Users) Task has Comments

Use this model to decide which resources need their own operations.

Comments can be numerous, paginated, created independently, and deleted under separate permissions. They likely deserve a resource identity. An assignee relationship can sit directly on the task, or use explicit assign and unassign actions. It does not have to appear as a storage-style join record.

Resource test

For each proposed resource, ask:

"Does the caller think in terms of this concept, or does only the database think in terms of it?"

If only the database needs it, keep it behind the contract where you can still change it.

5. Step 3: List the Operations, 10 Minutes

Now turn the caller jobs from Step 1 into operations.

Do not generate five operations per resource out of habit. Ask what the caller actually needs to do, and publish only that.

For the selected task-management scope:

Seven caller jobs and the operation each one produces, with the design note attached to it. The first three are core because they carry the primary flow, and creation is the operation taken to full depth.
Seven caller jobs and the operation each one produces, with the design note attached to it. The first three are core because they carry the primary flow, and creation is the operation taken to full depth.

That is more useful than an endpoint list, because every line is tied to a caller job and carries one design note with it.

Prioritize instead of expanding

Mark operations as:

  • core: required for the primary flow;
  • supporting: needed soon but not designed deeply; or
  • out of scope: plausible but not required for this answer.

For example:

"Creation, retrieval, and listing are core. I'll mention update and comments for model completeness, but I'll design creation in depth. Bulk import, task templates, and full-text search are out of scope."

A smaller, complete design usually explains your decisions more clearly than a larger design with important details missing.

6. Step 4: Design One Operation in Complete Detail, 10 Minutes

This is the center of the interview, and the step most worth protecting when time runs short.

For one important operation, define the complete caller-visible contract:

  1. method and path;
  2. authentication or required permission;
  3. important headers;
  4. request fields, types, units, and validation;
  5. success status and headers;
  6. response body;
  7. named failure cases with status codes;
  8. machine-readable error body; and
  9. retry or idempotency behavior.

For this example, design task creation in detail.

Request

POST /v1/projects/prj_123/tasks Authorization: Bearer <token> Idempotency-Key: c990fbf6-2e5c-41b8-b983-bfe08116e91a Content-Type: application/json
{ "title": "Prepare launch checklist", "description": "Cover monitoring, rollback, and support ownership.", "assignee_ids": ["usr_17", "usr_42"], "due_at": "<RFC 3339 UTC timestamp>", "external_id": "alert-88421" }

Define the fields rather than leaving an interviewer to assume them:

FieldRequired?TypeRule
titleYesString1 to 200 characters after trimming.
descriptionNoStringMaximum 10,000 characters. Omission means no description.
assignee_idsNoArray of user IDsNo duplicates; every user must be assignable in the project.
due_atNoRFC 3339 timestampMust include an offset; stored and returned in UTC.
external_idNoStringUnique within the caller and project; useful for reconciliation.

Notice the contract decisions contained in this table. A title is not merely "a string." It has a length rule. A timestamp includes a format and timezone expectation. An omitted description is not automatically the same as null. An external identifier has a uniqueness scope.

Success response

HTTP/1.1 201 Created Location: /v1/tasks/tsk_789
{ "id": "tsk_789", "project_id": "prj_123", "title": "Prepare launch checklist", "description": "Cover monitoring, rollback, and support ownership.", "status": "open", "assignees": [ { "id": "usr_17", "display_name": "Ari Chen" }, { "id": "usr_42", "display_name": "Sam Rivera" } ], "due_at": "<RFC 3339 UTC timestamp>", "external_id": "alert-88421", "version": 1, "created_at": "<RFC 3339 UTC timestamp>", "updated_at": "<RFC 3339 UTC timestamp>" }

201 Created states that a new resource exists. Location identifies it. The full representation lets a first-party client render the result without an immediate read. The version field can support later concurrency control.

Named failures

Every failure names what the caller should do about it, rather than only what went wrong.

Eight named failures for task creation. Each carries a status code, a stable machine-readable error code, the condition that produces it, and the action the caller should take next, because a failure the caller cannot act on is an unfinished contract.
Eight named failures for task creation. Each carries a status code, a stable machine-readable error code, the condition that produces it, and the action the caller should take next, because a failure the caller cannot act on is an unfinished contract.

A consistent error body might be:

{ "error": { "code": "invalid_assignee", "message": "User usr_42 cannot be assigned to this project.", "field": "assignee_ids[1]", "request_id": "req_91a8" } }

Retry behavior

If the caller times out it cannot know whether the task was created, and repeating an unprotected POST may create a second one.

The Idempotency-Key makes retry behavior explicit:

  • same key and same request body: return the original result;
  • same key and different body: return 400 idempotency_key_reused;
  • new key: treat as a new creation attempt.

State the idempotency key's scope and retention period, and explain what happens when two requests use the same key at the same time. You can discuss storage details if asked, but the client-visible rules must be clear. The rules above apply only while the server retains the key and result.

7. Step 5: Address the Hard Parts, 10 Minutes

The hard parts are cross-cutting decisions that affect several operations.

Common topics include:

  • paging and filtering;
  • retries and idempotency;
  • authentication and authorization;
  • rate limits;
  • versioning and compatibility;
  • concurrency;
  • asynchronous work;
  • caching;
  • consistency guarantees; and
  • multi-tenancy.

Choose the topics that matter to your requirements and the operation you designed. You do not need to cover every item in the list.

For the task API, five relevant decisions might be:

Five hard parts for the task API: pagination, safe retries, authorization, rate limits, and concurrency. Each shows the decision taken and the reason that decision fits this question rather than a general checklist.
Five hard parts for the task API: pagination, safe retries, authorization, rate limits, and concurrency. Each shows the decision taken and the reason that decision fits this question rather than a general checklist.

Then explain behavior at the contract boundary.

For example:

"Task lists use an opaque next_cursor. Filters are repeated on every request, and the cursor is valid only for the same filter and sort. The response does not promise a total count because calculating an exact count may be expensive and can become stale immediately."

Or:

"An update carries the ETag from the last read in an If-Match header. If another writer changed the task, the server returns 412 Precondition Failed so the client can reload before deciding whether to retry."

Prioritize by risk

When time is short, choose the hard parts most likely to cause duplicate work, data exposure, wrong client behavior, or future incompatibility.

For a public write API, authentication, authorization, idempotency, rate limits, and versioning may dominate. For a list-heavy first-party application, paging, filtering, payload size, and caching may dominate. For long-running work, asynchronous state and completion delivery may dominate.

Name several caller-visible decisions, each connected to a requirement. "We will have rate limiting" is not enough: state who is limited, what happens at the limit, and how the caller recovers.

8. Step 6: State the Trade-offs Taken and the Options Rejected, 5 Minutes

Use the final minutes to explain the reasons for your main choices.

Review the important decisions and describe the disadvantage of each.

For the task API:

Trade-off 1: Expanded task response versus separate assignee reads

"I included compact assignee summaries in the task response so the first-party client can render the common screen without additional reads. The cost is duplicated user data and a larger payload. I accept that for item reads but would keep large task lists more compact."

Trade-off 2: Explicit assign operation versus patching an ID array

"I chose an explicit assignment operation instead of treating assignees as a generic replaceable array. This adds an operation, but it gives assignment its own permissions, duplicate behavior, audit event, and errors."

Trade-off 3: Cursor versus offset pagination

"I chose cursor pagination because tasks can be inserted and reordered while a caller is paging. The cost is that callers cannot jump to an arbitrary page number."

Trade-off 4: Full created resource versus identifier-only response

"Creation returns the full task so the client does not need an immediate read. The cost is a larger response and more fields in the compatibility surface."

A final summary pattern

Close with:

"The design optimizes the first-party task flow and safe automation writes. I accepted larger responses and more operations to reduce client calls and make state transitions explicit. If the primary consumer changed to a high-volume public integration, I would revisit the expanded representations and limits."

A statement like that reminds the interviewer the design follows your stated requirements, rather than claiming to be optimal for everybody.

9. Compressing the Framework for a 30-Minute Round

For a 30-minute round, halve every step except Step 4, which still gets its full ten minutes.

The compressed steps total 27.5 minutes, leaving 2.5 minutes for interviewer questions and transitions.

What compression changes

For a 30-minute answer, choose one main client, model only the resources its task needs, and list three to five operations. Discuss two or three difficult issues and two clear trade-offs. Keep enough time to define one complete operation.

What compression must not change

Never reduce Step 4 to a method and a path, because that is the evidence the round exists to collect.

The deep operation is where the interviewer sees field design, success behavior, failures, retries, and consistency working together. If you halve every step equally, you may finish on time but provide no strong evidence.

If you have less time than expected, cover fewer operations while keeping the important details of one operation.

Keep: one caller, one job, a small resource model, a few operations, one complete operation, the two hardest concerns, and two trade-offs.

Remove first: secondary callers, rare operations, speculative features, and long debates about naming.

The 45-minute and 30-minute budgets side by side. Every step halves except step 4, the complete operation, which keeps its full ten minutes. The compressed steps total 27.5 minutes and leave 2.5 minutes of buffer for clarification and transitions.
The 45-minute and 30-minute budgets side by side. Every step halves except step 4, the complete operation, which keeps its full ten minutes. The compressed steps total 27.5 minutes and leave 2.5 minutes of buffer for clarification and transitions.

10. Staying Oriented When the Interviewer Interrupts

Interviewers interrupt for good reasons: to test one decision, to redirect the scope, or to give you information you were missing.

Answer the question directly, then restore the structure:

"That covers the retry behavior. I was listing the core operations, so I'll finish that list and then design creation in detail."

Keep a small six-line checklist visible:

1. Consumers and jobs [done] 2. Resources [done] 3. Operations [in progress] 4. One operation in full 5. Hard parts 6. Trade-offs

Use this checklist to track what you have covered. Adapt it to the discussion rather than following it mechanically.

A practical whiteboard layout

Reserve the areas before you begin, as laid out in the diagram below. The layout makes progress visible and reduces rewriting.

A whiteboard divided into six regions. Callers and jobs, resources, and operations stay small along the top. One operation in full takes the largest region. The hard parts run down the right side and the trade-offs across the bottom.
A whiteboard divided into six regions. Callers and jobs, resources, and operations stay small along the top. One operation in full takes the largest region. The hard parts run down the right side and the trade-offs across the bottom.

Key Takeaways

  • Every answer in the course follows six steps in this exact order: consumers and jobs, resources, operations, one complete operation, hard parts, and trade-offs.
  • The 45-minute budget is 5 + 5 + 10 + 10 + 10 + 5 minutes.
  • Starting from the caller keeps the published promise stable while storage and implementation remain free to change.
  • Operation names contain almost no decisions; one complete operation exposes inputs, outputs, status codes, failures, and retry behavior.
  • Step 5 should cover the hard parts created by the requirements, not every API topic you remember.
  • Trade-offs should name the selected option, rejected alternative, benefit, and accepted cost.
  • For a 30-minute round, halve every step except Step 4, which remains ten minutes; the resulting 27.5-minute plan leaves a 2.5-minute buffer.
  • When time is limited, cover fewer operations in enough detail.

You now have a structure for a complete answer. The next lesson explains Step 1 in more detail: identify the client, ask questions that affect the API, and sketch how client code would use it.

Reading Progress

0%


Vote for new content

On This Page

  1. The 45-Minute Framework
  1. Why the Order Matters

Choice one: Start from the caller

Choice two: Design one operation completely

  1. Step 1: Identify the Consumers and the Jobs They Need to Finish, 5 Minutes
  1. Step 2: Model the Resources, 5 Minutes

Resource test

  1. Step 3: List the Operations, 10 Minutes

Prioritize instead of expanding

  1. Step 4: Design One Operation in Complete Detail, 10 Minutes

Request

Success response

Named failures

Retry behavior

  1. Step 5: Address the Hard Parts, 10 Minutes

Prioritize by risk

  1. Step 6: State the Trade-offs Taken and the Options Rejected, 5 Minutes

Trade-off 1: Expanded task response versus separate assignee reads

Trade-off 2: Explicit assign operation versus patching an ID array

Trade-off 3: Cursor versus offset pagination

Trade-off 4: Full created resource versus identifier-only response

A final summary pattern

  1. Compressing the Framework for a 30-Minute Round

What compression changes

What compression must not change

  1. Staying Oriented When the Interviewer Interrupts

A practical whiteboard layout

Key Takeaways