Integration & APIs/
Lesson
AI pitfall
Ask AI to "generate a REST API" and you will get a working API with at least 3 inconsistencies: mixed naming conventions, missing pagination on some list endpoints, and different error formats across handlers. AI generates each endpoint independently and loses consistency across the whole API surface.

Knowing RESTWhat is rest?An architectural style for web APIs where URLs represent resources (nouns) and HTTP methods (GET, POST, PUT, DELETE) represent actions on those resources. basics is easy. Building a REST APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses. that does not become a maintenance nightmare after six months is harder. This lesson covers the patterns that separate well-designed APIs from ones that developers curse at.

PaginationWhat is pagination?Splitting a large set of results into smaller pages so the server and client only handle a manageable chunk at a time.: cursor vs offset

Good to know
Pagination is not optional, even for endpoints you think will "always be small." A test database with 10 records masks a production database with 100,000 rows. The findAll() call that takes 5ms in development takes 30 seconds in production and crashes the response serializer.

Any endpointWhat is endpoint?A specific URL path on a server that handles a particular type of request, like GET /api/users. that returns a list must be paginated. Without pagination, your database query returns 50,000 rows, your server serializes them all to JSONWhat is json?A text format for exchanging data between systems. It uses key-value pairs and arrays, and every programming language can read and write it., and your client crashes trying to render them.

Offset-based pagination

The simpler approach. The client says "give me items 20 through 40."

GET /api/articles?offset=20&limit=20
json
{
  "data": [...],
  "pagination": {
    "total": 1523,
    "offset": 20,
    "limit": 20,
    "hasMore": true
  }
}

Cursor-based paginationWhat is cursor-based pagination?A pagination method that uses an indexed column value from the last seen row rather than OFFSET, staying fast on very large tables.

The client says "give me 20 items after this marker."

GET /api/articles?after=eyJpZCI6NDJ9&limit=20
json
{
  "data": [...],
  "pagination": {
    "endCursor": "eyJpZCI6NjJ9",
    "hasNextPage": true
  }
}

The cursor is an opaque tokenWhat is token?The smallest unit of text an LLM processes - roughly three-quarters of a word. API pricing is based on how many tokens you use. (usually a base64-encoded ID or timestamp) that the server uses to find the next batch.

Which to choose?

FactorOffsetCursor
ImplementationSimpleMore complex
"Jump to page 5"YesNo
Performance at page 1000Slow (DB scans offset rows)Fast (seeks directly)
New items insertedDuplicates or skips itemsStable, no duplicates
Deletes during paginationSkips itemsStable
Best forAdmin dashboards, static dataFeeds, real-time data, mobile apps

Rule of thumb: If users need "page 5 of 20," use offset. If they scroll infinitely through a feed, use cursor.

02

Filtering patterns

Filtering should be predictable across your entire APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses.. Pick conventions and stick to them.

GET /api/articles?status=published&author=42&sort=-createdAt&fields=id,title,summary

Common conventions

// Equality filter
GET /api/users?role=admin

// Multiple values (OR)
GET /api/users?role=admin,editor

// Range filters
GET /api/products?price_min=10&price_max=100

// Date ranges
GET /api/orders?created_after=2024-01-01&created_before=2024-06-01

// Search
GET /api/articles?q=graphql+caching

// Sorting (prefix - for descending)
GET /api/articles?sort=-createdAt,title

// Field selection (sparse fieldsets)
GET /api/users?fields=id,name,email
ConventionFormatExample
Equality?field=value?status=active
Multiple values?field=a,b?role=admin,editor
Range?field_min=x&field_max=y?price_min=10&price_max=50
Sort ascending?sort=field?sort=name
Sort descending?sort=-field?sort=-createdAt
Field selection?fields=a,b,c?fields=id,name
Search?q=term?q=javascript
Pagination (offset)?offset=N&limit=N?offset=20&limit=10
Pagination (cursor)?after=cursor&limit=N?after=abc123&limit=10
Edge case
Offset pagination breaks when items are inserted or deleted between page requests. If you fetch page 1 (items 1-10), then a new item is inserted at position 1, page 2 will skip the item that was previously at position 10. Cursor-based pagination avoids this entirely because it seeks from a fixed point.
03

HATEOASWhat is hateoas?A REST constraint where API responses include hyperlinks to related actions, so clients can discover available operations without hardcoding URLs.: links in responses

HATEOAS is a RESTWhat is rest?An architectural style for web APIs where URLs represent resources (nouns) and HTTP methods (GET, POST, PUT, DELETE) represent actions on those resources. constraint that says responses should include links to related actions. The idea is that a client can navigate the APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses. without hardcoding URLs.

json
{
  "id": 42,
  "title": "REST Best Practices",
  "status": "draft",
  "_links": {
    "self": { "href": "/api/articles/42" },
    "publish": { "href": "/api/articles/42/publish", "method": "POST" },
    "author": { "href": "/api/users/7" },
    "comments": { "href": "/api/articles/42/comments" }
  }
}

In practice, full HATEOAS is rare. Most APIs include paginationWhat is pagination?Splitting a large set of results into smaller pages so the server and client only handle a manageable chunk at a time. links (next, prev) but skip the rest. The concept is worth knowing because it shows up in interviews and API design discussions.

04

