REST API Intermediate

Make the API usable in a real product.

Intermediate REST work is where an endpoint becomes useful to frontend teams, internal tools, dashboards, and partner integrations. This is where auth, pagination, filtering, and validation matter.

Authentication

Use bearer tokens, API keys, or signed requests so only approved clients can access data.

Pagination

Split large lists into pages or cursor windows so responses stay fast and predictable.

Filtering and sorting

Allow clients to ask for exactly the records they need instead of returning everything.

Validation

Reject missing or malformed input before it reaches the database.

Versioning

Keep `/v1` or header-based versions for breaking changes.

Caching

Use ETag, Cache-Control, or CDN caching on safe GET endpoints.

Idempotency

Protect side-effecting retries with idempotency keys so duplicate charges, orders, or events are not created.

Problem details

Use consistent error payloads instead of bespoke error shapes per endpoint.

Authentication patterns

  • Use API keys for simple server-to-server access when the use case is narrow and low-risk.
  • JWT bearer tokens are common for signed claims, but they must be protected in storage and transport.
  • Use OAuth2 when third-party or delegated access is required, especially with scopes and refresh flows.
  • PKCE matters for public clients such as mobile apps and SPAs because it protects the authorization code flow.
  • Never place sensitive tokens in public client-side code unless the token is designed for public use.
  • Return `401` for missing or invalid auth and `403` when the user is authenticated but not allowed.

Pagination and filters

  • Support `page` and `limit` or cursor-based navigation so large tables do not overload the response.
  • Add filters such as `status=active`, `country=IN`, or `search=video` to reduce noisy payloads.
  • Return total count or next cursor so the client can keep loading cleanly.
  • Keep sorting deterministic so new inserts do not break paging unexpectedly.

Validation and versioning

  • Validate types, required fields, enums, and length before writing to MySQL or a queue.
  • Return machine-friendly errors such as `field`, `code`, and `message` so the UI can react properly.
  • Keep a stable `/v1` while you build `/v2` if you need a breaking schema change.
  • Document defaults, optional fields, and deprecation dates so clients are not surprised.

Caching and performance

  • Cache safe GET requests, not write operations.
  • Use `Cache-Control`, ETag, or `Last-Modified` when a frontend repeatedly asks for mostly unchanged data.
  • Set sensible limits so one request cannot pull an entire database table into memory.
  • Log latency, slow SQL, and payload size so performance problems are measurable.

Rate limiting, retries, and idempotency

  • Return `429 Too Many Requests` when clients exceed policy and include retry guidance when possible.
  • Design write endpoints so clients can safely retry after timeouts without creating duplicate side effects.
  • For create or payment-style operations, use an idempotency key instead of trusting transport retries alone.

Content negotiation and errors

  • The `Accept` header lets the client ask for JSON, CSV export, or specialized error media types.
  • `application/problem+json` keeps errors predictable instead of inventing a different payload for every endpoint.
  • This becomes more important as multiple clients, SDKs, and partner teams depend on the same API.

Paginated JSON response example

{
  "success": true,
  "data": [
    { "id": 1, "title": "Campaign A", "status": "active" },
    { "id": 2, "title": "Campaign B", "status": "paused" }
  ],
  "pagination": {
    "page": 1,
    "limit": 2,
    "total": 18,
    "pages": 9
  }
}

Problem details example

{
  "type": "https://example.com/problems/validation-error",
  "title": "Validation failed",
  "status": 400,
  "detail": "name is required",
  "instance": "/v1/items"
}

Hypermedia in practice

  • Full HATEOAS is uncommon in many product APIs, but links still matter for pagination, related resources, and navigation.
  • The HTTP `Link` header and formats such as HAL or JSON:API are practical ways to expose link relations.
  • Even without full hypermedia, stable link patterns improve discoverability and client correctness.

Frontend `fetch()` example

This is the point where REST meets the website UI. The browser calls the endpoint, gets JSON, and re-renders cards, tables, charts, or forms.

async function loadCampaigns(page = 1) {
  const response = await fetch(`/pages/api.php?table=blogs&limit=5&page=${page}&key=YOUR_KEY`, {
    headers: {
      "Accept": "application/json",
      "X-API-Version": "1.0"
    }
  });

  if (!response.ok) {
    throw new Error(`Request failed with ${response.status}`);
  }

  const data = await response.json();
  renderCampaigns(data);
}