REST APIs · Backend Interview Q&A

REST API Interview Questions: Design, HTTP Methods, Status Codes & Versioning

Idempotency and safe methods, the status codes that matter and the ones people misuse, cursor pagination, versioning, authentication, caching and concurrency control, ending with a complete API design round worked end to end.

✍️ Pranjal Jain, Ex-Microsoft · IIT Kanpur 📅 10 October 2026 ⏱ 20 min read
Illustration of request envelopes routed through a glowing switchboard between client devices and servers with status lights
TL;DR
  • REST interviews test judgement: resource modelling, correct methods and status codes, idempotency, pagination, versioning and error design.
  • Know the table: GET, PUT, DELETE are idempotent; POST is not; PATCH is not guaranteed. Make POSTs safe to retry with an Idempotency-Key.
  • Use status codes precisely: 201 + Location for creates, 202 for async work, 401 vs 403, 409 for conflicts, 412 for failed preconditions, 429 with Retry-After.
  • Prefer cursor (keyset) pagination for large or changing collections; offset only for small admin lists.
  • In a design round, walk through resources, endpoints, request and response bodies, errors, auth, pagination, idempotency and versioning, in that order.

Almost every backend interview touches API design. Sometimes it is a direct question ("PUT vs PATCH?"), sometimes it is hidden inside system design ("define the APIs for a ride-hailing service"), and sometimes it is a resume probe ("how did clients of your service handle retries?"). The answers that impress are not definitions; they are decisions with reasons, especially about failure. This guide covers the questions in that order, with real HTTP exchanges, and finishes with a complete API design round for an e-commerce order and payment flow.

REST Fundamentals Interview Questions

Q1. What is REST?

REST (Representational State Transfer) is an architectural style described by Roy Fielding in his 2000 dissertation. Its constraints: client-server separation, statelessness (each request carries everything needed to process it), cacheability (responses declare whether they can be cached), a uniform interface (resources identified by URIs, manipulated through representations, self-descriptive messages, hypermedia), a layered system (proxies, gateways and CDNs can sit in between), and optional code on demand. In practice, "REST API" usually means resource-oriented HTTP + JSON that follows HTTP semantics.

Q2. What does stateless mean, and does it forbid sessions?

The server does not keep client conversation state between requests; each request is self-contained. That lets any server instance handle any request, which is what makes horizontal scaling and load balancing easy. Application data (orders, carts stored in a database) is fine; what REST avoids is server memory of "where this client is in a flow". Auth is carried in every request (a bearer token or a session cookie that maps to a shared store).

Q3. What is a resource vs a representation?

A resource is the concept (order 981). A representation is a particular serialised form of its state (JSON, XML, a PDF invoice), negotiated with Accept and Content-Type headers. GET /orders/981 with Accept: application/pdf could return the invoice for the same resource.

Q4. What is HATEOAS, and do real APIs use it?

Hypermedia as the Engine of Application State: responses include links to related actions, so clients discover what they can do next instead of hard-coding URLs.

{
  "id": "ord_981",
  "status": "PENDING_PAYMENT",
  "links": {
    "self":   { "href": "/v1/orders/ord_981" },
    "pay":    { "href": "/v1/orders/ord_981/payments", "method": "POST" },
    "cancel": { "href": "/v1/orders/ord_981/cancel", "method": "POST" }
  }
}

Honest answer: most public APIs implement it partially at best (pagination links are the common case). It is worth mentioning, and the state-dependent links above (no pay link once paid) are a neat way to show you understand the idea.

Q5. What is the Richardson Maturity Model?

Level 0: one endpoint, everything POSTed (RPC over HTTP). Level 1: multiple resources. Level 2: proper HTTP methods and status codes, where most good APIs sit. Level 3: hypermedia controls (HATEOAS).

HTTP Methods and Idempotency Interview Questions

Q6. Which HTTP methods are safe and which are idempotent?

