83 lines
3.7 KiB
Markdown
83 lines
3.7 KiB
Markdown
# REST API Design Guide
|
|
|
|
Practical principles for designing consistent, predictable, and evolvable HTTP APIs.
|
|
|
|
## URL Naming Conventions
|
|
|
|
- Use plural nouns for collections: `/orders`, `/users`, `/products`
|
|
- Nest resources to express ownership: `/users/{userId}/orders/{orderId}`
|
|
- Keep URLs shallow (max 2-3 levels); flatten when relationships are weak
|
|
- Use kebab-case for multi-word segments: `/order-items`, not `/orderItems`
|
|
- Avoid verbs in URLs; let HTTP methods convey the action
|
|
- Use query parameters for filtering, sorting, and pagination: `/orders?status=pending&sort=-createdAt`
|
|
|
|
## HTTP Method Semantics
|
|
|
|
| Method | Purpose | Idempotent | Safe |
|
|
|--------|---------|------------|------|
|
|
| GET | Retrieve resource(s) | Yes | Yes |
|
|
| POST | Create a resource or trigger a process | No | No |
|
|
| PUT | Full replace of a resource | Yes | No |
|
|
| PATCH | Partial update of a resource | No* | No |
|
|
| DELETE | Remove a resource | Yes | No |
|
|
|
|
Use POST for actions that do not map to CRUD: `POST /orders/{id}/cancel`.
|
|
|
|
## Status Code Usage
|
|
|
|
- **200 OK** — Successful GET, PUT, PATCH, or action POST
|
|
- **201 Created** — Successful POST that created a resource; include Location header
|
|
- **204 No Content** — Successful DELETE or PUT with no response body
|
|
- **400 Bad Request** — Malformed syntax or invalid field values
|
|
- **401 Unauthorized** — Missing or invalid authentication credentials
|
|
- **403 Forbidden** — Authenticated but insufficient permissions
|
|
- **404 Not Found** — Resource does not exist
|
|
- **409 Conflict** — State conflict (duplicate, version mismatch)
|
|
- **422 Unprocessable Entity** — Valid syntax but business rule violation
|
|
- **429 Too Many Requests** — Rate limit exceeded; include Retry-After header
|
|
- **500 Internal Server Error** — Unhandled server failure
|
|
|
|
## Error Response Format
|
|
|
|
Use a consistent envelope for every error. Include a machine-readable code, a human-readable message, and optional field-level detail:
|
|
|
|
```json
|
|
{
|
|
"error": {
|
|
"code": "VALIDATION_FAILED",
|
|
"message": "One or more fields failed validation.",
|
|
"details": [
|
|
{ "field": "email", "reason": "Must be a valid email address." }
|
|
],
|
|
"requestId": "abc-123"
|
|
}
|
|
}
|
|
```
|
|
|
|
Always include a request ID for traceability.
|
|
|
|
## Pagination Patterns
|
|
|
|
- **Offset-based**: `?offset=20&limit=10` — Simple but degrades on large datasets due to OFFSET cost.
|
|
- **Cursor-based**: `?cursor=eyJpZCI6MTAwfQ&limit=10` — Encode the last-seen key as an opaque token. Preferred for DynamoDB and large datasets.
|
|
- Return pagination metadata in the response body: `nextCursor`, `hasMore`, `totalCount` (if cheap to compute).
|
|
|
|
## Versioning Strategies
|
|
|
|
- **URL path versioning** (`/v1/orders`) — Most explicit, easiest for consumers. Preferred for public APIs.
|
|
- **Header versioning** (`Accept: application/vnd.myapi.v2+json`) — Cleaner URLs but harder to discover.
|
|
- Avoid query-parameter versioning (`?version=2`); it conflates filtering with contract selection.
|
|
- Version only when you introduce breaking changes. Additive changes (new optional fields) do not require a new version.
|
|
|
|
## OpenAPI and AsyncAPI
|
|
|
|
- Maintain an OpenAPI 3.1 spec as the source of truth. Generate server stubs and client SDKs from it.
|
|
- For event-driven APIs (SNS, EventBridge, SQS), use AsyncAPI to document message schemas and channel bindings.
|
|
- Store specs in the repo alongside the code (`docs/openapi.yaml`) and validate them in CI with spectral or redocly-cli.
|
|
|
|
## HATEOAS Considerations
|
|
|
|
- Include `_links` in responses to guide clients to related actions and resources.
|
|
- Useful for complex state machines (order lifecycle) where available transitions change.
|
|
- For internal microservice APIs, HATEOAS is often unnecessary overhead; reserve it for public or partner APIs where discoverability matters.
|