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
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)
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)
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"
}
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)
# 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
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.
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
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
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
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"}
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
4xx β Client Errors (your mistake)
5xx β Server Errors (their mistake)
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
POST /createUser
GET /getUsers
POST /users
GET /users
The HTTP method IS the verb. Do not repeat it in the URL.
π Collections and Individual Resources
GET /users
GET /users/123
Collections use the plural noun. Individual resources add the ID after a slash.
π Nested Resources
GET /users/123/orders
GET /users/123/orders/456
Nest resources when one belongs to another. Limit nesting to 2 levels deep.
π Query Parameters for Filtering
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:
42or3.14β no quotes - Boolean:
trueorfalse - 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:
{
"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.
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
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...
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
# 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 booksStep 3: POST /books β Create a Book
# 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
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
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 bookStep 6: DELETE /books/{id} β Delete a Book
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/usersis 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.
POST /createUserGET /getUserById?id=1DELETE /deletePost/5POST /usersGET /users/1DELETE /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.
200 OK: { "success": false, "error": "Not found" }404 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.
https://api.example.com/usershttps://api.example.com/v1/usersSee 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.
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.
HTTP Methods Deep Dive
Learn the nuances of GET, POST, PUT, PATCH, DELETE β safe vs idempotent, request/response formats, and real-world examples.
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.
Authentication & Security
Implement JWT authentication, OAuth 2.0 flows, and API key management. Protect your API from common security vulnerabilities.
Best Practices
API design conventions, error handling patterns, pagination, versioning, and everything you need to build production-quality APIs.
Real-World Examples
See complete API implementations for Users, Products, Orders, File Uploads, Authentication, and Webhooks with full request/response examples.
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.