In short
A REST API is a way for two programs to talk over HTTP by treating everything as a resource with a URL, and by using the plain HTTP verbs (GET, POST, PUT, PATCH, DELETE) to read and change it. It is the default integration style for Indian web and mobile products: UPI and NPCI interfaces, UIDAI/Aadhaar e-KYC, DigiLocker, GSTN, ONDC (beckn), Razorpay and Paytm payments, Swiggy/Zomato/Ola apps and almost every internal microservice all speak REST over JSON. Universities examine it under web technology, service-oriented architecture and cloud computing papers; placement rounds at TCS, Infosys, Wipro, Accenture, Cognizant, Zoho, Freshworks, Flipkart, Paytm and PhonePe almost always include "design an endpoint", "GET vs POST", "PUT vs PATCH" and "which status code would you return". A fresher who can name the right verb, the right status code and the right URI for a given requirement is usually judged job-ready on back-end basics.
Explained
What REST is, and the six constraints
- REST = REpresentational State Transfer, an architectural *style* defined by Roy Fielding (2000 doctoral thesis), not a protocol or a standard. Anything that obeys its constraints over HTTP is "RESTful".
- Resource: any thing worth naming — a job, an employer, a student, a collection of applications. Identified by a URI (
/jobs/48213). - Representation: the resource's state serialised into a format — JSON (usual), XML, CSV, PDF. The resource is not the JSON; the JSON is one view of it.
- The six constraints:
- Client-server — separate the UI from data storage so each evolves independently.
- Statelessness — every request carries everything needed to understand it; the server keeps no per-client conversation state. This is what lets you put ten identical servers behind a load balancer.
- Cacheability — responses declare whether and for how long they may be reused.
- Uniform interface — the same small set of verbs and status codes for every resource; no
/getJobById?id=5style custom verbs. - Layered system — gateways, proxies, CDNs and firewalls may sit between client and server without either knowing.
- Code-on-demand (optional) — the server may ship executable code (e.g. JavaScript) to the client.
- REST vs "RESTful" in practice: most industry APIs satisfy 1–5 and skip hypermedia; they are commonly called REST anyway.
- Richardson Maturity Model — a marking scheme for how RESTful an API is: Level 0 one URI, one verb (RPC-over-HTTP, SOAP style) → Level 1 many resources, still one verb → Level 2 resources + correct HTTP verbs and status codes (where most real APIs sit) → Level 3 + HATEOAS, where responses carry links telling the client what it may do next.
HTTP methods: safety, idempotency, semantics
- GET — read a resource; safe (no side effects) and idempotent; cacheable; must never carry business meaning in the act of calling it.
- POST — create a subordinate resource or trigger a process; not safe, not idempotent (two calls create two rows). Returns 201 Created with a
Locationheader pointing at the new resource. - PUT — *replace* the resource at a known URI with the body supplied; idempotent — doing it ten times leaves the same state. Fields omitted are treated as cleared.
- PATCH — *partial* update (only the supplied fields change). Not guaranteed idempotent in general (e.g.
{"op":"increment"}), though a field-merge patch usually is. - DELETE — remove the resource; idempotent (the second call finds nothing to delete; return 204 or 404 consistently).
- HEAD — like GET but headers only; used to check existence, size or
Last-Modifiedcheaply. - OPTIONS — ask which methods are allowed; used by browsers for the CORS preflight.
- Idempotency is the single most examined idea here: an operation is idempotent if repeating it has the same effect as doing it once. It matters because networks fail *after* the server has acted — the client cannot tell a lost response from a lost request, so it retries.
- For non-idempotent POSTs (payments, applications), clients send an **
Idempotency-Key** header; the server stores the key with the first result and replays that result for repeats. Razorpay, Stripe and most Indian payment gateways support this pattern.
Status codes and error design
- 1xx informational · 2xx success · 3xx redirection/conditional · 4xx client's fault · 5xx server's fault. The 4xx/5xx split decides who must fix the bug, so getting it right matters.
- Common ones: 200 OK · 201 Created · 202 Accepted (async, work queued) · 204 No Content (successful DELETE/PUT with empty body) · 301/302 moved · 304 Not Modified (conditional GET matched) · 400 Bad Request (malformed/invalid input) · 401 Unauthorized (really *unauthenticated* — no or bad credentials) · 403 Forbidden (authenticated but not permitted) · 404 Not Found · 405 Method Not Allowed · 409 Conflict (duplicate, or version clash) · 410 Gone · 415 Unsupported Media Type · 422 Unprocessable Content (syntax fine, semantics wrong) · 429 Too Many Requests (rate limit) · 500 Internal Server Error · 502 Bad Gateway · 503 Service Unavailable · 504 Gateway Timeout.
- Never return
200 OKwith{"error": "..."}inside — clients, proxies, caches and monitoring all key off the status line. - Return machine-readable errors: a stable
code, a humanmessage, and field-level details. **RFC 9457 (formerly 7807)application/problem+json** is the standard shape:type,title,status,detail,instance. - Include a correlation/request id in every error so support can trace it in logs.
Designing URIs, collections and payloads
- Nouns, not verbs; plural collections:
/jobs,/jobs/48213,/employers/902/jobs. Lowercase, hyphens not underscores, no file extensions, no trailing slash. - Avoid nesting beyond one level —
/employers/902/jobs/48213/applications/7is brittle; prefer/applications/7for the item and/applications?job_id=48213for the filtered collection. - Filtering, sorting, pagination and field selection go in the query string, not the path:
/jobs?city=Kochi§or=it&sort=-posted_at&page=3&per_page=50&fields=title,company,city. - Pagination types: *offset/limit* (
page,per_page) — simple, but deep offsets get slow and rows shift as data changes; *cursor/keyset* (?after=eyJpZCI6NDgyMTN9) — stable and fast at any depth, but no random page jumps. Always return the total (or anextcursor) and aLinkheader. - Versioning: URI path (
/v1/jobs) — most common and most visible; custom header orAcceptmedia type (application/vnd.abl.jobs.v2+json) — purer REST, harder to test in a browser. Rule: additive changes (new optional field) need no new version; removing or renaming a field or changing a type is breaking and does. - Content negotiation: the client's
Acceptheader says what it wants;Content-Typesays what it is sending; respond 406 if you cannot satisfyAccept, 415 if you cannot read the body. - Payload conventions: JSON object (never a bare array) at the top level,
snake_caseorcamelCaseconsistently, ISO-8601 timestamps with timezone (2026-10-29T09:15:00+05:30), money as integer paise plus a currency code ({"amount": 125000, "currency": "INR"}= ₹1,250.00) — never as a float. - HATEOAS example: a response includes
"links": [{"rel":"apply","method":"POST","href":"/jobs/48213/applications"}]so the client discovers actions instead of hardcoding URLs. - Asynchronous work: long jobs return
202 Accepted+ aLocationto a status resource the client polls, or a webhook (the server POSTs to the client's callback URL when done — webhooks must be signed with HMAC and be idempotent at the receiver).
Cross-cutting concerns
- Security (outline only, detailed separately): HTTPS/TLS everywhere; API keys for server-to-server, bearer tokens for user context; authorise *per resource* on the server — never trust an id from the client (an IDOR bug is checking only "is the user logged in?" and not "does record 7 belong to them?"). Validate and whitelist all input; use parameterised queries; never put secrets or PII in URLs (they land in logs and
Referer). - CORS: a browser blocks a cross-origin JavaScript call unless the server returns
Access-Control-Allow-Origin(and for non-simple requests answers anOPTIONSpreflight with allowed methods and headers). CORS is enforced by the browser only — Postman and curl are unaffected, which is why "it works in Postman but not in React" is such a common bug. - Rate limiting and quotas: protect the service with a token bucket or fixed/sliding window; answer 429 with
Retry-Afterand exposeX-RateLimit-Limit/Remaining/Reset. Public Indian APIs (UIDAI, GSTN, DigiLocker, Account Aggregator) all impose quotas and require registered client credentials. - Conditional requests: the server sends
ETag/Last-Modified; the client replays them asIf-None-Match/If-Modified-Sinceand gets 304 (no body).If-Matchgives optimistic concurrency — if another writer changed the row, return 409/412 instead of silently overwriting (the lost-update problem). - Reliability patterns: client timeouts on every call; retry only idempotent/safe calls, with exponential backoff plus jitter; circuit breaker to stop hammering a dead dependency; bulk endpoints to avoid chatty traffic; gzip/brotli compression; HTTP/2 multiplexing.
- Documentation and tooling: OpenAPI (Swagger) 3.x YAML/JSON as the contract — generates interactive docs, client SDKs, server stubs and mock servers; Postman/Insomnia/curl for manual testing;
supertest/pytest+requests/RestAssured for automated tests; an API gateway (AWS API Gateway, Kong, NGINX, Apigee) for auth, throttling, logging and routing in front of many services. - Indian standards and law: NPCI publishes the UPI API specifications; ReBIT specifies the RBI Account Aggregator (FIP/FIU) APIs with consent artefacts; ONDC uses the beckn protocol (asynchronous JSON-over-HTTP with callbacks); API Setu (NeGD) exposes government data APIs; the DPDP Act, 2023 governs personal data handled by such APIs (data minimisation, purpose limitation, consent, breach notification) — its subordinate rules have been rolling out, so check the current notified position before relying on specifics. CERT-In directions require logs to be retained and security incidents reported within 6 hours.
Key points
- REST - an architectural style over HTTP using resources, URIs, representations and the standard verbs; not a protocol.
- Statelessness - no per-client session on the server; each request is self-contained, which makes horizontal scaling possible.
- Uniform interface - same verbs and status codes for every resource; verbs never appear in URIs.
- Safe methods - GET, HEAD, OPTIONS: no state change. Idempotent - GET, HEAD, PUT, DELETE, OPTIONS (and usually PATCH).
- POST is not idempotent - retrying it can double-charge; guard with an
Idempotency-Key. - PUT vs PATCH - PUT replaces the whole resource (omitted fields cleared); PATCH changes only the fields sent.
- 201 Created - returned by POST along with a
Locationheader for the new resource. - 401 vs 403 - 401 means credentials missing or invalid; 403 means valid identity, insufficient rights.
- 400 vs 422 - 400 for malformed/unparseable input; 422 for well-formed but semantically invalid input.
- 429 + Retry-After - the correct answer to a client exceeding its rate limit.
- 4xx vs 5xx - client's fault vs server's fault; never hide errors behind 200.
- Cursor pagination beats offset pagination for large, changing datasets; offset is fine for small, stable ones.
- Versioning - add fields freely; renaming or removing a field is breaking and needs
/v2. - ETag + If-None-Match → 304 saves bandwidth; If-Match gives optimistic concurrency control.
- HATEOAS / Richardson Level 3 - responses carry links to next actions; most real APIs stop at Level 2.
- CORS is a browser-side restriction relaxed by server headers; it is not authentication.
- OpenAPI/Swagger is the machine-readable contract that drives docs, SDKs, mocks and tests.
- Idempotency plus retries plus timeouts plus circuit breakers is what makes a distributed REST call safe.
Formulas and examples
Sequential call latency T ≈ k × (RTT + server_time) ; k = number of round trips, RTT = round-trip time (s)
Little's Law: C = λ × W (C = concurrent in-flight requests, λ = throughput req/s, W = mean latency s)
Transfer time t = payload_bytes / bandwidth_bytes_per_second
Token bucket: time to serve a burst B = (B − C) / r for B > C (C = bucket capacity, r = refill rate req/s)
Reliability: success of a screen needing k calls = (1 − p)k ; with n attempts per call, p_eff = pn
1. Pagination arithmetic. A job portal holds N = 1,24,750 live listings; per_page = 50.
- pages = ⌈124750 / 50⌉ = 2,495 pages exactly.
offsetfor page 100 = (100 − 1) × 50 = 4,950, so the database must scan and discard 4,950 rows before returning 50 — the cost grows linearly with page number.- Keyset alternative:
GET /jobs?after_id=48213&per_page=50→WHERE id > 48213 ORDER BY id LIMIT 50uses the index and costs the same at page 1 and page 2,495.
2. Chatty API (N+1 problem). A mobile app lists 20 jobs, then fetches each employer separately. RTT = 120 ms, server time = 20 ms per call, calls made sequentially.
- Naive: k = 1 + 20 = 21 calls → T = 21 × (120 + 20) = 21 × 140 = 2,940 ms ≈ 2.9 s.
- One expanded call
GET /jobs?limit=20&expand=employertaking 80 ms of server work → T = 120 + 80 = 200 ms. - Speed-up = 2,940 / 200 = 14.7×. Lesson: round trips, not CPU, dominate mobile API latency.
3. Payload size, sparse fieldsets and compression. 100 listings × 1.8 KB = 180 KB of JSON; client on a 4 Mbps connection (4,000,000 / 8 = 500,000 B/s ≈ 488 KB/s; take 512 KB/s for a round figure of 2²⁹/2²⁰).
- Uncompressed: t = 180 / 512 = 0.3516 s = 352 ms.
- gzip at 5:1 → 36 KB: t = 36 / 512 = 0.0703 s = 70 ms → saves 282 ms for one
Content-Encoding: gzipheader. - Add
?fields=title,company,citycutting each record to 0.30 KB → 30 KB raw, ≈ 8 KB gzipped: ~16 ms.
4. Rate limiting. Bucket capacity C = 100, refill r = 10 req/s; a scraper fires B = 250 requests at once.
- First 100 pass immediately; the rest wait: t = (250 − 100)/10 = 15 s. Requests that cannot wait get 429 with
Retry-After: 15. - Quota view: a limit of 1,000 requests/hour. Polling every 10 s = 3,600/10 = 360 req/h → safe. Polling every 2 s = 1,800 req/h → the quota is exhausted after 1,000 × 2 = 2,000 s = 33 min 20 s, and the rest of the hour returns 429. Fix: poll less, use webhooks, or use
If-None-Match(304s usually still count against quota — check the provider's terms).
5. Retries and screen reliability. Each API call fails with probability p = 0.02 (2%); a dashboard needs k = 4 sequential calls.
- No retry: success = 0.98⁴ = 0.92237 → 92.24% (about 1 in 13 loads broken).
- One retry per call (independent failures): p_eff = 0.02² = 0.0004 → per-call success 0.9996 → screen success = 0.9996⁴ = 0.99840 → 99.84%.
- Capacity check with Little's Law: at λ = 2,000 req/s and W = 150 ms, C = 2,000 × 0.15 = 300 requests in flight; if one instance safely handles 50 concurrent requests, you need 300/50 = 6 instances (plus headroom).
| Requirement | Method | URI | Success code |
|---|---|---|---|
| List jobs in Kochi, page 2 | GET | /v1/jobs?city=Kochi&page=2 | 200 |
| Fetch one job | GET | /v1/jobs/48213 | 200 (or 404) |
| Post a new job | POST | /v1/jobs | 201 + Location |
| Replace a job fully | PUT | /v1/jobs/48213 | 200 / 204 |
| Mark a job closed | PATCH | /v1/jobs/48213 | 200 |
| Withdraw a job | DELETE | /v1/jobs/48213 | 204 |
| Apply to a job | POST | /v1/jobs/48213/applications | 201 |
| Start a bulk import | POST | /v1/imports | 202 + status URI |
| REST | SOAP | GraphQL | gRPC | |
|---|---|---|---|---|
| Style | Resources + HTTP verbs | RPC with XML envelope | Single endpoint, query language | RPC over HTTP/2 |
| Format | JSON (any) | XML only | JSON | Protocol Buffers (binary) |
| Contract | OpenAPI (optional) | WSDL (mandatory) | SDL schema | .proto file |
| Over/under-fetching | Common; fix with fields/expand | Common | Client asks for exact fields | Fixed messages |
| Caching | Native HTTP caching | Poor | Hard (POST queries) | Manual |
| Streaming | Limited (SSE/polling) | No | Subscriptions | Bi-directional, native |
| Best for | Public, browser and mobile APIs | Legacy banking/telecom, WS-Security | Rich UIs with varied data needs | Internal, high-volume microservices |
POST /v1/jobs/48213/applications HTTP/1.1
Host: api.abljobs.in
Content-Type: application/json
Authorization: Bearer <token>
Idempotency-Key: 9f2c1b7a-2026-10-29-001
{"student_id": 7741, "resume_id": 55120, "cover_note": "B.Tech CSE, 2027 batch"}
HTTP/1.1 201 Created
Location: /v1/applications/90312
ETag: "a1b2c3"
{"id": 90312, "status": "submitted", "created_at": "2026-10-29T09:15:00+05:30"}
HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json
{"type":"/errors/validation","title":"Validation failed","status":422,
"detail":"resume_id does not belong to student_id",
"errors":[{"field":"resume_id","code":"ownership_mismatch"}],
"request_id":"req_7c41e9"}
Where it is used
- Fintech and payments: UPI/NPCI switch interfaces, Razorpay/PayU/Cashfree order and webhook APIs, RBI Account Aggregator consent and data APIs (ReBIT specs), bank statement and KYC integrations — idempotency keys and HMAC-signed webhooks are mandatory here.
- Government and public digital infrastructure: UIDAI Aadhaar authentication and e-KYC, DigiLocker issued-document APIs, GSTN e-invoice and e-way bill APIs, API Setu, IRCTC and ONDC/beckn marketplaces; Smart City and IoT dashboards consume REST endpoints.
- Product and services companies: every mobile app (Swiggy, Zomato, Ola, Flipkart, PhonePe, Meesho) is a thin client over REST APIs; IT services firms (TCS, Infosys, Wipro, HCLTech, LTIMindtree, Accenture) staff large teams for API integration and legacy SOAP-to-REST modernisation.
- Job roles: back-end developer, API/integration engineer, full-stack developer, SDET/API test engineer (Postman, RestAssured), DevOps engineer managing API gateways, and solution architects writing OpenAPI contracts.
- Internal platform work: microservices, SaaS multi-tenant platforms (Zoho, Freshworks, Chargebee, Zeta), ERP and HRMS connectors, and partner/aggregator APIs with tiered rate limits and API keys.
- Data and AI: model-serving endpoints (
POST /v1/predict), LLM and OCR services, and analytics ingestion APIs are all exposed as REST.
Interview questions
- Q: What makes an API RESTful rather than just HTTP-based? A: It exposes named resources with URIs, uses the standard HTTP verbs and status codes uniformly, is stateless and cacheable, and keeps clients and servers independent; adding hypermedia links reaches the highest maturity level.
- Q: GET or POST for a search with many filters? A: GET is correct because search is safe, idempotent and cacheable; if the filter set is too large or sensitive for a URL, a POST to
/searchesreturning a result resource is the accepted compromise. - Q: Difference between PUT and PATCH? A: PUT replaces the entire resource — fields you omit are cleared — and is idempotent; PATCH applies a partial change to only the fields sent.
- Q: Why does idempotency matter for payments? A: A client that times out cannot tell whether the server processed the charge, so it retries; without an idempotency key the retry creates a second debit.
- Q: 401 or 403 for a user trying to open someone else's application record? A: 403 if they are properly authenticated but not permitted; many APIs return 404 instead to avoid revealing that the record exists.
- Q: What does statelessness forbid, and how do you keep a user logged in then? A: It forbids server-side per-client conversation state between requests; the client sends a credential (token or cookie) with every request, and any shared state lives in a database or cache both servers can read.
- Q: My React app gets a CORS error but Postman works. Why? A: CORS is enforced by browsers only; the server must return
Access-Control-Allow-Origin(and answer theOPTIONSpreflight) for the app's origin — Postman does not apply the policy. - Q: Offset or cursor pagination for 1.2 lakh listings? A: Cursor/keyset, because deep offsets force the database to scan and discard rows and because inserts shift items between pages; offset is acceptable only for small, stable sets needing random page access.
- Q: How do you version an API without breaking existing clients? A: Make only additive changes in place, and introduce
/v2(or a versioned media type) for breaking changes, running both with a published deprecation window andDeprecation/Sunsetheaders. - Q: When would you choose gRPC or GraphQL over REST? A: gRPC for high-volume internal service-to-service calls needing binary speed and streaming; GraphQL when varied clients over-fetch or need many resources per screen; REST for public, browser- and cache-friendly interfaces.
- Q: Which failed requests are safe to retry automatically? A: Only safe or idempotent ones (GET, HEAD, PUT, DELETE), or POSTs protected by an idempotency key — with exponential backoff and jitter, and never on a 4xx other than 429.
- Q: What is HATEOAS and why is it rare? A: Responses include links describing available next actions so clients need not hardcode URLs; it is rare because it adds payload and server complexity while most clients are written against fixed, documented routes anyway.
Common mistakes
- Putting verbs in URIs (
/getAllJobs,/deleteJob?id=5) or doing a destructive action through GET — crawlers and browser prefetch will then delete data. - Returning
200 OKwith an error body, or using 500 for a client's bad input — it breaks monitoring, retry logic and caching. - Using PUT to send only the changed fields, which wipes every omitted field.
- Blindly retrying POSTs without an idempotency key, producing duplicate orders, applications or payments.
- Checking only that the caller is logged in and not that the requested record belongs to them (IDOR), or trusting client-sent ids, prices or roles.
- Chatty designs (one call per row) and unbounded
GET /jobswith no pagination, no limit cap and no compression. - Breaking a live contract — renaming or removing a field without a new version — and shipping without an OpenAPI spec or tests, so clients discover changes in production.
Related topics
- Back-end development with Node.js · Authentication and authorisation: sessions, OAuth and JWT · Caching, queues and CDNs · System design basics for freshers · Containers: Docker and Kubernetes · Web fundamentals: HTML, CSS and JavaScript