Building maintainable APIs with .NET and Node.js

APIs are the contract between your system and its consumers. A well-designed API makes integration straightforward. A poorly designed one creates friction that compounds over time.

Consistent resource naming

Use plural nouns for resources (/users, /orders). Nest resources to show hierarchy (/orders/123/items). Use query parameters for filtering and pagination. Avoid verbs in URLs — HTTP methods already express the action.

Versioning

Put a version prefix on your API path (/v1/orders). Version when you make breaking changes to the contract. Non-breaking additions (new fields, new endpoints) do not require a new version.

Error responses

Return consistent error structures. Include a machine-readable error code, a human-readable message, and a trace ID for debugging.

{
  "code": "order_not_found",
  "message": "Order 456 was not found",
  "trace_id": "abc-123"
}

Use standard HTTP status codes. 400 for validation errors, 404 for not found, 409 for conflicts, 500 for server errors.

Pagination

Always paginate list endpoints. Use cursor-based pagination for large datasets. Return next and previous cursors in the response so clients do not construct URLs.

Validation

Validate input at the API boundary. Return detailed error messages for each invalid field. Never trust client input, even if it comes from your own frontend.