What Is a REST API? A Beginner's Guide to RESTful APIs

Learn about REST APIs, how they work, and how to design them effectively in this comprehensive beginner's guide.

REST API illustration

Designing REST APIs That Developers Actually Understand

Most developers can build APIs.

But very few can design them properly.

And when API design goes wrong, everything becomes painful:

  • confusing endpoints
  • inconsistent responses
  • hard-to-maintain backend

In this guide, you'll learn REST API design from scratch not just theory, but how things actually work in real systems.

By the end, you'll be able to design your own APIs confidently.

REST API illustration

What is a REST API?

A REST API (also called a RESTful API) is a way to design APIs using standard web rules.

Instead of building custom communication systems, REST uses HTTP — the same protocol that powers the web.

In REST, everything is treated as a resource (like users, orders, or bookings), and each resource is accessed through a URL.

You interact with these resources using HTTP methods like GET, POST, PUT, PATCH, and DELETE, and the server usually responds with structured data in JSON format.

Because REST is built on top of the web, it's simple to understand, widely supported, and used almost everywhere today.

How a REST API works

REST APIs work through a request-response cycle using HTTP, the same protocol that powers web browsing:

  1. Client initiates a request: Your application makes an HTTP request to an API endpoint.

  2. Request travels over the network: The request moves through the internet over HTTP/HTTPS to reach the server.

  3. Server processes the request: The API validates input and performs logic or functionality.

  4. Database operations: If needed, the server queries or updates the database.

  5. Response generated: The server returns a structured response (often in JSON) with a status code, headers, and a body.

  6. Response returned: The client receives the response and processes it, such as rendering a UI, logging, or making further calls.

REST API request-response cycle

REST API examples

Request:

GET /api/users/123 HTTP/1.1
Host: example.com
Authorization: Bearer Your_Token
Accept: application/json

Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 123,
  "name": "Prakash",
  "email": "prakash@example.com",
  "role": "developer"
}

REST API request and response example

HTTP methods in REST (with examples)

ActionHTTP MethodExample Endpoint
Fetch all resourcesGETGET /api/items
Fetch a single resourceGETGET /api/items/101
Create a new resourcePOSTPOST /api/items
Fully update a resourcePUTPUT /api/items/101
Partially update a resourcePATCHPATCH /api/items/101
Remove a resourceDELETEDELETE /api/items/101
Filter or search dataGETGET /api/items?type=active

HTTP Methods in REST

HTTP methods in REST

GET : Retrieve data

GET is used to fetch data from the server. It is safe, idempotent, and cacheable.

Examples:

GET /api/products
GET /api/products/789
GET /api/users?role=admin&limit=10

POST : Create new resources

POST is used to create a new resource. It is not idempotent and usually returns 201 Created with a Location header.

Example:

POST /api/orders
Content-Type: application/json

{
"product_id": "789",
"quantity": 2,
"customer_id": "12345"
}

PUT : Replace a resource

PUT is used to completely replace an existing resource. It is idempotent, meaning multiple requests give the same result.

Example:

PUT /api/users/12345
Content-Type: application/json

{
  "name": "Aman Sharma",
  "email": "aman@example.com",
  "role": "User"
}

PATCH : Partially update a resource

PATCH is used to update specific fields of a resource. Only the provided fields are modified.

Example:

PATCH /api/users/12345
Content-Type: application/json

{
  "email": "updated@example.com"
}

DELETE : Remove a resource

DELETE is used to remove a resource from the server.

Example:

DELETE /api/orders/456

Understanding REST Responses

Whenever you make a request to a REST API, the server always sends back a response.

This response tells you what happened — whether the request was successful, failed, or needs further action.

What a Response Contains

A typical REST API response has three main parts:

  • Status Code : indicates the result of the request (e.g., 200, 201, 400, 401, 404, 500)

  • Headers : provide additional information about the response (e.g., Content-Type, Cache-Control, rate limiting)

  • Body : contains the actual data returned by the server (usually in JSON format)

    REST API response structure

Example Response

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: max-age=3600
X-RateLimit-Remaining: 95

{
  "id": 123,
  "name": "Prakash",
  "email": "prakash@example.com",
  "role": "developer"
}

What REST APIs Are Used For

