API Design Best Practices

A good API feels boring in the best way: predictable, consistent, and hard to misuse. The patterns below make your API easier to ship, safer to evolve, and cheaper to support — whether you build it with REST, GraphQL, or RPC.

The throughline is consistency. Clients can guess how an unfamiliar endpoint behaves when every endpoint names, paginates, errors, and authorizes the same way.

TL;DR

Quick Example

A create endpoint that states its contract clearly — correct method, 201, and a Location header:

Start With Contracts

Before choosing REST vs GraphQL, decide what your API must guarantee.

Resource Modeling

Use nouns for resources and HTTP verbs for actions.

Consistent Error Shapes

Pick one error envelope and use it everywhere, with a stable machine-readable code:

See Error Handling.

Pagination (Cursor-First)

Offset pagination breaks under inserts and slows down at scale. Prefer cursors.

Idempotency

Network timeouts happen, and clients retry. Don't let retries create duplicates:

Versioning

Avoid versioning until you need it, then pick a strategy that fits how clients update.

If you need /v2, you also need a client migration plan. See API Versioning.

Authorization & Multi-Tenancy

Authorization is a data constraint, not a middleware checkbox.

Authenticate, authorize at the resource level, always scope queries by tenant, and audit writes. See API Security.

Best Practices

Common Mistakes

Inconsistent shapes across endpoints

Authorization by obscurity

FAQ

REST or GraphQL?

REST shines when endpoints map cleanly to resources and HTTP caching matters. GraphQL shines when clients need flexible response shapes across many UI surfaces — at the cost of more schema and cost-control work. See REST API Design and GraphQL.

When should I introduce versioning?

Only for an unavoidable breaking change. Additive changes (new optional fields, new endpoints) don't need a version bump. When you must version, be consistent — URL versioning is the simplest.

How do I keep an API backward compatible?

Add, don't change or remove: new optional fields, new endpoints, and tolerant readers. Never repurpose an existing field's meaning, and never make a previously optional field required.

What's the single highest-leverage design choice?

Consistency. A predictable, uniform API is easier to learn, document, test, and evolve than a clever but irregular one.

Related Topics

References