Lesson Progress
0% Complete

Modern websites are usually split into two parts:

  • Front-end (client): Runs in the browser (HTML, CSS, JavaScript).
  • Back-end (server): Runs on a server and handles data, business rules, authentication, and integration with databases or other services.

A well-designed API (Application Programming Interface) is the “contract” between the front-end and the back-end.


1) What a Server Does (in a Web Context)

A web server application listens for requests from clients (usually browsers or mobile apps) and sends back responses.

Typical responsibilities include:

  • Routing requests to the right handler (e.g. /api/products → “list products”).
  • Validating inputs (e.g. checking required fields).
  • Authorisation (checking what the user is allowed to do).
  • Reading/writing data (via a database).
  • Returning consistent responses (usually JSON for APIs).
  • Handling errors safely (not leaking sensitive details).

The request–response cycle

  1. The client sends an HTTP request (method + URL + headers + optional body).
  2. The server matches the request to a route.
  3. The server runs logic and returns an HTTP response (status code + headers + body).

2) Routing Basics

Routing is how your server decides what code runs for a given URL and HTTP method.

A route is usually made up of:

  • Method: GET, POST, PUT, PATCH, DELETE
  • Path: /api/users, /api/users/:id

Example route patterns:

  • GET /api/products → list all products
  • GET /api/products/123 → get product 123
  • POST /api/products → create a product
  • PATCH /api/products/123 → update part of product 123
  • DELETE /api/products/123 → delete product 123

Route parameters vs query parameters

  • Route parameter (part of the path):
    /api/products/123123 is the product ID
    Used to identify a specific resource.

  • Query parameter (after ?):
    /api/products?category=shoes&page=2
    Used for filtering, sorting, pagination, searching.

Good practice:

  • Use route params for identity (/api/orders/:orderId)
  • Use query params for options (?sort=price&direction=asc)

3) HTTP Request Methods (Verbs)

RESTful APIs use standard HTTP methods to describe actions:

GET (Read)

  • Fetch data.
  • Should not change server state.
  • Examples:
    • GET /api/users
    • GET /api/users/42

POST (Create)

  • Create a new resource.
  • Sends data in the request body (typically JSON).
  • Example:
    • POST /api/users with body { "email": "...", "password": "..." }

PUT (Replace)

  • Replace an entire resource (full update).
  • Example:
    • PUT /api/users/42 with a complete user object
  • If you omit a field, it may be overwritten/removed depending on implementation.

PATCH (Partial update)

  • Update part of a resource.
  • Example:
    • PATCH /api/users/42 with body { "displayName": "Sipho" }

DELETE (Remove)

  • Remove a resource.
  • Example:
    • DELETE /api/users/42

4) RESTful Endpoint Design Principles

REST (Representational State Transfer) is a style for designing APIs around resources.

4.1 Use nouns, not verbs, in URLs

Prefer:

  • /api/products
  • /api/products/123

Avoid:

  • /api/getProducts
  • /api/createProduct

The HTTP method already tells you the action.

4.2 Use consistent plural naming

Pick one style and stick to it:

  • Common: /api/products, /api/users, /api/orders

4.3 Design around resource relationships

Examples:

  • Products have reviews:
    • GET /api/products/123/reviews
    • POST /api/products/123/reviews

Users have orders:

  • GET /api/users/42/orders

Keep nesting reasonable (don’t go too deep). If it becomes confusing, consider linking via query parameters:

  • GET /api/orders?userId=42

4.4 Filtering, sorting, pagination

Use query parameters:

  • Filter: GET /api/products?category=shoes
  • Search: GET /api/products?search=running
  • Sort: GET /api/products?sort=price&direction=asc
  • Pagination:
    • GET /api/products?page=2&pageSize=20

Make your pagination behaviour clear and consistent. For example, always return:

  • items (array)
  • page, pageSize
  • totalItems (or totalPages)

4.5 Version your API (when needed)

For public or long-lived APIs, versioning helps you change things safely:

  • /api/v1/products

Avoid breaking changes where possible. If you must break, do it in a new version.


5) HTTP Status Codes You Should Know

Status codes tell the client what happened, in a standard way.

Success responses

  • 200 OK: Request succeeded (common for GET, PATCH)
  • 201 Created: Resource created (common for POST)
  • 204 No Content: Success with no response body (common for DELETE)

