A REST API exposes resources at URLs and lets clients work with them through HTTP methods, with each request carrying everything the server needs. Interviews test five things, the five sections of this page: the basics (methods, safe and idempotent, PUT vs PATCH, statelessness), status codes and error bodies, endpoint design (naming, pagination, versioning), production concerns (caching, concurrent edits, idempotency keys, security, rate limits) and scenario questions. There are 43 questions below.
Save your progress and get the interview checklist PDF
System Design Interview Cheat Sheet: the 7 interview stages, the 10 points a scorecard grades, 12 classic systems. 18 pages. Free with an account.
Here are 43 REST API interview questions with short answers in simple English, for freshers up to senior engineers. Each answer follows the HTTP standards themselves, mainly RFC 9110, and links to the course lesson that teaches the idea behind it.
One resource, many methods, and any server can answerThe request carries everything the server needs, including the token. So the load balancer can send it to any copy of the service, and none of them has to remember the client between calls. That is what stateless means in REST.
One resource, many methods, and any server can answerThe request carries everything the server needs, including the token. So the load balancer can send it to any copy of the service, and none of them has to remember the client between calls. That is what stateless means in REST.
How to answer a REST API question
Follow one request. Say which method it uses and whether it is safe to retry, which status code comes back and why, and what headers the client and any cache in between rely on. Most REST questions are about one of those three things, and the strong answer names the rule from the HTTP standard and the reason for it.
This page is the free part.
The course goes deeper on REST API
₹1,111 in India/$25 everywhere elseonce, for the whole course
The System Design course covers REST API across a run of lessons, not one page. These 4 alone are about 111 minutes of step-by-step reading, 1 of them with code you run in the browser, all with a quiz.
Start here if you are a fresher. These questions check that you know what REST means and how HTTP methods behave.
What is a REST API, in simple words?
REST stands for Representational State Transfer. It is an architectural style that Roy Fielding described in his 2000 doctoral dissertation. A REST API exposes resources, such as a user or an order, each at its own URL, and clients work with them using the standard HTTP methods like GET, POST, PUT, PATCH and DELETE.
The server sends back a representation of the resource, usually JSON today. The client never touches the server's internal objects. It only sees representations and links, which is why the server can change how it stores data without breaking clients.
Fielding lists six. Client and server are separate. Each request is stateless, so it carries everything needed to understand it. Responses say whether they can be cached. The interface is uniform. The system can be layered, so a client cannot tell if it talks to the real server or to a proxy in between. The sixth, code on demand, is optional: the server may send code, such as a script, for the client to run.
The uniform interface has four parts of its own: resources are identified by URLs, resources are changed through representations, messages describe themselves (for example with a Content-Type header), and hypermedia drives the application state, which means responses carry the links to what the client can do next.
REST is the style, the set of constraints. RESTful describes an API that follows those constraints. In daily use, people call almost any JSON over HTTP API with resource URLs a REST API, even if it skips some constraints, most often the hypermedia links.
In an interview it is fine to say this plainly. Most public APIs are resource based HTTP APIs that follow REST in part. Knowing which constraint they skip, and what that costs, shows you understand the style and not only the name.
GET reads a resource. POST asks the server to process the body, most often to create a new item in a collection. PUT replaces the whole state of the resource at that URL with the body you send, and creates it if it does not exist. PATCH applies a partial change. DELETE removes the resource.
Two more come up: HEAD is the same as GET but returns only the headers, which is useful to check size or freshness. OPTIONS asks which methods and features the server supports for a URL, and browsers use it for CORS preflight checks.
Which HTTP methods are safe and which are idempotent?
RFC 9110 defines safe as read only: the client does not ask for any change on the server. GET, HEAD, OPTIONS and TRACE are safe. Idempotent means sending the same request many times has the same intended effect on the server as sending it once. All safe methods are idempotent, and so are PUT and DELETE.
POST and PATCH are not idempotent by definition. RFC 5789 says PATCH is neither safe nor idempotent, though a particular PATCH can be written so that repeating it is harmless. This matters because clients and proxies may retry an idempotent request automatically after a network error, but should not retry a POST blindly.
If DELETE is idempotent, why can the second DELETE return 404?
Idempotency is about the effect on the server, not about the response. The first DELETE removes the item. The second DELETE finds nothing and returns 404 Not Found, but the state of the server is the same as after the first call: the item is gone.
So a client may safely retry a DELETE that timed out. If the retry gets 404, that usually means the first attempt worked. Some APIs return 204 for both calls to keep clients simple. Either choice is fine if it is documented.
PUT sends the complete new state of the resource. Any field you leave out is, in effect, removed or reset, because the body replaces what was there. PATCH sends only the change. RFC 5789 defines the method, and the body format says how to apply it.
Two common PATCH formats are JSON Merge Patch (RFC 7396), where you send the fields to change and null to remove a field, and JSON Patch (RFC 6902), which is a list of operations such as add, remove and replace. Use PUT when the client owns the whole object, and PATCH when many clients edit different fields of a large object.
When do you use POST and when PUT to create something?
Use POST to a collection, such as POST /orders, when the server picks the new id. The server answers 201 Created with a Location header that holds the URL of the new order. Use PUT to a full URL, such as PUT /users/42/avatar, when the client already knows where the resource will live.
The difference matters for retries. PUT to the same URL twice leaves one resource, so it is idempotent. POST to a collection twice can create two orders, which is why payment and order APIs add an idempotency key to POST.
What does stateless mean in REST, and why does it help?
Stateless means the server keeps no memory of the client between requests. Every request carries what the server needs, such as the auth token, the page cursor and the body. The server may still store data in a database. What it does not keep is the conversation.
This is what lets you put many identical servers behind a load balancer and send any request to any of them. A server can crash or be added without anyone losing a session. The cost is that each request is a little larger, because it repeats the context.
How is REST different from SOAP, GraphQL and gRPC?
SOAP is a protocol with an XML envelope and a formal contract (WSDL), common in older enterprise systems. GraphQL gives one endpoint where the client writes a query that names exactly the fields it wants. gRPC calls remote functions defined in Protocol Buffers over HTTP/2, which is compact and fast between services.
REST suits public APIs and anything that benefits from plain HTTP caching and tools like curl. GraphQL suits apps whose screens need many related objects in one trip. gRPC suits internal service to service calls where both sides share the schema. Many companies use REST at the edge and gRPC inside.
Interviewers like status codes because the wrong one breaks clients quietly. Know what each class means and the few that are often mixed up.
What do the five classes of HTTP status codes mean?
1xx is informational, such as 100 Continue. 2xx means success. 3xx means the client must take another step, such as following a redirect or using its cached copy. 4xx means the client made an error, so sending the same request again will not help. 5xx means the server failed to handle a request that may have been valid.
The class is what most clients act on. A client that does not know a specific code treats it like the x00 code of its class, as RFC 9110 says. So an unknown 4xx code is handled like 400.
What should an API return after creating, accepting or deleting something?
201 Created when a new resource exists now, with a Location header that points to it. 202 Accepted when the work has been queued but is not done yet, for example a video that will be processed later. 204 No Content when the action worked and there is nothing to send back, which is common for DELETE and some PUT calls.
A plain 200 OK is right when you return a body, for example the updated object after a PATCH. The aim is that the client can tell what happened from the code alone.
401 Unauthorized really means not authenticated. The request has no valid credentials, and RFC 9110 says the response must include a WWW-Authenticate header that tells the client how to authenticate. 403 Forbidden means the server knows who you are, or does not need to, and still refuses.
Simple rule: a missing or expired token gets 401, so the client should log in or refresh the token. A valid token without permission for this resource gets 403, so logging in again will not help. Some APIs return 404 instead of 403 to hide that a private resource exists at all.
400 Bad Request is for a request the server cannot process because it is malformed, such as broken JSON or a missing required header. 422 Unprocessable Content, which RFC 9110 now defines, is for a request that is well formed and of a supported type, but whose content cannot be processed, such as an end date before the start date.
Many APIs use 400 for both, and that is acceptable if the error body explains the problem field by field. What matters most is being consistent across the whole API.
What do 409 Conflict and 412 Precondition Failed mean?
409 Conflict means the request clashes with the current state of the resource, for example creating a user with an email that already exists, or moving an order that is already shipped. The body should say what the conflict is so the client can fix it.
412 Precondition Failed is the answer to a conditional request. If the client sent If-Match with an old ETag and someone else changed the resource since, the server refuses with 412. This is how REST APIs stop two people from overwriting each other's edits.
What does 429 Too Many Requests mean, and what should come with it?
429 is defined in RFC 6585. It means this client has sent too many requests in a given time, so the server is rate limiting it. It is a 4xx code because the fix is on the client side: slow down.
Send a Retry-After header, either as a number of seconds or as a date, so a well behaved client waits the right amount of time instead of retrying at once. Without it, many clients retry together and make the overload worse.
What is the difference between 500, 502, 503 and 504?
500 Internal Server Error means the server hit an unexpected problem, often a bug. 502 Bad Gateway comes from a proxy or gateway that got an invalid response from the server behind it. 503 Service Unavailable means the server cannot handle the request right now, usually overload or maintenance, and it can send Retry-After. 504 Gateway Timeout means a proxy or gateway did not get a reply from the server behind it in time.
These codes tell you where to look. A 502 or 504 points at the link between the gateway and the service, a 503 at capacity, and a 500 at the code itself.
Use one shape for every error. RFC 9457, Problem Details for HTTP APIs, defines a standard one with the media type application/problem+json. Its members are type (a URL that names the kind of problem), title (a short summary), status (the HTTP code), detail (what went wrong this time) and instance (which request or resource it was about). You may add your own fields, such as a list of invalid fields.
Keep the status code in the HTTP response as well, never only in the body. Do not leak stack traces or SQL errors to the client. Log them on the server with a request id, and put that id in the error so support can find it.
These questions check whether you can design endpoints that stay easy to use as the API grows.
How do you name REST endpoints?
Use nouns for resources and let the HTTP method be the verb: GET /orders, POST /orders, GET /orders/42. Use plural collection names, lowercase words and hyphens. Avoid verbs in the path such as /getOrders or /createOrder, because the method already says that.
Nest only to show real ownership, and only one level deep, such as /orders/42/items. For actions that do not fit create, read, update or delete, a common choice is a sub resource such as POST /orders/42/cancel, or a state change through PATCH with status set to cancelled.
How do you support filtering, sorting and field selection?
Use query parameters on the collection, because they narrow the same resource rather than naming a new one: GET /orders?status=shipped&sort=-created_at&fields=id,total. Document which fields can be filtered and sorted, and back those with database indexes.
Put limits in from day one. Cap the page size, reject sorting on fields you have no index for, and validate every parameter. An open filter on a large table is an easy way for one client to slow down the database for everyone.
Offset pagination uses ?limit=20&offset=40. It is simple and lets a user jump to page 50. But the database still walks past every skipped row, so deep pages get slow, and if rows are added while someone pages, they see items twice or miss some.
Cursor pagination returns an opaque token that points just after the last item, and the next request sends it back: ?limit=20&after=token. The query uses an indexed column such as created_at plus id, so every page costs about the same and new rows do not shift the pages. Return the next link in the body or in a Link header with rel="next", as RFC 8288 defines.
The common ways are a version in the path (/v1/orders), a version in a header, or a version in the media type through the Accept header. The path is the easiest to see, test and route. Headers keep URLs stable but are easier to forget.
More important than the method is the rule behind it: adding an optional field or a new endpoint does not need a new version, while removing or renaming a field, or changing its meaning, does. Clients should also ignore fields they do not know. With those two habits, most changes never need a new version at all.
The client says which formats it can accept with the Accept header, for example Accept: application/json. The server picks one it supports and labels the reply with Content-Type. If it supports none of them, it can answer 406 Not Acceptable.
For request bodies it works the other way. The client sends Content-Type, and if the server does not support that format it answers 415 Unsupported Media Type. The same idea covers language with Accept-Language and compression with Accept-Encoding.
HATEOAS means hypermedia as the engine of application state. The response includes links to the actions the client can take next, so an order that can still be cancelled carries a cancel link, and a shipped order does not. The client follows links instead of building URLs by hand.
It is part of Fielding's uniform interface, but most public JSON APIs use it only lightly, for example for pagination links. Give the honest answer: it makes clients less tied to URL layouts, but it needs clients written to follow links, and most are not.
How do you design an endpoint for a task that takes minutes?
Do not keep the HTTP connection open for minutes. Accept the request, put the work on a queue and answer 202 Accepted with a Location header pointing to a status resource, such as /exports/77. The client checks that URL, and when the job is done it shows the result or a link to it.
If clients can receive calls, offer a webhook as well, so they do not have to poll. Make the start request safe to retry with an idempotency key, so a timeout does not start the same export twice.
How do you let clients create or update many items at once?
Add a bulk endpoint, such as POST /orders/batch, that takes a list and returns one result per item, because some items may succeed and others fail. Decide and document whether the batch is all or nothing, or per item. Put a limit on the batch size.
A batch saves round trips, which matters for mobile clients. But a very large batch holds a server thread and a database transaction for a long time, so past a certain size an asynchronous job with 202 Accepted is the better design.
One screen needs data from five endpoints. What do you do?
Five sequential calls on a phone network is slow. Options: let the client ask for related data in one call with an include or expand parameter, add a backend for frontend, which is a small service built for one client type that calls the others and returns exactly what the screen needs, or use GraphQL for that client.
The backend for frontend keeps the public REST resources clean and moves the many calls inside the data centre, where each one is fast. Say which you pick and why.
Senior questions are about what happens with real traffic: retries, caches, concurrent edits and attackers.
How does HTTP caching work for a REST API?
The server sets Cache-Control on the response. For example, Cache-Control: max-age=60 lets the browser or a CDN reuse the response for 60 seconds, private keeps it out of shared caches, and no-store forbids keeping it at all. RFC 9111 defines these rules.
After the copy goes stale, the client can revalidate instead of downloading again. It sends If-None-Match with the ETag it has, which is a version tag for the representation. If nothing changed, the server answers 304 Not Modified with no body. Only safe requests such as GET are normally cached, and anything that differs per user must be private or not cached.
Two users edit the same record at once. How do you stop one from overwriting the other?
Use optimistic concurrency with ETags. The client reads the resource and gets its ETag. When it saves, it sends If-Match with that ETag. If someone else saved first, the ETag has changed, so the server refuses with 412 Precondition Failed, and the client reloads and tries again.
A server can require this by answering 428 Precondition Required, from RFC 6585, to any update that comes without If-Match. Inside the database the same check is often a version column: update the row only where version equals the one the client read.
How do you make a POST safe to retry, for example a payment?
The client creates a unique key for the action, such as a UUID, and sends it in a header, usually called Idempotency-Key. On a retry it sends the same key. The server saves the key with the result of the first attempt, and when the key comes again it returns the saved result instead of doing the work twice.
Store the key and the result in the same transaction as the work, give keys an expiry, and refuse a reused key with a different body. The header is being standardised in an IETF draft, and payment providers already use the pattern.
A retried POST with the same idempotency key charges the card oncePOST is not idempotent by itself. The client makes one key per action and sends it on every retry. The server stores the first result under that key and returns it again, so a retry after a lost reply does not create a second payment.
Use HTTPS everywhere, so tokens and data are encrypted in transit. Authenticate every request, usually with a bearer token in the Authorization header, such as an OAuth 2.0 access token or a signed JWT, or with an API key for server to server use. Check authorisation on every resource, not only at login: user 7 must not read /orders/42 just by changing the number.
Then validate all input, limit request size and rate, keep secrets out of URLs because URLs end up in logs, and log access with a request id. Most API breaches come from a missing authorisation check on one endpoint, not from broken encryption.
An API key is a long secret that identifies a calling application. It is simple and fits server to server calls from a known customer. It usually does not expire on its own and does not say which user is acting.
An OAuth access token is issued after a user or client authenticates, is short lived, and carries scopes that limit what it can do. Use OAuth when an app acts for a user, or when you need fine grained and short lived access. Many APIs offer both.
What is CORS, and why does the browser send an OPTIONS request?
Browsers stop a script on one origin from reading responses from another origin unless that server allows it. CORS, defined in the Fetch standard, is how the server allows it, with headers such as Access-Control-Allow-Origin.
For requests that are not simple, such as a PUT or a JSON body with a custom header, the browser first sends an OPTIONS preflight request to ask whether the real request is allowed. CORS protects users in browsers. It does not protect your API from curl or other servers, so it is never a replacement for authentication.
Pick the key to limit on, such as the API key or user id, and an algorithm, such as a token bucket, which allows short bursts but holds a steady average. Keep the counters in a shared fast store such as Redis so every server sees the same count, and enforce the limit at the gateway.
Return 429 with Retry-After when a client is over its limit, and tell well behaved clients how much they have left, so they can slow down before they hit the wall.
Write an OpenAPI description, a machine readable file that lists every path, method, parameter, request body, response and error. From it you can generate reference docs, client libraries and request validation, and you can check in CI that a change did not break the contract.
Add what a generated reference cannot say: how to authenticate, the rate limits, how pagination and errors work, and a short example for each common task. Good docs reduce support tickets more than any other single thing.
Announce a date, then tell clients in every response. RFC 9745 defines a Deprecation header that marks a resource as deprecated, and RFC 8594 defines a Sunset header that says when it will stop working. Add a Link to the migration guide.
Track which clients still call the old version, contact them directly, and only switch it off after the traffic has really dropped. Semantic versioning helps everyone understand which changes break things and which do not.
These are the questions where there is no single right answer. Say the trade-off out loud.
A client sent POST /payments and got a timeout. Did the payment happen?
The client cannot know. The request may have failed before the server saw it, or the payment may have gone through and only the reply was lost. That is why retrying a plain POST is dangerous.
The fix is designed in advance: the client sends an idempotency key, retries with the same key, and the server returns the stored result if the first attempt finished. The client can also look up the payment by its own reference before trying again.
GET /orders became slow as the table grew. How do you fix it?
First measure: is it the query, the payload size or the number of calls? Common fixes are cursor pagination instead of deep offsets, an index that matches the filter and sort, a cap on page size, and returning only the needed fields.
If many clients ask for the same data, add caching with Cache-Control and ETags, or a cache in front of the database. If one screen makes many calls, combine them. Fix the biggest measured cost first.
You must rename a field that thousands of clients use. How?
Do not rename it in place. Add the new field next to the old one and fill both. Mark the old one as deprecated in the docs and the OpenAPI file, and measure how many clients still read it.
Once usage is near zero, remove it in a new version or after the sunset date you announced. Adding is safe and removing is a breaking change, so every rename is really an add followed, much later, by a remove.
Many services each expose their own REST API. How do you present one API to the outside?
Put an API gateway in front. It gives one host name, checks tokens, applies rate limits, routes each path to the right service and collects logs and metrics in one place. Services behind it can change without clients noticing.
Keep business logic out of the gateway, or it becomes a bottleneck that every team must change. The full walkthrough covers routing, auth, limits and how the gateway itself scales.
Would you use REST or gRPC between two internal services?
If both services are yours, call each other often and need low latency, gRPC is a strong choice: a shared schema, compact binary messages, HTTP/2 connections and streaming. If the API is also used by browsers, partners or tools like curl, REST is easier to debug, cache and explain.
Many teams use both: REST, or GraphQL, at the edge for outside clients and gRPC inside. Say what you are optimising for: speed between services, or ease of use for people outside.
When clients need many related objects in different shapes, such as a mobile app and a web app with very different screens. One GraphQL query can fetch exactly those fields in one trip, which avoids both over fetching and many round trips.
The cost is that plain HTTP caching works less well because most queries are POSTs to one URL, and one expensive query can load the servers, so you need query cost limits. For simple resource APIs and public APIs, REST is usually simpler.
Which response headers would you add to an API for safety?
Strict-Transport-Security so browsers only use HTTPS, X-Content-Type-Options: nosniff so a browser does not guess a different type than the Content-Type you sent, and correct Cache-Control on anything private so a shared cache never stores one user's data for another.
Also return precise Content-Type headers, and send CORS headers only for the origins you trust. These are cheap and close whole classes of mistakes.
Every answer on this page comes from our System Design course: 770 lessons on databases, caching, scaling, messaging and reliability, each drawn step by step. You learn why the answer is right, which is what an interviewer checks with the second question. 18 lessons are free to read, with no card needed.
These questions are a start. The interview asks more.
Get all 200 questions in the System Design and Distributed Systems pack
Each question has why it is asked, a full answer, what the interviewer listens for, the follow-ups, the common mistakes and a diagram (268 diagrams in all). A PDF you keep, junior to staff level.
It covers API design, idempotency keys, rate limiting, pagination and versioning, and how an API gateway fits in front of many services.
India: UPI, cards or netbanking through Razorpay. Elsewhere: card or PayPal. Download at once from My packs.
NEWSystem Design Hands-On
Included in the System Design course: real systems, built live
Postgres Sharding: Complete Hands-On (PgBouncer + Citus). 2 h 36 min and 20 chapters: one PostgreSQL loaded until it breaks, then four shards behind a router you write, PgBouncer and Citus, with the 139-page slide deck. The first 15 minutes are free to watch.