MethodPurposeSafeIdempotentRequest body
GETRead a resource or collectionYesYesNo (semantics undefined)
HEADGET headers onlyYesYesNo
OPTIONSCapabilities, CORS preflightYesYesRare
POSTCreate in a collection, or trigger a processNoNoYes
PUTReplace (or create at a client-chosen URI)NoYesYes
PATCHPartial updateNoNot guaranteedYes
DELETERemoveNoYesRare

Safe means no intended state change. Idempotent means the effect on the server of N identical requests equals the effect of one. Idempotency is about server state, not the response: a second DELETE /orders/981 may return 404 instead of 204, and it is still idempotent because the order is equally gone. The definitions are in RFC 9110 (HTTP Semantics).

Q7. Why does idempotency matter so much?

Networks fail ambiguously. A client sends a request, the connection drops, and it does not know whether the server processed it. Idempotent requests can be retried blindly by clients, SDKs, proxies and load balancers. Non-idempotent ones (a POST that charges a card) can double-charge. That is why idempotency is the heart of every payment API discussion.

Q8. PUT vs PATCH vs POST?

PUT /v1/users/u_42                 # full replacement: omitted fields are cleared or defaulted
{ "name": "Asha Rao", "email": "asha@example.com", "phone": "+919800000000" }

PATCH /v1/users/u_42               # partial: only these fields change
Content-Type: application/merge-patch+json
{ "phone": "+919811111111" }

POST /v1/users                     # create; server assigns the ID
{ "name": "Ravi", "email": "ravi@example.com" }
-> 201 Created, Location: /v1/users/u_43

PATCH format matters: JSON Merge Patch (RFC 7386) sends a partial object, where null means delete the field. JSON Patch (RFC 6902) sends operations ([{"op":"replace","path":"/phone","value":"..."}]) and can express array edits precisely. A PATCH like {"op":"increment"} is not idempotent.

Q9. How do you make POST idempotent? Design the Idempotency-Key mechanism.

POST /v1/payments
Idempotency-Key: 8f14e45f-ea3b-4c1d-9a6e-2c9d1c5e7b10
{ "order_id": "ord_981", "amount": 49900, "currency": "INR", "method": "upi" }
  1. Client generates a UUID per logical operation (per checkout attempt, not per HTTP attempt) and reuses it on every retry.
  2. Server inserts (merchant_id, key) into an idempotency table with a unique constraint, plus a hash of the request body and status IN_PROGRESS, inside the same transaction as the work, or before it with careful state handling.
  3. Duplicate with the same body while in progress: return 409 (or make the client wait). After completion: return the stored response (same status and body), without re-executing.
  4. Same key, different body: reject with 422 or 409; it is a client bug.
  5. Expire keys after a window (24 hours is common).

Follow-up: idempotency at the edge does not remove the need for idempotent consumers downstream (a Kafka consumer may still see an event twice). This pattern is central to the payment system design.

Q10. How do you model actions that aren't CRUD, like "cancel order"?

Options: a state change via PATCH ({"status": "CANCELLED"}), which works when the transition is simple; or a sub-resource for the action, POST /v1/orders/ord_981/cancellation (or /cancel), when the action has its own inputs (reason, refund mode), side effects and rules. The second is clearer for business operations and easier to authorise separately. Avoid verbs at the top level (/cancelOrder?id=981).

HTTP Status Codes Interview Questions

Q11. Which status codes should every API use correctly?

