Lesson 13 / 25
Pagination, Filtering and Naming Conventions
Describe common API conventions consistently in OpenAPI.
Consistency makes APIs predictable
OpenAPI makes conventions visible, so decide them once and apply them everywhere, ideally captured in an API style guide enforced by linting. Naming: plural nouns for collections (/orders), kebab-case paths, consistent property casing (camelCase or snake_case, never mixed), and verbs only for genuine actions (/orders/{id}/cancellation as a resource, or :cancel if your guide allows). Pagination: prefer cursor-based pagination for large or changing collections, with limit and cursor parameters and a response envelope containing items and nextCursor; offset pagination is simpler but slower and inconsistent under concurrent inserts. Filtering and sorting: query parameters such as status, createdAfter and sort=-createdAt. Partial responses: optional fields parameters. Dates: ISO 8601 date-time in UTC. IDs: opaque strings, possibly prefixed by type (ord_...). Model these patterns as reusable components (a Page schema, standard parameters) so every list endpoint looks the same.
Consistent list endpoints
Every collection returns the same page shape with items and a cursor to the next page.
A reusable page envelope for cursor pagination
Every list endpoint returns the same structure.
components:
schemas:
OrderPage:
type: object
required: [items, nextCursor]
properties:
items:
type: array
items: { $ref: '#/components/schemas/Order' }
nextCursor:
type: [string, 'null']
description: Pass as ?cursor= to get the next page; null when there are no more items
parameters:
Sort:
name: sort
in: query
description: Field to sort by; prefix with - for descending
schema: { type: string, enum: [createdAt, -createdAt, total, -total], default: -createdAt }
CreatedAfter:
name: createdAfter
in: query
schema: { type: string, format: date-time }
paths:
/orders:
get:
operationId: listOrders
parameters:
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/CreatedAfter'
responses:
'200':
description: A page of orders
content:
application/json:
schema: { $ref: '#/components/schemas/OrderPage' }Write the style guide as lint rules
A style guide in a wiki is forgotten; the same rules expressed as Spectral or Redocly lint rules run on every pull request and keep dozens of APIs consistent.
Quick check: Why is cursor-based pagination often preferred for large collections?
- It stays fast and consistent as data changes, unlike large offsets
- It is easier to implement than every alternative
- It returns all items at once
- OpenAPI only supports cursors
Answer
It stays fast and consistent as data changes, unlike large offsets — Cursors avoid slow deep offsets and skipped or duplicated items when rows are inserted.