Skip to content

Essential Best Practices (REST API & URI Design)

  • Client-Server, Stateless, Cacheable, Layered System, Uniform Interface, Code-on-Demand (optional)
  • Benefits: scalability, evolvability, and loose coupling across services
  • A resource represents a domain object or collection (e.g., resources)
  • Representations are exchanged (JSON), identified by stable URIs
  • Singleton: a single resource instance (e.g., /resources/{id})
  • Collection: a set of resources (e.g., /resources)
  • Collections may expose nested sub-collections (e.g., /resources/{resourceId}/items)
  • Use nouns; operations are via HTTP methods (GET, POST, PATCH, DELETE)
  • Pattern: /<bounded-context>/<version>/<resource>[/{id}[/<sub-resource>]]
  • Example (Bounded Context = data-owner-bc, Version = v1):
    • Collection: /data-owner-bc/v1/resources
    • Item: /data-owner-bc/v1/resources/{id}
    • Sub-collection: /data-owner-bc/v1/resources/{resourceId}/items
  • Use nouns, not verbs: URIs represent resources (things), not actions

    ✅ GET /data-owner-bc/v1/resources
    ✅ POST /data-owner-bc/v1/resources
    ✅ DELETE /data-owner-bc/v1/resources/{id}
  • Use plural nouns for collections: Consistency across all endpoints

    ✅ GET /data-owner-bc/v1/resources
    ✅ GET /data-owner-bc/v1/orders
  • Use kebab-case for multi-word resources: Lowercase with hyphens

    ✅ /data-owner-bc/v1/order-items
    ✅ /data-owner-bc/v1/audit-logs
  • Use forward slash (/) for hierarchy: Show resource relationships

    ✅ /data-owner-bc/v1/resources/{resourceId}/items
    ✅ /data-owner-bc/v1/orders/{orderId}/line-items/{itemId}/attachments
  • Use query parameters for filtering, sorting, pagination: Not part of the path

    ✅ /data-owner-bc/v1/resources?page=1&page_size=10
    ✅ /data-owner-bc/v1/orders?status=active&category=premium
    ✅ /data-owner-bc/v1/resources?sort=created_at&order=desc
  • Don’t use verbs in URIs: HTTP methods define the action

    ❌ GET /data-owner-bc/v1/getResources
    ❌ POST /data-owner-bc/v1/createResource
    ❌ DELETE /data-owner-bc/v1/deleteResource/{id}
  • Don’t use underscores (_): Use hyphens instead

    ❌ /data-owner-bc/v1/order_items
    ❌ /data-owner-bc/v1/audit_logs
  • Don’t use mixed case: Keep URIs lowercase

    ❌ /data-owner-bc/v1/OrderItems
    ❌ /data-owner-bc/v1/AuditLogs
  • Don’t use singular nouns for collections: Maintain consistency

    ❌ /data-owner-bc/v1/resource
    ❌ /data-owner-bc/v1/order
  • Don’t use trailing slashes: Keep URIs clean

    ❌ /data-owner-bc/v1/resources/
    ❌ /data-owner-bc/v1/orders/
  • Don’t use file extensions: Resources are format-agnostic

    ❌ /data-owner-bc/v1/resources.json
    ❌ /data-owner-bc/v1/resources/{id}.xml
  • Don’t put filters in the path: Use query parameters

    ❌ /data-owner-bc/v1/resources/page/1
    ❌ /data-owner-bc/v1/resources/active/true

Each microservice must expose Swagger UI and JSON endpoints:

  • UI: /{prefix}/{version}/api-docs
  • JSON: /{prefix}/{version}/json-docs (used by docs-gateway to aggregate all specs)

Example (local development):

  • Auth UI: http://localhost:5001/auth/v1/api-docs
  • Data Owner UI: http://localhost:4000/data-owner-bc/v1/api-docs
  • Data Owner JSON: http://localhost:4000/data-owner-bc/v1/json-docs
  • Keep URIs lowercase, kebab-case for bounded contexts; plural nouns for collections
  • Prefer IDs in path for identity; use query params for filtering, sorting, pagination
  • Align docs structure with service routes for discoverability