Client errors (the client did something wrong)

  • 400 Bad Request: Invalid input (missing fields, wrong formats)
  • 401 Unauthorized: Not logged in / missing or invalid authentication
  • 403 Forbidden: Logged in, but not allowed to access this resource
  • 404 Not Found: Resource doesn’t exist
  • 409 Conflict: Conflict with current state (e.g. duplicate email)
  • 422 Unprocessable Content: Valid JSON but failed business validation (optional; some teams use 400 instead)

Server errors (the server failed)

  • 500 Internal Server Error: Unexpected error
  • 503 Service Unavailable: Server is overloaded or down for maintenance

Good practice:

  • Be consistent in what you return for similar situations.
  • Don’t use 200 for errors. Let status codes do their job.

6) Request and Response Format (JSON)

Most REST APIs use JSON.

Example request:

POST /api/products
Content-Type: application/json
Authorization: Bearer <token>

{
  "name": "Running Shoes",
  "price": 999.99,
  "inStock": true
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": "p_123",
  "name": "Running Shoes",
  "price": 999.99,
  "inStock": true,
  "createdAt": "2026-03-12T10:15:00Z"
}

Good practice:

  • Always set and check Content-Type: application/json when sending JSON.
  • Use consistent naming (e.g. camelCase) across the whole API.
  • Return stable identifiers (IDs) for resources.

7) Error Handling Patterns (Clear and Safe)

Errors are normal. What matters is returning errors that are:

  • Understandable for the front-end
  • Consistent across endpoints
  • Safe (no leaked stack traces or secrets)

A common error format:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Price must be a positive number.",
    "details": [
      { "field": "price", "issue": "must be greater than 0" }
    ]
  }
}

Guidelines:

  • Keep message user-friendly (or at least developer-friendly).
  • Use code values the front-end can handle (e.g. show a specific message, highlight a field).
  • Only include details when helpful (especially for form validation).

Validation errors

Return:

  • 400 (or 422) with field-level details.

Not found

Return:

  • 404 with a clear message like “Product not found”.

Authentication/authorisation failures

Return:

  • 401 when not logged in or token invalid.
  • 403 when logged in but not allowed.

Unexpected errors

Return:

  • 500 with a generic message:
    • “Something went wrong.”
  • Log technical detail on the server (for debugging), not in the response.

8) Designing Endpoints for Smooth Front-end Integration

Your front-end developers (including future you) will thank you for consistency.

8.1 Make responses predictable

For example, always return:

  • a single object for single-resource endpoints
  • arrays for list endpoints
  • the same field names everywhere

Example:

  • GET /api/products/123 returns { id, name, price }
  • GET /api/products returns { items: [ ... ], page, pageSize, totalItems }

8.2 Avoid over-fetching and under-fetching

  • Over-fetching: returning too much data the UI doesn’t need.
  • Under-fetching: forcing the UI to call 5 endpoints for one page.

Balance ideas:

  • Provide “list views” with summary fields and “detail views” with full fields.
  • Consider query options like ?include=reviews only if your team agrees and documents it clearly.

8.3 Handle empty states cleanly

If there are no products, the list endpoint should return:

  • 200 OK
  • items: []

Not an error.

8.4 Idempotency (important for reliability)

Some requests should be safe to repeat:

  • GET, PUT, DELETE are typically idempotent (repeating should not change the outcome).
  • POST is usually not idempotent (repeating may create duplicates).

This matters for retries when networks are unreliable.


9) Quick Example: A Small REST API for Products

A simple, clear set of endpoints:

  • GET /api/products
    List products (supports ?page=1&pageSize=20&search=...)

  • POST /api/products
    Create a product

  • GET /api/products/:id
    Fetch one product

  • PATCH /api/products/:id
    Update fields (e.g. price or stock)

  • DELETE /api/products/:id
    Remove product

Potential responses:

  • On create success: 201 Created + new product JSON
  • On delete success: 204 No Content
  • On invalid data: 400 Bad Request + validation details
  • On missing product: 404 Not Found

10) Checklist: REST Design and Server Behaviour

Use this as a quality check when you build APIs:

  • [ ] Routes use nouns and consistent naming (usually plural).
  • [ ] HTTP methods match the action (GET, POST, PATCH, DELETE).
  • [ ] Status codes are correct and consistent.
  • [ ] Errors return a consistent JSON structure.
  • [ ] Validation is handled with helpful field-level messages.
  • [ ] Pagination/filtering/sorting use query parameters.
  • [ ] Sensitive server details are not exposed in responses.
  • [ ] API behaviour is predictable for the front-end (stable fields and formats).

If you want, I can also provide a small “API contract” template (endpoint + request + response examples) you can include in your project documentation for the LMS.