REST APIs are used in almost every modern application. Their simplicity and flexibility make them suitable for a wide range of use cases.

Cloud Applications

REST APIs work well in cloud environments because they are stateless and cacheable. This makes it easier to scale applications across multiple servers and regions.

Microservices Architecture

In microservices, each service handles a specific responsibility. REST APIs provide a clear and consistent way for these services to communicate with each other.

Web and Mobile Applications

REST APIs are platform-independent, which means they can be used by:

  • web apps
  • mobile apps
  • IoT devices

This makes them ideal for building modern applications.

Third-Party Integrations

REST APIs make it easy to connect with external systems and services. Because they follow standard patterns, other developers can quickly understand and use them.

Benefits of REST APIs

REST APIs are widely used because they offer several important advantages that make systems easier to build and scale.

Scalability

REST APIs are stateless, which means each request is independent. This allows servers to handle multiple requests efficiently and makes horizontal scaling much easier.

Flexibility

REST APIs support different data formats such as JSON, XML, or plain text. This flexibility allows different types of clients (web, mobile, etc.) to interact with the same API.

Decoupling

REST follows a client-server architecture, meaning the frontend and backend are independent. This allows both sides to evolve, update, and scale without affecting each other.

Lightweight

REST uses standard HTTP methods and usually returns compact data (like JSON). This makes it fast and efficient, especially for mobile and low-bandwidth environments.

REST API Versioning

APIs evolve over time. New features are added, data structures change, and old behavior may need to be updated. To avoid breaking existing applications, APIs use versioning.

Versioning allows you to introduce changes while still supporting older clients.

Common Versioning Strategies

1. URI Versioning

The version is included directly in the URL.

GET /api/v1/users
GET /api/v2/users

2. Header Versioning

The version is specified in the request headers.

GET /api/users
Accept: application/vnd.company.v1+json
  • Keeps URLs clean
  • Slightly harder to test and debug

3. Query Parameter Versioning

The version is passed as a query parameter.

GET /api/users?version=1
  • Easy to implement
  • Generally less preferred

Designing Resource URIs the Right Way

Before writing a single line of code, model your resources — the nouns in your system.

Nouns in, verbs out

Your URI names the thing being acted on. The HTTP method is the action.

✔️ right
GET    /orders
POST   /orders
DELETE /orders/42

❌ wrong
GET    /getOrders
POST   /createOrder
DELETE /removeOrder/42

Keep nesting shallow

Two levels is the practical limit. Deeper nesting creates URLs that break whenever relationships change.

/customers/5/orders           -- maintainable
/customers/5/orders/99/items  -- too deep, avoid this

Never expose your database

Your API is an abstraction over your data — not a direct mirror of your tables. If your table is named tbl_usr_data, that name should never appear in a URL. Design your URIs in business terms.

HTTP Status Codes: The Full Picture

Status codes are the language your API uses to respond. Use them accurately.

2xx  -- it worked
3xx  -- go somewhere else
4xx  -- you made a mistake
5xx  -- we made a mistake
CodeNameWhen to use
200OKStandard success for GET, PUT, PATCH
201CreatedResource created via POST
204No ContentSuccess, no body — use for DELETE
301Moved PermanentlyResource URL changed permanently
304Not ModifiedCached version is still valid
400Bad RequestMalformed request or invalid input
401UnauthorizedNot authenticated
403ForbiddenAuthenticated but not permitted
404Not FoundResource does not exist
409ConflictDuplicate or version mismatch
415Unsupported Media TypeCannot handle that Content-Type
422Unprocessable EntityValid JSON but fails validation
429Too Many RequestsRate limit hit
500Internal Server ErrorSomething broke on the server
503Service UnavailableTemporarily down

A common mistake is returning 200 OK with an error message in the body. Use the correct status code — that is what clients, monitoring tools, and load balancers expect.

Structured Error Responses

A status code tells the client that something went wrong. A structured error body tells them what, why, and where to look for help.

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "error": "validation_failed",
  "message": "The 'email' field is required.",
  "field": "email",
  "requestId": "req-7x2k9p",
  "docs": "https://api.yourapp.com/docs/errors#validation_failed"
}

Every error response should tell the developer:

  • what went wrong (error, message)
  • which request this was (requestId — for support tickets)
  • where to learn more (docs)

