REST API Tutorial: Complete Guide for Beginners

Learn REST APIs from scratch β€” what they are, how they work, and how to use them with real code examples

Last updated:

What is a REST API?

A REST API (Representational State Transfer Application Programming Interface) is a standardized way for applications to communicate over the internet. When you check the weather on your phone, book a flight, or log into a website, your app almost certainly makes REST API calls.

Roy Fielding defined REST in his 2000 doctoral dissertation. It became the dominant style for web APIs because it builds on the web infrastructure that already exists (HTTP). REST is also simple to understand and implement.

The Restaurant Analogy

Think of a REST API like a restaurant:

  • Menu = API Documentation: lists what you can order (available endpoints)
  • Your order = HTTP Request: what you want and how you want it
  • Waiter = API: takes your request to the kitchen and brings back the food
  • Kitchen = Server/Database: does the actual work
  • Food = HTTP Response: what you get back (usually JSON data)
GET https://api.example.com/users/1
HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 1,
  "name": "Jane Doe",
  "email": "jane@example.com",
  "role": "admin",
  "created_at": "2026-01-15T10:30:00Z"
}

The 6 REST Constraints

πŸ”Œ

Client-Server

The client (your app) and server (the API) are separate. The client does not need to know how the server stores data. The server does not need to know how the UI works.

πŸ“¦

Stateless

Each request contains all information needed to process it. The server stores no client session state. This makes APIs easier to scale.

⚑

Cacheable

Clients, CDNs, and proxies can cache responses to improve performance. The server uses HTTP headers to indicate what it can cache.

πŸ”—

Uniform Interface

You access all resources the same way, with standard HTTP methods and URLs. This consistency is what makes REST APIs predictable.

πŸ—οΈ

Layered System

The API can have multiple layers (load balancers, caches, security gateways) that the client does not need to know about.

πŸ’»

Code on Demand (Optional)

Servers can optionally send executable code to clients. Rarely used in practice, but allowed by the REST specification.

How REST APIs Work: Request & Response

Every REST API interaction is a request-response cycle. Your application sends an HTTP request. The API sends back an HTTP response.

Anatomy of an HTTP Request

  • Method: what action to perform (GET, POST, PUT, DELETE)
  • URL: which resource to act on (/api/v1/users/123)
  • Headers: metadata about the request (Content-Type, Authorization, Accept)
  • Body: data to send with POST, PUT, PATCH requests (usually JSON)

Anatomy of an HTTP Response

  • Status code: did it succeed? (200 OK, 404 Not Found, 500 Error)
  • Headers: metadata (Content-Type, Cache-Control, rate limit info)
  • Body: the actual data returned (JSON in most REST APIs)
Complete Request
POST /api/v1/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGci...
Accept: application/json

{
  "name": "John Doe",
  "email": "john@example.com"
}
Complete Response
HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/v1/users/124

{
  "id": 124,
  "name": "John Doe",
  "email": "john@example.com",
  "created_at": "2026-03-24T10:30:00Z"
}

Your First REST API Call

Make a real API call right now. We will use JSONPlaceholder β€” a free public API for testing that returns fake but realistic data.

Try it with curl (Terminal)

GET https://jsonplaceholder.typicode.com/users/1
# Run this in your terminal:
curl https://jsonplaceholder.typicode.com/users/1

# Expected response:
{
  "id": 1,
  "name": "Leanne Graham",
  "username": "Bret",
  "email": "Sincere@april.biz",
  "address": {
    "street": "Kulas Light",
    "city": "Gwenborough",
    "zipcode": "92998-3874"
  },
  "phone": "1-770-736-0988 x56442",
  "website": "hildegard.org"
}

Try it with JavaScript fetch

// Works in any browser console or Node.js:
fetch('https://jsonplaceholder.typicode.com/users/1')
  .then(response => {
    console.log('Status:', response.status); // 200
    return response.json();
  })
  .then(data => {
    console.log('User:', data.name); // "Leanne Graham"
    console.log('Email:', data.email);
  })
  .catch(error => {
    console.error('Error:', error);
  });