CodeMeaningUse when
200 OKSuccess with bodyGET, or PUT/PATCH returning the updated resource
201 CreatedResource createdPOST that creates; include Location header
202 AcceptedAccepted for async processingReport generation, bulk import; return a status URL
204 No ContentSuccess, no bodyDELETE, or updates that return nothing
301 / 308Permanent redirect (308 keeps method and body)Moved endpoints
302 / 307Temporary redirect (307 keeps method and body)Temporary moves
304 Not ModifiedCached copy still validConditional GET with If-None-Match
400 Bad RequestMalformed requestInvalid JSON, wrong types
401 UnauthorizedNot authenticatedMissing or invalid token
403 ForbiddenAuthenticated but not allowedUser accessing another merchant's data
404 Not FoundNo such resourceAlso used instead of 403 to avoid revealing existence
405 Method Not AllowedMethod unsupported on resourceDELETE on a collection; include Allow
409 ConflictConflicts with current stateDuplicate unique field, invalid state transition
412 Precondition FailedConditional header failedIf-Match ETag mismatch (lost-update protection)
415 Unsupported Media TypeWrong Content-TypeXML sent to a JSON-only endpoint
422 Unprocessable ContentValid syntax, invalid semanticsValidation failures
429 Too Many RequestsRate limitedInclude Retry-After
500 Internal Server ErrorUnexpected server failureBugs; never for client errors
502 / 503 / 504Bad gateway / unavailable / gateway timeoutUpstream failure, overload or maintenance, upstream timeout

Q12. 401 vs 403?

401: "I don't know who you are" (no token, expired token, bad signature); the client should (re)authenticate, and the response should carry a WWW-Authenticate header. 403: "I know who you are, and you can't do this"; retrying with the same credentials won't help. Despite its name, 401 is about authentication, not authorisation.

Q13. 400 vs 422 vs 409?

400 for syntactically broken requests (unparseable JSON). 422 for well-formed requests that fail validation rules (quantity of -2). 409 for requests that are valid in isolation but conflict with the current state of the resource (cancelling an already-shipped order, registering an email that exists). Consistency across your API matters more than which camp you pick for 400 vs 422.

Q14. Should errors ever return 200 with an error body?

No. Clients, proxies, monitoring and retries all key off status codes. A 200 with {"success": false} breaks caching, hides errors from dashboards and confuses SDKs. Return the right status plus a structured body.

Q15. Design a good error response.

HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json

{
  "type": "https://api.example.com/errors/validation",
  "title": "Request validation failed",
  "status": 422,
  "detail": "2 fields are invalid",
  "instance": "/v1/orders",
  "request_id": "req_7Hq2kd91",
  "errors": [
    { "field": "items[0].quantity", "code": "min", "message": "must be at least 1" },
    { "field": "shipping.pincode", "code": "pattern", "message": "must be a 6-digit PIN code" }
  ]
}

This follows the Problem Details format (RFC 9457): a stable machine-readable type/code for programs, a human message for developers, per-field errors, and a request ID for support. Never leak stack traces or SQL.

Resource and URL Design Questions

Q16. What are good URL naming conventions?

  • Nouns, plural: /orders, /orders/{id}; the method is the verb.
  • Lowercase, hyphenated: /delivery-slots.
  • Nesting for ownership, at most one or two levels: /orders/{id}/items. Deeper relations get their own top-level resources with filters (/shipments?order_id=981).
  • Query parameters for filtering, sorting, pagination, never for identity.
  • No file extensions or verbs: not /getOrders.json.

Q17. Should IDs be sequential integers?

Sequential IDs leak business volume (order 10452 tells a competitor how many orders you have) and invite enumeration attacks. Public APIs commonly use opaque, prefixed IDs (ord_8fK2...) or UUIDs; prefixes make logs and support tickets readable. Time-ordered IDs (UUIDv7, Snowflake-style) keep database indexes efficient; see unique ID generator design.

Q18. Should responses be wrapped in an envelope?

For single resources, return the object directly. For collections, an object wrapper is useful because it leaves room for pagination metadata: {"data": [...], "next_cursor": "..."}. Returning a bare top-level array makes it impossible to add metadata later without a breaking change.

Q19. How do you handle long-running operations?

POST /v1/reports  { "type": "gst-sales", "month": "2026-09" }
-> 202 Accepted
   Location: /v1/report-jobs/job_77
   { "id": "job_77", "status": "QUEUED" }

GET /v1/report-jobs/job_77
-> 200 { "id": "job_77", "status": "SUCCEEDED", "result_url": "https://files.example.com/..." }