Idempotency keys

Network failures happen. When a client sends a POST request to create a payment and the connection drops before receiving the response, should it retry? If it does, will it create a duplicate payment?

Idempotency keys solve this. The client generates a unique key and sends it with the request. If the server receives the same key twice, it returns the original response instead of processing again.

// Client generates a unique key per operation
const idempotencyKey = crypto.randomUUID();

const response = await fetch('/api/payments', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Idempotency-Key': idempotencyKey
  },
  body: JSON.stringify({
    amount: 4999,
    currency: 'usd',
    customer: 'cus_abc123'
  })
});
// Server-side implementation
app.post('/api/payments', async (req, res) => {
  const idempotencyKey = req.headers['idempotency-key'];

  // Check if this key was already processed
  const existing = await db.idempotencyKeys.findOne({ key: idempotencyKey });
  if (existing) {
    return res.status(existing.statusCode).json(existing.responseBody);
  }

  // Process the payment
  const payment = await stripe.charges.create(req.body);

  // Store the result keyed by idempotency key (TTL: 24 hours)
  await db.idempotencyKeys.insert({
    key: idempotencyKey,
    statusCode: 201,
    responseBody: payment,
    expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000)
  });

  res.status(201).json(payment);
});

Stripe, PayPal, and most payment APIs use this pattern. You should too for any operation that must not be duplicated.

05

OpenAPIWhat is openapi?A standard format for describing REST APIs - their endpoints, parameters, and response shapes. Tools can generate documentation and client libraries from it automatically. / Swagger

OpenAPI (formerly Swagger) is the standard for describing RESTWhat is rest?An architectural style for web APIs where URLs represent resources (nouns) and HTTP methods (GET, POST, PUT, DELETE) represent actions on those resources. APIs. You write a YAMLWhat is yaml?A human-readable text format used for configuration files, including Docker Compose and GitHub Actions workflows. or JSONWhat is json?A text format for exchanging data between systems. It uses key-value pairs and arrays, and every programming language can read and write it. spec, and tooling generates documentation, client SDKs, and server stubs.

yaml
openapi: 3.0.0
info:
  title: Blog API
  version: 1.0.0
paths:
  /api/articles:
    get:
      summary: List articles
      parameters:
        - name: status
          in: query
          schema:
            type: string
            enum: [draft, published]
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
      responses:
        '200':
          description: List of articles
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Article'

SchemaWhat is schema?A formal definition of the structure your data must follow - which fields exist, what types they have, and which are required.-first workflow: Write the OpenAPI spec before writing any code. The spec becomes the contract between frontend and backend teams. Both sides can work in parallel, frontend mocks the APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses. from the spec, backend implements it.

06

What AI gets wrong when generating RESTWhat is rest?An architectural style for web APIs where URLs represent resources (nouns) and HTTP methods (GET, POST, PUT, DELETE) represent actions on those resources. APIs

Here is what AI typically generates when you ask for a REST APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses., and why you should not trust the output without review:

Inconsistent naming: The AI might use createdAt on one endpointWhat is endpoint?A specific URL path on a server that handles a particular type of request, like GET /api/users. and created_at on another. Or userId in one response and user_id in the next. Pick camelCase or snake_case and enforce it everywhere.

Missing paginationWhat is pagination?Splitting a large set of results into smaller pages so the server and client only handle a manageable chunk at a time.: AI-generated list endpoints often return all items with no pagination. This works fine with 10 test records and breaks catastrophically in production with 100,000 rows.

No error format: Responses come back as { error: "something" } on one endpoint and { message: "something", code: 400 } on another. Define a standard error format and use it everywhere:

json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Email format is invalid",
    "details": [
      { "field": "email", "issue": "Must be a valid email address" }
    ]
  }
}

No versioning strategy: AI rarely adds API versioning. When you need to make a breaking changeWhat is breaking change?A modification to an API that causes existing code using it to stop working, such as renaming a field or changing a response format. six months later, you have no path forward. Always version your API from day one, /v1/articles, even if you never plan to change it.

Ignoring idempotency: AI-generated POST endpoints almost never include idempotency keyWhat is idempotency key?A unique client-generated string sent with a mutation request so the server can safely deduplicate retried requests. handling. For non-critical endpoints this is fine. For payments, orders, or anything involving money, it is a production incident waiting to happen.

07

RESTWhat is rest?An architectural style for web APIs where URLs represent resources (nouns) and HTTP methods (GET, POST, PUT, DELETE) represent actions on those resources. conventions table

ConventionDoDo not
Resource namesPlural nouns: /users, /articlesVerbs: /getUsers, /createArticle
URL casingLowercase kebab-case: /user-profilescamelCase: /userProfiles
Response casingPick one: camelCase or snake_caseMix both in the same API
HTTP methodsUse semantically: GET reads, POST createsPOST for everything
Status codesUse specific codes: 201 Created, 204 No Content200 for everything
Error formatConsistent structure across all endpointsDifferent shapes per endpoint
VersioningURL prefix: /v1/ or header: Accept-VersionNo versioning at all
PaginationAlways on list endpointsReturn unbounded arrays
Date formatISO 8601: 2024-03-15T10:30:00ZUnix timestamps or custom formats
Null fieldsInclude with null value or omit consistentlySometimes include, sometimes omit