Pagination, Filtering, and Sorting

Never return an unbounded collection. If you have 50,000 orders and someone calls GET /orders, your server will either time out or return a 50 MB payload. Always paginate.

Pagination with limit and offset

Pagination with limit and offset

GET /api/orders?limit=25&offset=50
{
  "data": [ ... ],
  "meta": {
    "total": 320,
    "limit": 25,
    "offset": 50
  },
  "_links": {
    "next": "/api/orders?limit=25&offset=75",
    "prev": "/api/orders?limit=25&offset=25"
  }
}

Always cap your limit. If a client requests limit=999999, return your maximum (e.g., 100) or a 400 Bad Request.

Filtering

GET /api/orders?status=shipped&minCost=100

Sorting

GET /api/orders?sort=createdAt&order=desc

Field selection

Let clients request only the fields they need — useful for mobile clients on slow connections:

GET /api/orders?fields=id,status,total

Authentication and Security

Authentication and security

Bearer tokens (OAuth 2.0 / JWT)

GET /api/orders HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

The server validates the token on every request. No session is stored server-side, keeping things stateless and scalable.

API keys

GET /api/orders HTTP/1.1
X-API-Key: sk_live_abc123xyz

Simpler than OAuth. Common for server-to-server integrations where a user is not involved.

Security checklist

- Always use HTTPS — never send tokens over plain HTTP
- Validate every input — never trust client data
- Rate limit all endpoints, especially auth endpoints
- Return 401 when a token is missing or expired
- Return 403 when a resource exists but access is denied
- Never expose stack traces or internal details in error responses
- Use short-lived tokens and refresh tokens, not long-lived secrets

Handling Long-Running Operations

Some operations take too long for a single HTTP round-trip — bulk imports, report generation, video processing. The pattern:

Step 1: Server returns 202 Accepted immediately.

POST /api/reports/generate
Content-Type: application/json

{ "type": "annual-sales", "year": 2025 }
HTTP/1.1 202 Accepted
Location: /api/jobs/abc-123

{
  "jobId": "abc-123",
  "status": "queued"
}

Step 2: Client polls the status endpoint.

GET /api/jobs/abc-123
{
  "status": "in_progress",
  "progress": 62,
  "_links": {
    "cancel": { "href": "/api/jobs/abc-123", "method": "DELETE" }
  }
}

Step 3: When done, return 303 See Other with the result location.

HTTP/1.1 303 See Other
Location: /api/reports/annual-sales-2025

Common Mistakes to Avoid

Verbs in URLs

-- wrong
POST /api/createUser

-- right
POST /api/users

Returning 200 for errors

-- wrong — never do this
HTTP/1.1 200 OK
{ "success": false, "error": "User not found" }

Use 404. That is what it is for.

No pagination

-- wrong
GET /api/orders   -- returns 50,000 records at once

-- right
GET /api/orders?limit=25&offset=0

Leaking internal details

-- wrong
GET /api/tbl_usr_data/123
{ "sql_error": "..." }

-- right
GET /api/users/123
{ "error": "not_found", "message": "User 123 does not exist." }

Inconsistent naming

Pick one style and use it everywhere:

-- inconsistent
/api/userProfile
/api/user_profile

-- consistent (kebab-case is recommended)
/api/user-profiles

The Richardson Maturity Model

A useful way to measure how RESTful your API actually is:

LevelNameWhat it meansExample
0Swamp of POXSingle endpoint, all POST/api with action in body
1ResourcesSeparate URL per resource/orders, /users
2HTTP verbsCorrect methods and status codesGET /orders, 201 on create
3HATEOASResponses include links to next actions_links in every response

Most production APIs sit at Level 2. Level 3 is the ideal but requires deliberate design upfront. Start at Level 2 and evolve.

Wrapping Up

A good REST API feels invisible. Developers can pick it up quickly, the endpoints do what they say, errors are informative, and things just work.

The patterns in this guide are not arbitrary rules — they are conventions that have been battle-tested across millions of APIs. Following them means your API will feel familiar to any developer who has worked with REST before.

Start with clean URIs, correct HTTP methods, and consistent status codes. Add pagination and proper error responses. Layer in auth and versioning. And always design the API you would want to consume yourself.

• Build • Break • Fix • Repeat