Clients poll with backoff, or you notify via a webhook when done. Webhooks need signatures (HMAC of the body with a shared secret plus a timestamp to prevent replay), retries with backoff, and idempotent receivers.

Q20. How do you design bulk operations?

POST /v1/products/batch with an array, returning per-item results (status and error for each) with 200, or 207 Multi-Status in WebDAV-style APIs. Decide and document whether a batch is atomic (all or nothing) or partial; cap the batch size; for very large imports, upload a file and process it asynchronously (Q19).

Pagination, Filtering and Sorting Interview Questions

Q21. Offset vs cursor pagination?

Offset (?page=50&limit=20)Cursor / keyset (?after=eyJpZCI6...&limit=20)
SQLORDER BY created_at DESC LIMIT 20 OFFSET 980WHERE (created_at, id) < (:ts, :id) ORDER BY created_at DESC, id DESC LIMIT 20
Deep page costGrows with offset: DB scans and discards 980 rowsConstant: index seek
Concurrent insertsItems shift: duplicates or skips across pagesStable
Jump to page NYesNo (next/previous only)
Best forSmall admin tables with page numbersFeeds, transaction histories, large collections, infinite scroll

Note the tiebreaker: sorting by created_at alone breaks when two rows share a timestamp, so the cursor encodes (created_at, id) and the index covers both. Encode the cursor opaquely (base64 of JSON, ideally signed) so clients cannot construct or depend on its format.

GET /v1/transactions?limit=20&after=eyJ0cyI6IjIwMjYtMTAtMDlUMTA6MDA6MDBaIiwiaWQiOiJ0eG5fOTkifQ

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

Q22. Should you return a total count?

Only if clients truly need it. COUNT(*) over a large filtered table can cost more than fetching the page itself. Many APIs return has_more instead, or an approximate count, or make the total an opt-in parameter.

Q23. How do you design filtering and sorting?

GET /v1/orders?status=PAID&created_after=2026-10-01&sort=-created_at&limit=50. Whitelist filterable and sortable fields (each needs an index), cap limit (say 100), use ISO 8601 timestamps with time zones, and validate every parameter. For complex search, provide a dedicated search endpoint backed by a search engine rather than turning query strings into arbitrary SQL. Sparse fieldsets (?fields=id,status,amount) reduce payload size for mobile clients.

API Versioning Strategies

Q24. What are the ways to version a REST API?

StrategyExampleProsCons
URI path/v1/ordersExplicit, easy routing, cacheable, testable in a browser"Version" is not a resource; big-bang moves to v2
Query parameter/orders?version=2Easy to addEasy to forget, messy caching
Custom headerApi-Version: 2026-10-01Clean URIs, fine-grained date-based versionsInvisible in links and logs unless you log it
Media typeAccept: application/vnd.shop.v2+jsonMost "RESTful"Harder for clients and tooling

A good answer picks one and explains. URI versioning for the major version is the most common; Stripe popularised date-based versions pinned per account, which lets the API evolve continuously while each client sees a stable contract.

Q25. What counts as a breaking change?

Breaking: removing or renaming a field or endpoint, changing a field's type or meaning, making an optional request field required, adding a new required parameter, changing error codes clients depend on, adding a new enum value that strict clients cannot parse. Non-breaking: adding optional request fields, adding response fields, adding endpoints. Tell clients to ignore unknown fields (the tolerant reader principle) so additions stay safe.

Q26. How do you deprecate an API version?

Announce a timeline, mark responses with Deprecation and Sunset headers (the Sunset header is RFC 8594), publish a migration guide, track usage per client via API keys, contact the heaviest remaining users directly, and only then retire. Optionally run "brownouts" (short scheduled failures) to surface forgotten clients before the final shutdown.

REST API Authentication and Security Questions

Q27. API keys vs OAuth 2.0 vs JWT vs session cookies?

