Skip to content

Consistency & Conventions

The individual rules matter less than applying them everywhere. An API that is 90% consistent is more confusing than one that is consistently quirky, because the exceptions are where bugs and support tickets live.

Decide these for the whole API and write them down:

  • Casing of fields — camelCase or snake_case, the same in every response.
  • Plurals — every collection plural (/articles, /users), no mixing.
  • IDs — one format (UUID, ULID, or integer) and one field name (id).
  • Timestamps — ISO 8601 UTC strings (2026-06-24T10:00:00Z), with consistent field names like createdAt/updatedAt.
  • Money & enums — minor units (integers) for money; documented string enums, not magic numbers.

Most resources are items in a collection (/articles/42). A few are singletons — there is exactly one per context, so there is no ID:

GET /me # the authenticated user
GET /settings # the account's settings
PATCH /settings # update them

Singletons skip the collection level on purpose; do not invent a fake ID for them.

  • Collections are plural; items are /collection/{id}.
  • Lowercase, hyphenated paths; no verbs; no file extensions.
  • One casing, one ID format, one timestamp format across every resource.
  • Errors share one shape (covered in Status Codes & Errors).
  • The same field means the same thing everywhere.
Advantages (Consistency)Trade-offs
Faster developer onboarding — endpoints become guessableRequires agreeing on conventions upfront — costs time
Easier SDK generation and documentationSome conventions don’t fit every resource
Consistent client code — no special casesChanging a convention later is a breaking change
Fewer bugs from typos or inconsistent casingThe team has to enforce it — needs linting or review

Inconsistent response format Symptom:

  • One endpoint returns { data: [...] }, another returns [...] directly
  • Error responses vary too: some endpoints send { error: "..." }, others { message: "..." }
  • Define a standard response envelope and use it everywhere

Inconsistent date format Symptom:

  • createdAt: "2024-01-15" on one endpoint, created: "15/01/2024" on another
  • Clients have to parse a different format per call
  • Use ISO 8601 (2024-01-15T10:30:00Z) consistently across the whole API

💡 Real-world examples

Stripe API:

  • Every resource carries id, object, created, livemode — consistent metadata
  • The same error shape on every endpoint: { error: { type, code, message, param } }

GitHub API:

  • X-RateLimit-* headers on every response, consistently
  • Pagination via the Link header on every collection endpoint

Sources: Stripe API — errors, GitHub REST API rate limits

Why is partial consistency often worse than consistent quirkiness?
How should a singleton resource like the current user be addressed?
What is the recommended format for timestamps in responses?