Building Your Learning Module...
Getting things ready for you!
Find videos you like?
Save to resource drawer for future reference!
REST (Representational State Transfer) is an architectural style for building web APIs. A REST API uses HTTP methods (GET, POST, PUT, DELETE) to perform CRUD operations on resources, returning data usually in JSON format.
Everything is a resource (users, posts, products)
/api/users/123Actions performed on resources
GET - RetrievePOST - CreatePUT - UpdateDELETE - RemoveResponse status indicators
200 - Success201 - Created404 - Not Found500 - Server ErrorData exchange format
{
"id": 1,
"name": "John"
}| HTTP Method | CRUD | Purpose | Example |
|---|---|---|---|
GET | Read | Retrieve data | GET /users |
POST | Create | Add new resource | POST /users |
PUT | Update | Replace entire resource | PUT /users/1 |
PATCH | Update | Partial update | PATCH /users/1 |
DELETE | Delete | Remove resource | DELETE /users/1 |
async function getUsers() {
const response = await fetch('https://api.example.com/users');
const users = await response.json();
return users;
}
// Get single user
async function getUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`);
return await response.json();
}async function createUser(userData) {
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(userData)
});
if (!response.ok) {
throw new Error('Failed to create user');
}
return await response.json();
}
// Usage
const newUser = await createUser({
name: 'John Doe',
email: 'john@example.com'
});async function updateUser(id, userData) {
const response = await fetch(`https://api.example.com/users/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(userData)
});
return await response.json();
}
// Usage - must include ALL fields
await updateUser(1, {
name: 'Jane Doe',
email: 'jane@example.com',
age: 25
});async function patchUser(id, updates) {
const response = await fetch(`https://api.example.com/users/${id}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(updates)
});
return await response.json();
}
// Usage - only update specific fields
await patchUser(1, { email: 'newemail@example.com' });async function deleteUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`, {
method: 'DELETE'
});
if (response.ok) {
return { success: true };
}
throw new Error('Failed to delete user');
}
// Usage
await deleteUser(1);Query parameters allow you to filter, sort, paginate, and search data:
// Pagination GET /users?page=2&limit=10 // Filtering GET /users?age=25&status=active // Sorting GET /users?sort=name&order=asc // Searching GET /users?search=john // Multiple filters GET /users?country=USA&role=admin&sort=createdAt
// Method 1: Manual string concatenation
const url = `https://api.example.com/users?page=${page}&limit=${limit}`;
// Method 2: URLSearchParams (Recommended)
const params = new URLSearchParams({
page: 2,
limit: 10,
status: 'active'
});
const url = `https://api.example.com/users?${params.toString()}`;
// Result: https://api.example.com/users?page=2&limit=10&status=active
// Method 3: URL object
const url = new URL('https://api.example.com/users');
url.searchParams.set('page', '2');
url.searchParams.set('limit', '10');
fetch(url);const token = 'your-jwt-token';
fetch(url, {
headers: {
'Authorization': `Bearer ${token}`
}
});Most common for modern APIs
const apiKey = 'your-api-key';
fetch(url, {
headers: {
'X-API-Key': apiKey
}
});Simple authentication method
class APIClient {
constructor(baseURL, token) {
this.baseURL = baseURL;
this.token = token;
}
async request(endpoint, options = {}) {
const url = `${this.baseURL}${endpoint}`;
const headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.token}`,
...options.headers
};
const response = await fetch(url, { ...options, headers });
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await response.json();
}
get(endpoint) {
return this.request(endpoint, { method: 'GET' });
}
post(endpoint, data) {
return this.request(endpoint, {
method: 'POST',
body: JSON.stringify(data)
});
}
}
// Usage
const api = new APIClient('https://api.example.com', 'your-token');
const users = await api.get('/users');
const newUser = await api.post('/users', { name: 'John' });async function apiRequest(url, options) {
try {
const response = await fetch(url, options);
// Handle different status codes
switch (response.status) {
case 200:
case 201:
return await response.json();
case 400:
throw new Error('Bad Request - Check your data');
case 401:
throw new Error('Unauthorized - Login required');
case 403:
throw new Error('Forbidden - No permission');
case 404:
throw new Error('Not Found - Resource doesn\'t exist');
case 500:
throw new Error('Server Error - Try again later');
default:
throw new Error(`HTTP Error: ${response.status}`);
}
} catch (error) {
console.error('API Error:', error.message);
throw error;
}
}1. Hardcoding API URLs - Use environment variables
2. Exposing API keys - Never commit keys to repositories
3. Not handling errors - Always use try-catch
4. Ignoring HTTP status codes - Check response.ok
5. No request timeouts - Use AbortController
// Complete blog post management system
class BlogAPI {
constructor() {
this.baseURL = 'https://api.example.com';
this.token = localStorage.getItem('authToken');
}
// GET - Fetch all posts
async getAllPosts() {
const response = await fetch(
`${this.baseURL}/posts`,
{
headers: {
'Authorization': `Bearer ${this.token}`
}
}
);
if (!response.ok) {
throw new Error('Failed to fetch posts');
}
return await response.json();
}
// POST - Create new post
async createPost(postData) {
const response = await fetch(
`${this.baseURL}/posts`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.token}`
},
body: JSON.stringify(postData)
}
);
if (!response.ok) {
throw new Error('Failed to create post');
}
return await response.json();
}
// PUT - Update entire post
async updatePost(id, postData) {
const response = await fetch(
`${this.baseURL}/posts/${id}`,
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.token}`
},
body: JSON.stringify(postData)
}
);
if (!response.ok) {
throw new Error('Failed to update post');
}
return await response.json();
}
// DELETE - Remove post
async deletePost(id) {
const response = await fetch(
`${this.baseURL}/posts/${id}`,
{
method: 'DELETE',
headers: {
'Authorization': `Bearer ${this.token}`
}
}
);
if (!response.ok) {
throw new Error('Failed to delete post');
}
return { success: true };
}
}
// Usage example
const blog = new BlogAPI();
// Create post
const newPost = await blog.createPost({
title: 'My First Post',
content: 'This is amazing!',
author: 'John Doe'
});POST /posts (Create)
{
"id": 1,
"title": "My First Post",
"content": "This is amazing!",
"author": "John Doe"
}
GET /posts (Read All)
[{ id: 1, title: "My First Post", ... }]
PUT /posts/1 (Update)
{ id: 1, title: "Updated Title", ... }
DELETE /posts/1 (Delete)
{ success: true }
✅ Complete CRUD operations
✅ Proper HTTP methods
✅ Authentication headers
✅ Error handling
GET, POST, PUT, PATCH, DELETE for CRUD
2xx success, 4xx client error, 5xx server error
Bearer tokens or API keys in headers
Always check response.ok and handle errors