MechanismWhat it isFits
API keyA static secret identifying a client applicationServer-to-server integrations; pair with IP allow-lists and rotation
OAuth 2.0A framework for delegated authorisation that issues scoped access tokensThird-party access to user data ("Sign in with Google", partner apps)
JWTA token format: signed claims, verifiable without a DB lookupAccess tokens between services; keep them short-lived
Session cookieOpaque ID mapping to server-side session stateFirst-party web apps; easy revocation

OAuth and JWT are not alternatives: OAuth defines flows, JWT is one way to encode the tokens. Details in OAuth2 and JWT explained.

Q28. What is the most common API security vulnerability?

Broken object level authorisation (BOLA), first in the OWASP API Security Top 10: the API checks that you are logged in but not that the object belongs to you, so changing /v1/orders/981 to /v1/orders/982 shows someone else's order. Fix: every data access is scoped by the caller's identity (WHERE id = :id AND customer_id = :caller), enforced centrally, and tested. Other top issues: broken authentication, excessive data exposure (returning whole DB rows), missing rate limits, and mass assignment (binding request JSON directly onto models so a client can set "role": "admin").

Q29. How should you rate limit an API?

Per API key or user (and per IP for unauthenticated endpoints like login and OTP), with algorithms such as token bucket or sliding window counters in a shared store like Redis. Return 429 with Retry-After, and expose remaining quota in headers (many APIs use X-RateLimit-Limit/-Remaining/-Reset; an IETF draft standardises RateLimit headers). Full design in rate limiter system design.

Q30. What is CORS and why does my API call fail in the browser but work in Postman?

Browsers block JavaScript from reading cross-origin responses unless the server opts in with Access-Control-Allow-Origin. "Non-simple" requests (JSON bodies, custom headers, PUT/DELETE) trigger a preflight OPTIONS request first. Postman is not a browser, so it ignores CORS. Fix it on the server with an explicit origin allow-list; never reflect arbitrary origins together with Access-Control-Allow-Credentials: true.

Q31. Other security essentials?

  • HTTPS everywhere; HSTS.
  • Validate input against a schema; reject unknown fields to prevent mass assignment.
  • Never put secrets or personal data in URLs (they end up in logs and browser history).
  • Limit request body sizes and pagination limits.
  • Sign webhooks and verify signatures in constant time.
  • Log with request IDs but mask PAN, Aadhaar numbers, tokens and passwords.

Caching and Concurrency Control in REST APIs

Q32. How does HTTP caching work for APIs?

Cache-Control declares policy: public, max-age=300 for shared caching of a product catalogue; private, max-age=60 for user-specific data browsers may cache; no-store for sensitive responses. Validators let clients revalidate cheaply:

GET /v1/products/p_12
-> 200 OK
   ETag: "v42"
   Cache-Control: max-age=60

(after 60 s)
GET /v1/products/p_12
If-None-Match: "v42"
-> 304 Not Modified       (no body; client reuses its copy)

Use Vary: Accept-Encoding, Authorization (as appropriate) so caches do not serve one user's response to another.

Q33. How do you prevent lost updates when two clients edit the same resource?

Optimistic concurrency with ETags and If-Match:

GET /v1/products/p_12          -> ETag: "v42", { "price": 49900 }
PATCH /v1/products/p_12
If-Match: "v42"
{ "price": 44900 }
-> 200 OK, ETag: "v43"         (if still at v42)
-> 412 Precondition Failed     (if someone else changed it first: re-fetch and retry)

Server side, the ETag is often a version column: UPDATE products SET price = ?, version = version + 1 WHERE id = ? AND version = 42; zero rows updated means 412. An API can return 428 Precondition Required to force clients to send If-Match.

Q34. How do you make an API fast?

Avoid N+1 queries behind endpoints (and N+1 API calls from clients; offer ?expand=customer,items for related data), paginate everything, compress responses (gzip or brotli), cache at the CDN and application layers, keep payloads lean, use connection keep-alive and HTTP/2, and move slow work to async jobs (Q19). Measure p95/p99 per endpoint, not averages.

API Design Interview Scenario: Orders and Payments for an E-commerce App

