🔌 RESTful APIs

Connect Frontend and Backend Seamlessly

👋 Welcome to RESTful APIs!

REST APIs are the backbone of modern web applications. They allow your frontend to communicate with your backend, enabling data exchange and functionality across different systems.

Understanding APIs is essential for both frontend and backend developers!

🤔 What is a REST API?

REST (Representational State Transfer) is an architectural style for designing networked applications. A REST API is a way for different software applications to communicate over HTTP.

Think of it like a restaurant:

The waiter (API) is the interface between you and the kitchen!

🎯 REST Principles

🔗

Client-Server

Separation between frontend and backend

🔄

Stateless

Each request contains all needed information

📦

Cacheable

Responses can be cached for performance

🎨

Uniform Interface

Consistent way to interact with resources

📝 HTTP Methods (CRUD Operations)

GET

Read Data

Retrieve information from the server

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

Use for: Fetching data, viewing resources

POST

Create Data

Send new data to the server

POST /api/users Body: { "name": "John" }

Use for: Creating new resources

PUT

Update Data

Update existing data on the server

PUT /api/users/123 Body: { "name": "Jane" }

Use for: Updating entire resources

DELETE

Delete Data

Remove data from the server

DELETE /api/users/123

Use for: Deleting resources

📊 HTTP Status Codes

2xx Success

  • 200 OK: Request succeeded
  • 201 Created: Resource created
  • 204 No Content: Success, no data returned

4xx Client Errors

  • 400 Bad Request: Invalid request
  • 401 Unauthorized: Authentication required
  • 404 Not Found: Resource doesn't exist

5xx Server Errors

  • 500 Internal Server Error: Server problem
  • 503 Service Unavailable: Server down

🔧 Building a REST API (Node.js/Express)

Complete CRUD API Example

const express = require('express'); const app = express(); // Middleware app.use(express.json()); // In-memory data store (use database in production) let users = [ { id: 1, name: 'John Doe', email: 'john@example.com' }, { id: 2, name: 'Jane Smith', email: 'jane@example.com' } ]; // GET - Get all users app.get('/api/users', (req, res) => { res.json(users); }); // GET - Get single user app.get('/api/users/:id', (req, res) => { const user = users.find(u => u.id === parseInt(req.params.id)); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json(user); }); // POST - Create new user app.post('/api/users', (req, res) => { const { name, email } = req.body; // Validation if (!name || !email) { return res.status(400).json({ error: 'Name and email are required' }); } const newUser = { id: users.length + 1, name, email }; users.push(newUser); res.status(201).json(newUser); }); // PUT - Update user app.put('/api/users/:id', (req, res) => { const user = users.find(u => u.id === parseInt(req.params.id)); if (!user) { return res.status(404).json({ error: 'User not found' }); } const { name, email } = req.body; if (name) user.name = name; if (email) user.email = email; res.json(user); }); // DELETE - Delete user app.delete('/api/users/:id', (req, res) => { const index = users.findIndex(u => u.id === parseInt(req.params.id)); if (index === -1) { return res.status(404).json({ error: 'User not found' }); } users.splice(index, 1); res.status(204).send(); }); app.listen(3000, () => { console.log('API running on http://localhost:3000'); });

💻 Consuming APIs (Frontend)

Using Fetch API (JavaScript)

// GET Request async function getUsers() { try { const response = await fetch('http://localhost:3000/api/users'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const users = await response.json(); console.log(users); } catch (error) { console.error('Error fetching users:', error); } } // POST Request async function createUser(userData) { try { const response = await fetch('http://localhost:3000/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(userData) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const newUser = await response.json(); console.log('User created:', newUser); } catch (error) { console.error('Error creating user:', error); } } // PUT Request async function updateUser(id, userData) { try { const response = await fetch(`http://localhost:3000/api/users/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(userData) }); const updatedUser = await response.json(); console.log('User updated:', updatedUser); } catch (error) { console.error('Error updating user:', error); } } // DELETE Request async function deleteUser(id) { try { const response = await fetch(`http://localhost:3000/api/users/${id}`, { method: 'DELETE' }); if (response.ok) { console.log('User deleted successfully'); } } catch (error) { console.error('Error deleting user:', error); } } // Usage getUsers(); createUser({ name: 'Alice', email: 'alice@example.com' }); updateUser(1, { name: 'John Updated' }); deleteUser(2);

