CLOSE

First let's get familiar with what exactly API is:

An API – short of Application Programming Interface – is a set of rules, protocol, and tools that allows different software systems or components to communicate with each other. In essence, it acts as a contract between two pieces of software: one system offers specific functions or data, and the other system can access these services without needing to understand the internal workings behind them.

For example, when you use a weather app on your phone, it might call a weather API to fetch the latest forecast data, which is then returned in a standardized format like JSON or XML. This abstraction not only speeds up development by letting programmers reuse existing functionalities but also ensures that systems can work together seamlessly even if their internal implementations change over time.

APIs come in many varieties, and they can be categorized based on how they are used, who can access them, and the underlying technology or architecture they follow. Here are some common types:

1 By Accessibility:

  • Public APIs (Open APIs):
    • Available to anyone.
    • They are designed for external developers to build on top of a platform.
    • e.g., Twitter API, Google Maps API.
  • Private APIs:
    • Used internally within an organization to streamline development and integrate systems without exposing functionality to the public.
  • Partner APIs:
    • Shared with specific business partners under controlled conditions to enable integrations and collaborations.

2 By Architectural Style/Protocol:

  • REST APIs:
    • Use standard HTTP methods (GET, POST, PUT, PATCH, DELETE) and are typically stateless. They return data in formats like JSON or XML.
  • SOAP APIs:
    • Follow the Simple Object Access Protocol, using XML for message formatting and are often found in enterprise environments with strict security and transaction requirements.
  • GraphQL APIs:
    • Allow clients to request exactly the data they need in a single query, reducing over-or under-fetching of data.
  • WebSockets APIs:
    • Enable real-time, two-way communication between the client and server over a single persistent connection.
  • gRPC APIs:
    • A high-performance framework by Google that uses HTTP/2 and Protocol Buffers for efficient communication in distributed systems.

3 By Functionality/Use Case:

  • Operating System APIs:
    • Provide methods to interact with the OS, such as file management and hardware control (e.g., Windows API, POSIX).
  • Library APIs:
    • Offered by programming libraries to expose functions or classes that developers can reuse in their own applications (e.g., Java API, Python’s Standard Library).
  • Database APIs:
    • Allow applications to interact with database systems (e.g., JDBC, ODBC).
  • Hardware APIs:
    • Enable software to interact with hardware components like sensors or cameras.

REST API

RESTful is an approach to building web services that makes them simple, predictable, and easy to use.

Imagine a library where every book is a "resource." Each book has a unique location (like a URL). When you want to do something with a book—such as look it up, add a new one, update its information, or remove it—you use a standard method:

  • GET: Think of it as "reading" or checking out a book.
  • POST: This is like "adding" a new book to the library.
  • PUT/PATCH: This updates or "replacing" a book’s information.
  • DELETE: This removes a book from the library.

A RESTful system uses these HTTP methods (GET, POST, PUT, DELETE) in a consistent way, so no matter what kind of data you’re dealing with, the actions you perform on it are the same. Also, each request you make to the library is independent—the library doesn’t need to remember your previous requests (this is called "statelessness").

Thus we can say that RESTful is an architectural style for designing networked applications. The term RESTful refers to systems or services that adhere to the principles of Representational State Transfer (REST), a concept introduced by Roy Fielding in his 2000 doctoral dissertation.

In Restful systems:

  • Resources (data objects) are identified via URIs (Uniform Resource Identifiers).
  • HTTP Methods such as GET, POST, PUT and DELETE are used to perform operations on these resources – mapping directly to read, create, update, and delete actions (CRUD).
  • Statelessness is a key principle; each request from a client must contain all the information needed to understand and process the request, with no client context stored on the server between requests.
  • A uniform interface is maintained, which simplifies and decouples the architecture, allowing each part to evolve independently.

RESTful API Design Approach

RESTful API design is an approach to building web services that treat server data as “resources” and allow clients to interact with them using standard HTTP methods. In this model, CRUD operations—Create, Read, Update, and Delete—are mapped to specific HTTP verbs and URL structures.

RESTful API and CRUD Operations

  • Create
    • Use POST to add a new resource. For example, sending a POST request to /items creates a new item.
  • Read
    • Use GET to retrieve resources.
      • GET /items return all items.
      • GET /items/:id returns a specific item.
  • Update:
    • Use PUT or PATCH to modify an existing resource.
      • PUT /items/:id replaces an item completely.
      • PATCH /items/:id makes partial updates.
  • Delete:
    • Use DELETE to remove a resource, such as:
      • DELETE /items/:id.

This approach provides a standardized way for clients and servers to communicate and ensures that the API is intuitive and scalable.

Designing a RESTful API with Express.js

When building a RESTful API in Express.js, consider the following best practices:

  1. Resource-Oriented URLs:
    1. Use nouns to represent resources (e.g., /users, /products), not actions.
  2. HTTP Status Codes:
    1. Return appropriate status codes. For instance:
      1. 201 Created after a successful POST.
      2. 200 OK for successful, GET, PUT, or DELETE.
      3. 400 Bad Request for malformed input.
  3. Versioning:
    1. Consider versioning your API (e.g., /v1/items) to manage future changes.
  4. Statelessness:
    1. Each request should contain all the information needed to process it, making your API scalable.

Example: A Simple CRUD API in Express.js

Below is a sample Express.js application that implements CRUD operations for an in-memory “items” resource:

const express = require('express');
const app = express();
app.use(express.json());

// In-memory data store
let items = [];

// CREATE: Add a new item
app.post('/items', (req, res) => {
  const newItem = req.body;
  newItem.id = items.length + 1; // simple unique ID assignment
  items.push(newItem);
  res.status(201).json(newItem);
});

// READ: Get all items
app.get('/items', (req, res) => {
  res.json(items);
});

// READ: Get a single item by ID
app.get('/items/:id', (req, res) => {
  const id = parseInt(req.params.id, 10);
  const item = items.find(i => i.id === id);
  if (item) {
    res.json(item);
  } else {
    res.status(404).json({ error: 'Item not found' });
  }
});

// UPDATE: Modify an existing item
app.put('/items/:id', (req, res) => {
  const id = parseInt(req.params.id, 10);
  const index = items.findIndex(i => i.id === id);
  if (index !== -1) {
    // Merge the current item with the updates from the request
    const updatedItem = { ...items[index], ...req.body };
    items[index] = updatedItem;
    res.json(updatedItem);
  } else {
    res.status(404).json({ error: 'Item not found' });
  }
});

// DELETE: Remove an item
app.delete('/items/:id', (req, res) => {
  const id = parseInt(req.params.id, 10);
  const index = items.findIndex(i => i.id === id);
  if (index !== -1) {
    const deletedItem = items.splice(index, 1)[0];
    res.json(deletedItem);
  } else {
    res.status(404).json({ error: 'Item not found' });
  }
});

// Start the server
app.listen(3000, () => {
  console.log('Server is running on http://localhost:3000');
});

Explanation

  • POST /items:
    Creates a new item. The server assigns a simple unique ID and returns the created item with a 201 Created status.
  • GET /items:
    Retrieves all items from the in-memory array.
  • GET /items/:id:
    Retrieves a specific item by its ID. If the item isn’t found, a 404 Not Found error is returned.
  • PUT /items/:id:
    Updates an existing item. The request body is merged with the existing item, and the updated item is returned.
  • DELETE /items/:id:
    Deletes an item based on its ID. If successful, the deleted item is returned; otherwise, a 404 Not Found error is sent.