"Design the APIs for checkout in a Flipkart-style app: create an order, pay for it, check its status, cancel it, and list a user's orders." Here is how to run that round.

Step 1: Clarify requirements

  • Clients: mobile apps and web. Authenticated users only.
  • Payments via a gateway (UPI, cards, netbanking) with asynchronous confirmation.
  • Retries must never double-charge or double-create orders.
  • Order history must paginate well for users with years of orders.

Step 2: Resources

orders (with embedded items), payments (an order may have several attempts), and webhooks from the payment gateway.

Step 3: Endpoints

Method and pathPurposeSuccessNotable errors
POST /v1/orders + Idempotency-KeyCreate order from cart contents, reserve stock201 + Location409 out of stock, 422 invalid address
GET /v1/orders/{id}Order details and status200 (ETag)404 (also for other users' orders)
GET /v1/orders?status=&limit=&after=User's orders, newest first, cursor paginated200400 bad cursor
POST /v1/orders/{id}/payments + Idempotency-KeyStart a payment attempt, returns gateway action (UPI intent, redirect URL)201409 order not payable
GET /v1/payments/{id}Poll payment status200404
POST /v1/orders/{id}/cancellationCancel with reason, triggers refund if paid202 (refund is async)409 already shipped
POST /v1/webhooks/payment-gatewayGateway notifies payment outcome200 quickly401 bad signature

Step 4: Request and response bodies

POST /v1/orders
Authorization: Bearer eyJ...
Idempotency-Key: 0b6c1e1e-6a1f-4a3e-bf0e-1f2a9b7c3d55
{
  "items": [ { "sku": "MOB-IPH-128-BLK", "quantity": 1 } ],
  "shipping_address_id": "addr_19",
  "coupon": "DIWALI10"
}

-> 201 Created
Location: /v1/orders/ord_9Xk2
{
  "id": "ord_9Xk2",
  "status": "PENDING_PAYMENT",
  "items": [ { "sku": "MOB-IPH-128-BLK", "quantity": 1, "unit_price": 6990000 } ],
  "amount": { "subtotal": 6990000, "discount": 699000, "total": 6291000, "currency": "INR" },
  "expires_at": "2026-10-10T12:15:00+05:30",
  "created_at": "2026-10-10T12:00:00+05:30"
}

Design choices worth saying out loud: money as integers in the smallest unit (paise) with an explicit currency, never floats; the server computes prices (never trust client-sent prices); timestamps in ISO 8601 with offsets; a reservation expiry so abandoned orders release stock.

Step 5: Status as a state machine

PENDING_PAYMENT ──pay ok──► CONFIRMED ──► SHIPPED ──► DELIVERED │ ▲ │ │ └─pay failed (retry) └─cancel──► CANCELLED ──► REFUND_PENDING ──► REFUNDED └─expires / cancel──► CANCELLED

Invalid transitions return 409. The webhook handler is idempotent (keyed by the gateway's event ID), verifies the HMAC signature, and only moves the order forward. Because webhooks can be delayed or lost, a reconciliation job also queries the gateway for payments stuck in a pending state.

Step 6: Cross-cutting decisions

  • Auth: OAuth access tokens; every query scoped by the caller (BOLA protection).
  • Idempotency: required on both POSTs that create things or move money.
  • Pagination: cursor on (created_at, id).
  • Versioning: /v1; additive changes only within it.
  • Rate limits: per user on order creation, stricter on payment attempts.
  • Observability: request IDs returned in responses and propagated to logs.
✅
What interviewers look for in API design roundsResources named well, correct methods and codes, explicit idempotency for money-moving calls, a pagination strategy with a reason, an error format, authorisation per object, and awareness of async flows (202, webhooks, reconciliation). The most common mistakes: verbs in URLs, floats for money, 200-with-error-body, trusting client-sent prices, and no answer for "what if the client retries?"

REST vs GraphQL vs gRPC: When to Use Which

RESTGraphQLgRPC
Transport and formatHTTP, usually JSONHTTP, single endpoint, JSONHTTP/2, Protocol Buffers (binary)
Data fetchingFixed responses per endpoint; over- or under-fetching possibleClient specifies exactly the fields it needsStrongly typed RPC methods
CachingNative HTTP caching and CDNsHarder (POST to one URL); needs client or persisted-query cachingApplication-level
StreamingSSE, chunked responsesSubscriptionsBuilt-in client, server and bidirectional streaming
Browser supportNativeNativeNeeds gRPC-Web or a proxy
Best forPublic APIs, CRUD services, broad compatibilityFrontends aggregating many sources with varied screensInternal service-to-service calls needing low latency and strict contracts

A common real-world combination: gRPC between internal microservices, REST for public and partner APIs, and GraphQL (or a backend-for-frontend) for complex mobile and web screens. Where gateways fit in that picture is covered in API gateway system design.

Q35. How do you document and test an API?

Describe it with OpenAPI (generate from code or design-first), publish interactive docs, and generate client SDKs from the spec. Test with contract tests (the provider verifies it still satisfies consumers' expectations, for example with Pact), integration tests for each status code path, and a backward-compatibility check in CI that diffs the OpenAPI spec and flags breaking changes before they merge.

REST API design ties together much of backend interviewing. Practise it in your language of choice with the Spring Boot or Node.js interview guides, then take the same thinking into system design, where every high-level design starts with "here are the APIs".

Frequently Asked Questions

Which HTTP methods are idempotent?▾
GET, HEAD, OPTIONS, PUT and DELETE are idempotent: repeating the same request has the same effect on the server as sending it once. POST is not idempotent, and PATCH is not guaranteed to be, since an operation like incrementing a counter changes the result each time. GET, HEAD and OPTIONS are also safe, meaning they should not change server state at all.
What is the difference between PUT and PATCH?▾
PUT replaces the entire resource at the given URI with the representation in the request body, and creates it if the client chooses the URI. PATCH applies a partial modification, such as changing one field. PUT is idempotent by definition; PATCH may or may not be depending on the patch format and operation.
What is the difference between 401 and 403?▾
401 Unauthorized means the request lacks valid authentication credentials, so the client should authenticate and retry; the response should include a WWW-Authenticate header. 403 Forbidden means the server knows who the client is but that identity is not allowed to perform the action, so retrying with the same credentials will not help.
How do you make a POST request idempotent?▾
Have the client send a unique Idempotency-Key header, typically a UUID generated per logical operation. The server stores the key with the request fingerprint and the response; a retry with the same key returns the stored response instead of executing again, and a reuse of the key with a different body is rejected. Payment APIs such as Stripe and Razorpay-style integrations use this pattern.
Should I use offset or cursor pagination?▾
Offset pagination with page and limit is simple and supports jumping to page N, but it gets slower on deep pages and can skip or duplicate items when data changes between requests. Cursor or keyset pagination returns an opaque cursor encoding the last item's sort key, which stays fast at any depth and is stable under inserts. Use cursors for feeds and large or frequently changing collections.
What is the best way to version a REST API?▾
URI versioning such as /v1/orders is the most common because it is explicit, easy to route and easy to test in a browser. Header or media-type versioning keeps URIs clean but is less visible. Whatever you choose, avoid breaking changes inside a version, add fields rather than renaming or removing them, and publish a deprecation timeline before retiring old versions.
When should an API return 422 instead of 400?▾
Use 400 Bad Request when the request is malformed, such as invalid JSON or a wrong content type. Many APIs use 422 Unprocessable Content when the syntax is valid but the content fails validation, such as a negative quantity or an end date before the start date. Either is defensible as long as the API is consistent and the error body explains which fields failed.

Get Ready for API and System Design Rounds

Prepflix's interview program teaches API design, system design and DSA together, with mock interviews modelled on backend loops at Indian product companies.

Explore the Prepflix Course →
Pranjal Jain
Pranjal Jain

Ex-Microsoft SDE · IIT Kanpur · Founder of Prepflix. Helps engineers crack startup and product company interviews across India.