Using Axios (Popular Library)

// Install: npm install axios import axios from 'axios'; const API_URL = 'http://localhost:3000/api'; // GET Request const getUsers = async () => { try { const response = await axios.get(`${API_URL}/users`); console.log(response.data); } catch (error) { console.error('Error:', error.response?.data || error.message); } }; // POST Request const createUser = async (userData) => { try { const response = await axios.post(`${API_URL}/users`, userData); console.log('User created:', response.data); } catch (error) { console.error('Error:', error.response?.data || error.message); } }; // PUT Request const updateUser = async (id, userData) => { try { const response = await axios.put(`${API_URL}/users/${id}`, userData); console.log('User updated:', response.data); } catch (error) { console.error('Error:', error.response?.data || error.message); } }; // DELETE Request const deleteUser = async (id) => { try { await axios.delete(`${API_URL}/users/${id}`); console.log('User deleted'); } catch (error) { console.error('Error:', error.response?.data || error.message); } };

🔐 API Authentication

⚠️ Secure Your APIs!

Always implement authentication and authorization for sensitive endpoints.

JWT Authentication Example

// Backend - Generate JWT const jwt = require('jsonwebtoken'); app.post('/api/login', (req, res) => { const { email, password } = req.body; // Verify credentials (check database) const user = users.find(u => u.email === email); if (!user) { return res.status(401).json({ error: 'Invalid credentials' }); } // Generate token const token = jwt.sign( { userId: user.id, email: user.email }, 'your-secret-key', { expiresIn: '24h' } ); res.json({ token }); }); // Middleware to verify token const authenticate = (req, res, next) => { const token = req.headers.authorization?.split(' ')[1]; if (!token) { return res.status(401).json({ error: 'No token provided' }); } try { const decoded = jwt.verify(token, 'your-secret-key'); req.user = decoded; next(); } catch (error) { res.status(401).json({ error: 'Invalid token' }); } }; // Protected route app.get('/api/profile', authenticate, (req, res) => { res.json({ user: req.user }); }); // Frontend - Using token const login = async (email, password) => { const response = await fetch('http://localhost:3000/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); const { token } = await response.json(); localStorage.setItem('token', token); }; const getProfile = async () => { const token = localStorage.getItem('token'); const response = await fetch('http://localhost:3000/api/profile', { headers: { 'Authorization': `Bearer ${token}` } }); const profile = await response.json(); console.log(profile); };

💡 API Best Practices

REST API Best Practices:

API Versioning

// Version in URL app.get('/api/v1/users', (req, res) => { /* ... */ }); app.get('/api/v2/users', (req, res) => { /* ... */ }); // Version in Header app.get('/api/users', (req, res) => { const version = req.headers['api-version']; if (version === '2') { // V2 logic } else { // V1 logic } });

Pagination Example

app.get('/api/users', (req, res) => { const page = parseInt(req.query.page) || 1; const limit = parseInt(req.query.limit) || 10; const startIndex = (page - 1) * limit; const endIndex = page * limit; const results = {}; if (endIndex < users.length) { results.next = { page: page + 1, limit: limit }; } if (startIndex > 0) { results.previous = { page: page - 1, limit: limit }; } results.data = users.slice(startIndex, endIndex); results.total = users.length; res.json(results); }); // Usage: GET /api/users?page=2&limit=10

🛠️ API Testing Tools

Postman

Most popular API testing tool

  • Test all HTTP methods
  • Save requests
  • Automated testing
  • Team collaboration

Insomnia

Clean, simple interface

  • REST and GraphQL
  • Environment variables
  • Code generation
  • Free and open source

Thunder Client

VS Code extension

  • Built into VS Code
  • Lightweight
  • Easy to use
  • Collections support

cURL

Command-line tool

  • Terminal-based
  • Scriptable
  • Universal
  • Powerful

🎓 Our Training Course

Learn RESTful APIs

Take our comprehensive REST APIs course:

📚 RESTful APIs Course →

🚀 Master REST APIs!

Build powerful, scalable APIs for your applications

Start Learning →

📖 Related Topics