API Design Principles We Actually Follow

Engineering Team·April 22, 2026

Practical principles for designing REST APIs that are easy to use, version gracefully, and don't surprise your consumers.

Consistency beats cleverness

The hardest part of API design isn't any single endpoint — it's keeping the whole surface area consistent. Consumers build mental models. Every exception to your patterns breaks that model.

Pick conventions and document them. Ours:

  • Resources are plural nouns: /invoices, /purchase-orders
  • Actions that don't fit CRUD use POST with a verb suffix: /invoices/:id/approve
  • Dates are always ISO 8601 in UTC: 2026-04-22T14:30:00Z

Error responses need as much care as success responses

A 400 that says "Bad Request" is useless. We standardized on:

{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "The request body contains invalid fields.",
    "details": [
      { "field": "amount", "issue": "Must be a positive number." }
    ]
  }
}

Consumers can programmatically handle code, show message to users, and map details to form fields. All three serve different needs.

Version in the URL, not headers

/v1/invoices is easier to test in a browser, easier to log, and easier to route at the gateway level than Accept: application/vnd.api+json;version=1. We've never regretted this choice.

Don't break consumers silently

Additive changes (new fields, new endpoints) are safe. Everything else is a breaking change:

  • Removing a field
  • Changing a field's type
  • Changing the meaning of a status code
  • Renaming a resource

We treat breaking changes as requiring a new major version. We keep old versions alive for at least 12 months and send deprecation notices via email and a Deprecation response header.

Pagination on every list endpoint, from day one

Adding pagination to an endpoint that previously returned everything is a breaking change. We default to cursor-based pagination:

{
  "data": [...],
  "pagination": {
    "next_cursor": "eyJpZCI6MTIzfQ==",
    "has_more": true
  }
}

Cursor pagination handles insertions and deletions between pages correctly — offset pagination doesn't.

The rule we always come back to

If you wouldn't want to consume this API yourself, don't ship it.

April 22, 2026