Architecture
REST API Design: Versioning, Documentation and Developer Experience
REST principles, status codes, versioning, auth, rate limiting and OpenAPI.
Good API design makes the interface predictable, easy to use and change. This article reviews REST principles, versioning, error handling, authentication and documentation – so consumers (internal or external) can integrate the API quickly and safely.
REST – resources and actions: resources are identified by URL – plural nouns (e.g. /users, /orders). Actions are expressed by HTTP method: GET (read), POST (create), PUT/PATCH (update), DELETE (delete). Do not put actions in the URL (e.g. /getUser); use GET /users/:id. Filtering and sorting via query params: ?status=active&sort=createdAt.
Status codes and responses: 200 OK (success), 201 Created (creation, with Location header), 204 No Content (success without body). 400 Bad Request (invalid input), 401 Unauthorized (missing/invalid auth), 403 Forbidden (no permission), 404 Not Found, 409 Conflict (conflict, e.g. duplicate), 429 Too Many Requests (rate limit), 500 Internal Server Error. Consistency: uniform error format (code, message, details) in all responses.
Versioning: breaking changes – field name change, endpoint removal – require a new version to avoid breaking consumers. Common approach: version in URL (/v1/users, /api/v2/orders). Alternatives: header (Accept-Version: 2) or query (?version=2). Define policy: support for old versions (e.g. 12 months), deprecation notice in advance, and document breaking changes in changelog.
Authentication and authorization: auth – usually OAuth2/OIDC or API keys for machine-to-machine. Authorization – RBAC or per-resource check (is the user authorized for this resource). Do not return 401/403 with a body that reveals too much (e.g. "user not authorized to read field X").
Rate limiting and throttling: limiting number of requests per client (e.g. 100/min) prevents overuse and system damage. Return 429 with Retry-After when limit is reached. Document limits in API docs.
Documentation: OpenAPI (Swagger) – a single document describing endpoints, parameters, responses and examples. Tools: code generation (client/server), automated tests, and trial interface (Swagger UI). Prefer storing the document in the repo and updating with every change; CI integration fails the build if code deviates from the contract.
Developer experience (DX): readable examples, explanation of business terms, description of common errors and how to fix. Sandbox or trial environment with dummy data. Clear changelog and versioning policy – build trust and reduce support.
GraphQL as alternative: when consumers need to fetch different fields or reduce over-fetching, GraphQL offers a query language and a single endpoint version. Requires schema design, protection against heavy queries (depth limit, complexity) and documentation. REST remains simple and widely supported.
In summary: good API design is based on consistent REST, clear status codes and error format, versioning and deprecation policy, authentication and authorization and rate limiting, and up-to-date documentation (OpenAPI) and good developer experience. Investing in design saves integration time and reduces incidents.