What you will take away
- Consistency beats cleverness - a predictable API needs less documentation.
- Errors need a stable code, a human message and the field at fault.
- Cursor pagination is correct; offset pagination breaks under writes.
Consistency is the whole feature
A developer integrating with your API builds a mental model in the first ten minutes and expects it to hold. Plural nouns for collections, identifiers in the path, filters in the query string, one casing convention, the same date format everywhere, the same envelope on every response.
Every exception costs a documentation lookup and eventually a support ticket. An API that is predictable but plain is easier to use than one that is clever in three places.
Errors are part of the interface
Return the right status code, and a body that is actually actionable: a stable machine-readable code, a human-readable message, the field at fault for validation errors, and a request id the caller can quote to support.
- 400 for a malformed request, 422 for one that is well-formed but invalid.
- 401 when the caller is unauthenticated, 403 when authenticated but not permitted.
- 404 for a missing resource - and for one the caller may not know exists.
- 409 for a conflict, 429 with a retry hint when rate limited.
Never return 200 with an error inside the body. Every client retry, cache and monitor in the world reads the status code first.
Pagination, filtering and the N+1 trap
Use cursor pagination for anything that changes. Offset pagination silently skips and repeats records when rows are inserted between requests, which produces bugs that are almost impossible to reproduce.
Always cap the page size, and give clients a way to request related data in one call - sparse fieldsets or an include parameter - so they are not forced into a request per item. An API that makes N+1 calls the natural pattern will be blamed for being slow.
Versioning decided before launch
Adding a field is safe; removing or renaming one is not, and neither is tightening validation or changing the meaning of a value. Decide how you will version - path, header or content negotiation - before the first external consumer exists, because retrofitting it is far harder.
Then commit to a deprecation policy in writing: how long an old version is supported, how you notify, and what the migration path is. Publishing that policy is what makes an API safe to build a business on.
REST or GraphQL
REST suits resource-shaped domains, benefits from HTTP caching, and is simpler to operate, monitor and secure. GraphQL earns its complexity when many different clients need different shapes of the same data, and it removes a class of over-fetching problems for mobile.
GraphQL also brings its own work: query cost limiting, depth restrictions, dataloader batching to avoid N+1 at the resolver layer, and caching that HTTP no longer does for you. Choose it for a real client need, not for the developer experience of the query language.