Skip to main content
Guides Skills and frameworks REST API Design Interview Questions — Resources, Status Codes, and Idempotency
Skills and frameworks

REST API Design Interview Questions — Resources, Status Codes, and Idempotency

9 min read · April 25, 2026

A practical REST API design interview guide with resource modeling rules, status-code choices, idempotency patterns, pagination, errors, and sample answers.

REST API Design Interview Questions — Resources, Status Codes, and Idempotency

REST API design interview questions usually test whether you can model resources cleanly, use HTTP semantics correctly, and make retries safe through idempotency. The best answers are not abstract lectures about REST maturity. They are concrete designs: nouns for resources, predictable URLs, correct status codes, validation errors that clients can use, pagination that scales, and write operations that do not duplicate money, orders, or messages when a client retries.

REST API design interview questions: what interviewers expect

A typical prompt sounds like "Design an API for orders," "How would you build a payments endpoint?" or "What's the difference between PUT and PATCH?" The interviewer wants to hear how you reason about:

  • Resource boundaries and URL structure.
  • HTTP methods and their semantics.
  • Status codes for success, validation, conflicts, auth, and missing resources.
  • Idempotency for retries and duplicate submissions.
  • Pagination, filtering, sorting, and versioning.
  • Error shape, observability, and backward compatibility.

A strong opening: "I'll model stable nouns as resources, use HTTP methods for actions where possible, define request/response examples, and call out idempotency and error handling for unsafe writes."

Model resources as nouns

REST URLs should generally name resources, not actions. Prefer:

GET /users/{userId}
GET /users/{userId}/orders
POST /orders
GET /orders/{orderId}
PATCH /orders/{orderId}
POST /orders/{orderId}/cancel

Over:

POST /getUser
POST /createOrder
POST /updateOrderStatus

The exception is a domain operation that is not a simple CRUD update. Cancellation, refund, capture, archive, and resend can be modeled as sub-resources or action endpoints. For example, POST /orders/{id}/cancel is understandable because canceling an order may trigger inventory release, payment reversal, notifications, and state-machine checks. If you want a more resource-oriented style, POST /orders/{id}/cancellations can also work.

The interview point is consistency. Do not mix /create-user, /users/delete, and /v1/doThing randomly.

Choose HTTP methods deliberately

| Method | Use | Idempotent? | Example | |---|---|---|---| | GET | Read a resource or collection | Yes | GET /orders/123 | | POST | Create subordinate resource or trigger non-idempotent operation | Not inherently | POST /orders | | PUT | Replace or create at a known URL | Yes if implemented correctly | PUT /users/123/profile | | PATCH | Partially update a resource | Not inherently, but can be | PATCH /orders/123 | | DELETE | Delete or mark deleted | Yes conceptually | DELETE /sessions/abc |

Idempotent means repeating the same request has the same intended server state as doing it once. It does not mean the response must be byte-for-byte identical. A second DELETE might return 204 or 404 depending on API convention, but the resource is still gone.

Status codes that matter in interviews

You do not need every HTTP code. Know the practical set.

| Code | Meaning | Use it when | |---|---|---| | 200 OK | Successful request with body | Returning an existing resource or update result | | 201 Created | Resource created | POST /orders creates an order; include Location if useful | | 202 Accepted | Accepted for async processing | Long-running import, export, video processing, payment workflow | | 204 No Content | Successful with no response body | Delete succeeded, update accepted without body | | 400 Bad Request | Malformed request | Invalid JSON or impossible parameter shape | | 401 Unauthorized | Missing/invalid authentication | Token absent or invalid | | 403 Forbidden | Authenticated but not allowed | User lacks permission | | 404 Not Found | Resource not found or hidden | Missing order, or intentionally hide unauthorized existence | | 409 Conflict | State conflict | Duplicate unique value, invalid state transition, version conflict | | 422 Unprocessable Entity | Semantic validation error | Valid JSON but business validation fails | | 429 Too Many Requests | Rate limit | Client exceeded quota; include retry info | | 500/503 | Server error/unavailable | Unexpected failure or temporary outage |

A good answer includes error body shape, not just status code:

{
  "error": {
    "code": "invalid_state_transition",
    "message": "Order cannot be canceled after shipment.",
    "request_id": "req_123",
    "details": [{ "field": "status", "issue": "already_shipped" }]
  }
}

Clients need stable machine-readable codes, not only English strings.

Idempotency for unsafe writes

Idempotency is the most important REST API interview topic for payments, orders, messages, and retries. Networks fail in ambiguous ways: the client may time out after the server created the order. If the client retries a normal POST /orders, you may create two orders.

Use an idempotency key:

POST /orders
Idempotency-Key: 3d6a0b1d-1c4e-4e41-9b67-client-generated

Server behavior:

  1. Client generates a unique key for one intended operation.
  2. Server stores the key with a hash of request parameters and the final response.
  3. If the same key arrives again with the same parameters, return the original result.
  4. If the same key arrives with different parameters, return 409 Conflict or validation error.
  5. Keys expire after a defined retention window.

This pattern is common for payment APIs because duplicate charges are catastrophic. In an interview, say that idempotency keys should be scoped by user/account and endpoint, stored transactionally with the operation, and protected against concurrent duplicate requests.

Pagination, filtering, and sorting

Collection endpoints need explicit pagination. Offset pagination is simple:

GET /orders?limit=50&offset=100