// Or with async/await (modern JavaScript):
async function getUser(id) {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/users/${id}`
  );
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
  const user = await response.json();
  return user;
}

const user = await getUser(1);
console.log(user.name);

Create a Resource with POST

POST https://jsonplaceholder.typicode.com/posts
curl -X POST https://jsonplaceholder.typicode.com/posts \
  -H "Content-Type: application/json" \
  -d '{
    "title": "My First Post",
    "body": "This is the post content",
    "userId": 1
  }'

# Response (201 Created):
{
  "id": 101,
  "title": "My First Post",
  "body": "This is the post content",
  "userId": 1
}

HTTP Methods β€” The REST Verbs

HTTP methods tell the server what action to perform. Each method has a specific purpose. The correct method makes your API predictable and follows REST conventions.

GET

Read Data

Retrieve a resource or collection. Safe (no side effects) and idempotent (two or more identical calls return the same result).

GET /api/users GET /api/users/123
POST

Create Data

Create a new resource. Returns 201 Created with the new resource in the body and a Location header that points to it.

POST /api/users POST /api/orders
PUT

Replace/Update

Replace a resource entirely (all fields). Idempotent β€” two or more identical calls produce the same result. Requires you to send the complete resource.

PUT /api/users/123
PATCH

Partial Update

Update only the fields you specify. More efficient than PUT when you only need to change one or two fields.

PATCH /api/users/123 {"name": "New Name"}
DELETE

Remove Data

Delete a resource. Returns 204 No Content on success (no body). Idempotent β€” a DELETE request for an already-deleted resource should also return a success response.

DELETE /api/users/123

πŸ’‘ The Golden Rule of HTTP Methods

Use the method that matches your intent. The most common mistake is POST for everything. If you read data, use GET. If you remove data, use DELETE. This makes your API predictable and easy to understand.

See our complete HTTP Methods guide for detailed examples of each method.

HTTP Status Codes β€” What Responses Mean

Status codes tell you whether a request succeeded or failed β€” and why. Always check the status code before you read the response body.

2xx β€” Success

200 OK β€” Request succeeded. The body contains the requested data.
201 Created β€” Resource was created. The body contains the new resource.
204 No Content β€” Success, but no body (common for DELETE).

4xx β€” Client Errors (your mistake)

400 Bad Request β€” Invalid input. Check the error message for details.
401 Unauthorized β€” Missing or invalid authentication. Log in first.
403 Forbidden β€” Authenticated but not allowed. You do not have permission.
404 Not Found β€” Resource does not exist. Check the ID.
429 Too Many Requests β€” Rate limit hit. Wait and try again.

5xx β€” Server Errors (their mistake)

500 Internal Server Error β€” Something broke on the server. Try again later.
503 Service Unavailable β€” Server is down or overloaded. Try again later.

See our complete Status Codes reference for all HTTP codes with examples.

REST API Resources and URLs

In REST, everything is a resource β€” any noun that your application manages: users, orders, products, articles. URLs (Uniform Resource Locators) identify resources.

πŸ“š Use Nouns, Not Verbs

❌ Bad (verb in URL) POST /createUser GET /getUsers
βœ… Good (noun + HTTP method) POST /users GET /users

The HTTP method IS the verb. Do not repeat it in the URL.

πŸ“‚ Collections and Individual Resources

Collection GET /users
Individual resource GET /users/123

Collections use the plural noun. Individual resources add the ID after a slash.

πŸ”— Nested Resources

Orders for user 123 GET /users/123/orders
Specific order for user 123 GET /users/123/orders/456

Nest resources when one belongs to another. Limit nesting to 2 levels deep.

πŸ” Query Parameters for Filtering

Filter + sort + paginate GET /users?status=active&sort=name&page=2

Use query parameters for filtering, sorting, searching, and pagination. Never put filter logic in the URL path.

Working with JSON

JSON (JavaScript Object Notation) is the standard data format for REST APIs. JSON is human-readable, lightweight, and supported natively in JavaScript and most programming languages.

JSON Data Types

  • String: "Hello World" β€” text in double quotes
  • Number: 42 or 3.14 β€” no quotes
  • Boolean: true or false
  • Null: null β€” explicit absence of value
  • Array: [1, 2, 3] or ["a", "b"]
  • Object: {"key": "value"} β€” key-value pairs

Standard Response Envelope

Many APIs use a consistent "envelope" structure to wrap all responses:

GET /api/v1/users
{
  "data": [
    {"id": 1, "name": "Jane"},
    {"id": 2, "name": "John"}
  ],
  "meta": {
    "total": 150,
    "page": 1,
    "per_page": 10
  },
  "links": {
    "next": "/api/v1/users?page=2",
    "prev": null
  }
}

Parsing JSON in JavaScript

// Making an API request and handling JSON:
async function fetchUsers() {
  const response = await fetch('/api/v1/users', {
    headers: {
      'Authorization': 'Bearer YOUR_TOKEN',
      'Accept': 'application/json'
    }
  });

  // Always check for errors before parsing
  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.message || 'Request failed');
  }

  const data = await response.json();
  console.log('Users:', data.data); // the array of users
  console.log('Total:', data.meta.total);
  return data.data;
}

// Sending JSON data (POST/PUT/PATCH):
async function createUser(userData) {
  const response = await fetch('/api/v1/users', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json', // Required!
      'Authorization': 'Bearer YOUR_TOKEN'
    },
    body: JSON.stringify(userData) // Convert object to JSON string
  });

  if (response.status === 201) {
    const newUser = await response.json();
    return newUser.data;
  }
}

Authentication Basics

Most REST APIs require authentication β€” a way to prove who you are. Without it, anyone could read or modify any data. There are three main approaches.

1

API Keys β€” Simplest

A static secret string assigned to your application. Send it with every request. Simple to implement, best for server-to-server calls.

# In a header (preferred):
Authorization: Bearer sk_live_abc123xyz

# Never in the URL:
# ❌ /api/users?api_key=sk_live_abc123xyz
2

JWT Tokens β€” Most Common

JSON Web Tokens. After logging in, you receive a token that expires. Send it with each request. The server verifies it without a database lookup.

# Login to get a token:
POST /api/auth/login
{"email": "you@example.com", "password": "..."}

# Response:
{"access_token": "eyJhbGci...", "expires_in": 3600}

# Use the token:
Authorization: Bearer eyJhbGci...
3

OAuth 2.0 β€” Most Powerful

The industry standard for "Login with Google/GitHub" type flows. Allows users to grant your app limited access to their data on another service.

scope: read:users email profile

Used by Google, GitHub, Stripe, Slack, and virtually every major API.

See our complete Authentication guide for implementation details and security best practices.

REST API Design Principles

These core principles make REST APIs consistent, predictable, and easy to use. These principles help you, whether you build an API or use one.

πŸ”‘

Stateless Requests

Every request must include all information needed to process it. The server never remembers anything between requests β€” no server-side sessions.

πŸ“

Use HTTP Correctly

GET to read, POST to create, PUT or PATCH to update, DELETE to remove. Use the right status codes: 200, 201, 204, 400, 401, 403, 404.

πŸ”’

Version Your API

Include a version in your URL: /api/v1/users. This lets you make breaking changes in v2 without breaking clients on v1.

πŸ“„

Consistent Naming

Use lowercase, hyphens for URLs (/user-profiles). Use consistent casing for JSON keys β€” choose camelCase or snake_case and stick to it.

Ready to design your own API? Read our REST API Design Guide for comprehensive best practices.

Build Your First REST API: A Books API Walkthrough

The best way to understand REST is to build something. We will design a Books API from scratch β€” a simple service that lets you create, read, update, and delete books. Follow along step by step.

Step 1: Design the Resource

Our resource is a Book. Before writing any code, we define the URL structure and what data each book contains:

URL structure:
  GET    /books          β†’ list all books
  POST   /books          β†’ create a book
  GET    /books/{id}     β†’ get one book
  PUT    /books/{id}     β†’ replace a book
  DELETE /books/{id}     β†’ delete a book

Book JSON shape:
{
  "id": 1,
  "title": "The Pragmatic Programmer",
  "author": "David Thomas",
  "isbn": "978-0135957059",
  "published_year": 1999
}

Step 2: GET /books β€” List All Books

GET/books
# curl
curl https://api.example.com/books \
  -H "Authorization: Bearer YOUR_TOKEN"

# Response β€” 200 OK
{
  "data": [
    {"id": 1, "title": "The Pragmatic Programmer", "author": "David Thomas"},
    {"id": 2, "title": "Clean Code", "author": "Robert C. Martin"}
  ],
  "total": 2
}
// JavaScript fetch
const res = await fetch('/books', {
  headers: { 'Authorization': 'Bearer YOUR_TOKEN' }
});
const { data } = await res.json();
console.log(data); // array of books

Step 3: POST /books β€” Create a Book

POST/books
# curl
curl -X POST https://api.example.com/books \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "title": "Designing Data-Intensive Applications",
    "author": "Martin Kleppmann",
    "isbn": "978-1449373320",
    "published_year": 2017
  }'

# Response β€” 201 Created
# Location: /books/3
{
  "id": 3,
  "title": "Designing Data-Intensive Applications",
  "author": "Martin Kleppmann",
  "isbn": "978-1449373320",
  "published_year": 2017
}

Step 4: GET /books/{id} β€” Get One Book

GET/books/3
curl https://api.example.com/books/3

# 200 OK β€” book found
{ "id": 3, "title": "Designing Data-Intensive Applications", ... }

# 404 Not Found β€” book doesn't exist
{ "error": "not_found", "message": "Book with id 99 not found" }

Step 5: PUT /books/{id} β€” Update a Book

PUT/books/3
curl -X PUT https://api.example.com/books/3 \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Designing Data-Intensive Applications",
    "author": "Martin Kleppmann",
    "isbn": "978-1449373320",
    "published_year": 2017
  }'
# All fields required β€” PUT replaces the full resource
# Response β€” 200 OK with updated book

Step 6: DELETE /books/{id} β€” Delete a Book

DELETE/books/3
curl -X DELETE https://api.example.com/books/3 \
  -H "Authorization: Bearer YOUR_TOKEN"

# Response β€” 204 No Content (empty body, delete succeeded)
# Call DELETE again β€” still 204 (idempotent!)

πŸŽ‰ You just designed a complete REST API

This Books API pattern applies to any resource β€” users, products, orders, articles. The structure is always the same: a collection endpoint (/books) and an individual resource endpoint (/books/{id}), combined with HTTP methods for CRUD operations.

REST vs SOAP vs GraphQL β€” Which Should You Use?

REST is not the only way to build APIs. This is how it compares to the two main alternatives.

Feature REST SOAP GraphQL
Protocol HTTP HTTP, SMTP, TCP HTTP
Data format JSON (usually) XML only JSON
Flexibility Fixed endpoints Fixed contract Client-defined queries
Caching Native HTTP caching Difficult Requires extra setup
Learning curve Low High (WSDL, SOAP envelope) Medium
Over-fetching Common Common Eliminated
Best for Most web/mobile APIs Enterprise, banking, legacy Complex, nested data
Used by GitHub, Stripe, Twitter PayPal legacy, Salesforce GitHub v4, Shopify, Meta

Choose REST when…

  • Building a public API that many developers will consume
  • You want simple caching and HTTP semantics
  • Your team is already familiar with HTTP
  • You need broad client/tool support

Choose GraphQL when…

  • Clients need very different subsets of the same data
  • You have complex, deeply nested relationships
  • You want to eliminate multiple round-trips
  • Building a product where the frontend evolves rapidly

See our detailed REST vs GraphQL comparison for a deeper dive.

REST API Glossary

Key terms you will encounter when working with REST APIs.

Endpoint
A specific URL that your API exposes. Example: /api/v1/users is the users endpoint.
Resource
Any noun your API manages β€” a user, product, order, or article. Resources are identified by URLs.
Representation
The format of a resource's data when transferred β€” usually JSON. The same resource can have multiple representations (JSON, XML).
Stateless
The server stores no client state between requests. Every request must carry all the information needed to process it (auth token, session data, etc.).
Idempotent
An operation where calling it multiple times produces the same result. GET, PUT, DELETE are idempotent. POST is not.
Base URL
The root URL for an API. Example: https://api.example.com/v1. All endpoints are relative to this.
Payload
The data body of a request or response. In a POST request, the payload is the JSON object you send to create a resource.
Rate Limiting
Restricting how many requests a client can make in a time window. Returns 429 Too Many Requests when exceeded.
Pagination
Splitting large result sets across multiple pages. Common patterns: offset/limit, cursor-based, and page-based.

Common Beginner Mistakes

These are the mistakes almost every developer makes when first working with REST APIs.

❌ Using verbs in URLs

The HTTP method is the verb. Do not repeat it in the URL path.

BadPOST /createUser
GET /getUserById?id=1
DELETE /deletePost/5
GoodPOST /users
GET /users/1
DELETE /posts/5

❌ Ignoring HTTP status codes

Always return the right status code. Returning 200 OK for an error response confuses clients and breaks monitoring tools.

Bad200 OK: { "success": false, "error": "Not found" }
Good404 Not Found: { "error": "not_found", "message": "User 99 not found" }

❌ Not versioning your API

Without versioning, any breaking change breaks all existing clients. Add /v1/ to your base URL from day one.

Badhttps://api.example.com/users
Goodhttps://api.example.com/v1/users

See our API Versioning guide for strategies and trade-offs.

❌ Not validating input

Always validate request bodies on the server. Never trust client data. Return 422 Unprocessable Entity with field-level errors when validation fails.

Good β€” field-level error response 422 Unprocessable Entity { "errors": [ { "field": "email", "message": "Email is invalid" }, { "field": "age", "message": "Must be 18 or older" } ]}

❌ Storing auth tokens in localStorage

Storing JWTs or API keys in localStorage exposes them to XSS attacks. Use httpOnly cookies for sensitive tokens in browser-based apps.

Next Steps: Your Learning Path

You now understand the fundamentals of REST APIs. Use this recommended path to learn more.

Step 1

HTTP Methods Deep Dive

Learn the nuances of GET, POST, PUT, PATCH, DELETE β€” safe vs idempotent, request/response formats, and real-world examples.

Step 2

Status Codes Reference

Master all HTTP status codes: when to use 201 vs 200, 422 vs 400, and 401 vs 403. Learn how to handle each one on the client side.

Step 3

Authentication & Security

Implement JWT authentication, OAuth 2.0 flows, and API key management. Protect your API from common security vulnerabilities.

Step 4

Best Practices

API design conventions, error handling patterns, pagination, versioning, and everything you need to build production-quality APIs.

Step 5

Real-World Examples

See complete API implementations for Users, Products, Orders, File Uploads, Authentication, and Webhooks with full request/response examples.

Advanced

Design Guide

The complete reference to build production-ready REST APIs: URL design, response structure, versioning, security, and the full design checklist.

Frequently Asked Questions

What is a REST API?

A REST API (Representational State Transfer API) is a standardized way for applications to communicate over HTTP. It uses standard HTTP methods (GET, POST, PUT, DELETE) to perform operations on resources identified by URLs, and returns data β€” usually in JSON format. REST is the dominant API style for web services today, used by companies like Twitter, Stripe, GitHub, and Google.

What is the difference between REST and RESTful?

REST is the architectural style defined by Roy Fielding in 2000. A RESTful API is one that follows the REST constraints: stateless, client-server, cacheable, uniform interface, layered system, and optional code on demand. In practice, the terms are used interchangeably β€” when someone says "REST API," they usually mean a RESTful API.

What format does a REST API use?

REST APIs can technically use any format, but JSON (JavaScript Object Notation) is now the standard. JSON is lightweight, human-readable, and natively supported in JavaScript. Older APIs sometimes use XML, and some specialized APIs use Protocol Buffers (gRPC), but for most modern REST APIs, assume JSON.

How is a REST API different from GraphQL?

REST APIs have multiple endpoints. Each endpoint returns a fixed data structure. GraphQL has a single endpoint where the client specifies exactly what data it wants. REST is simpler and more widely supported. GraphQL is better for complex, nested data requirements and when you need to minimize over-fetching. See our REST vs GraphQL guide for a detailed comparison.