But it can be slow and inconsistent for large changing datasets. Cursor pagination is usually better:

GET /orders?limit=50&cursor=eyJjcmVhdGVkX2F0Ijoi..."

Return:

{
  "data": [ ... ],
  "next_cursor": "...",
  "has_more": true
}

Cursor pagination should use a stable sort key such as (created_at, id) to avoid missing or duplicating items when new rows arrive. Filtering and sorting should be explicit: status=paid, created_after=..., sort=-created_at. Put limits on limit, validate filters, and avoid arbitrary unindexed queries.

Versioning and backward compatibility

Common versioning approaches:

  • URL version: /v1/orders.
  • Header version: Accept: application/vnd.company.v1+json.
  • Date-based versioning for APIs with many clients.

The exact style matters less than compatibility discipline. Do not remove fields, rename fields, or change meanings silently. Add fields in a backward-compatible way. Treat enum expansion carefully because some clients fail on unknown enum values. If you need a breaking change, create a new version and give migration time.

A strong interview line: "I would design responses so clients ignore unknown fields and rely on documented stable fields, then use additive changes whenever possible."

Example: design an orders API

A concise design:

POST /orders
GET /orders/{order_id}
GET /orders?status=paid&limit=50&cursor=...
PATCH /orders/{order_id}
POST /orders/{order_id}/cancel
POST /orders/{order_id}/payments
GET /orders/{order_id}/events

POST /orders creates a draft or pending order. It accepts line items, shipping address ID, and optional coupon. It requires an idempotency key. Success returns 201 Created with the order. Validation failures return 422 for business issues like unavailable SKU, and 409 for conflicts like duplicate client order reference.

PATCH /orders/{id} allows limited mutable fields while the order is still draft. It should reject changes after payment with 409 Conflict or a domain-specific error.

POST /orders/{id}/cancel is a state transition. It checks whether the order is cancelable, records the cancellation reason, releases inventory, and maybe creates a refund. It may return 202 Accepted if cancellation is asynchronous.

GET /orders/{id}/events exposes an audit trail: created, paid, shipped, canceled. This is useful in interviews because it shows you think about debuggability.

Security and permissions

REST design includes auth and authorization. Mention:

  • Authentication via session cookie, OAuth token, or service token depending on client type.
  • Authorization checks on every resource access.
  • Avoid exposing sequential IDs if enumeration is a concern, or enforce strong authorization so enumeration does not matter.
  • Validate input server-side even if clients validate too.
  • Rate limit expensive endpoints and login-like flows.
  • Do not put secrets in URLs because URLs are logged widely.

For multi-tenant APIs, tenant scoping matters. GET /orders/{id} must ensure the order belongs to the caller's tenant, not merely that the ID exists.

Common REST interview traps

Trap: verbs everywhere. Use resource nouns unless a domain action is clearer.

Trap: always returning 200. Status codes help clients handle errors and retries.

Trap: no idempotency on payment/order creation. Retried writes can duplicate real-world actions.

Trap: offset pagination for huge live collections. Cursor pagination is safer at scale.

Trap: unstable error messages. Machine-readable error codes are better contracts than prose.

Trap: leaking authorization details. Sometimes returning 404 for unauthorized resources is safer than revealing existence.

Trap: treating PATCH as magic. Define which fields are patchable and how null values behave.

How to answer common questions

PUT vs PATCH: PUT replaces the resource at a known URL; PATCH applies a partial update. PUT should be idempotent. PATCH can be idempotent depending on the patch semantics.

POST vs PUT for create: Use POST when the server assigns the ID. Use PUT when the client chooses the resource URL and repeating the request should create/replace the same resource.

What status for validation? 400 for malformed request syntax; 422 for semantically valid JSON that fails business validation; 409 for conflicts with current resource state.

How do retries work? Safe reads can retry. Unsafe writes need idempotency keys, transactional storage, and conflict handling.

Prep checklist

Before a REST API interview, practice designing one resource end-to-end:

  • URL structure and resource boundaries.
  • Methods for read, create, update, delete, and state transitions.
  • Request and response examples.
  • Status codes and machine-readable errors.
  • Idempotency key behavior for POST.
  • Pagination and sorting for list endpoints.
  • Authz checks and tenant scoping.
  • Versioning and backward-compatible changes.

The strongest REST API answers are boring in the best way: predictable resources, explicit contracts, safe retries, and clear failure modes. That is what production clients need.

Concurrency, conditional updates, and state transitions

Many REST interviews include a hidden concurrency problem. Two clients may update the same resource at the same time, or a user may submit an action after the resource has changed. A solid API design explains how to avoid lost updates.

One common pattern is optimistic concurrency with a version field or ETag:

GET /orders/123
ETag: "order-v7"

PATCH /orders/123
If-Match: "order-v7"

If the order is now version 8, the server returns 412 Precondition Failed or 409 Conflict, and the client must refetch. This is useful for profile edits, document updates, inventory settings, and admin workflows where overwriting newer data would be harmful.

State transitions should also be explicit. An order might move draft -> pending_payment -> paid -> shipped -> delivered, but not shipped -> draft. The API should validate transitions server-side and return a stable error code when a transition is invalid. For long-running operations, return 202 Accepted with an operation resource:

POST /exports
GET /exports/{export_id}

That keeps clients from holding open requests and gives them a predictable polling or webhook model. In an interview, these concurrency details show that your API can survive real clients, retries, tabs, mobile networks, and background jobs.