Skip to content
ADP
API Design PrincipleBETA

[ADP-308] Resource Design Misc

Defining and Naming Resources

  • SHOULD define useful resources.

    • Resources should be defined to cover 90% of all client use cases. A useful resource should contain as much information as necessary but as little as possible. To support the remaining 10%, allow clients to specify their needs for more/less information by supporting filtering and embedding.

    • Example:

      http
      /events
      /users
  • MUST use domain-specific resource names.

    • API resources represent elements of the application’s domain model. Using domain-specific nomenclature for resource names helps developers understand the functionality and semantics of your resources. For example, "sales-order-items" is superior to "order-items" as it clearly indicates the business object it represents. Similarly, "items" is too general.

    • Example:

      http
      /project-tasks
      /financial-reports
      /employee-records
  • SHOULD model complete business processes.

    • An API should encapsulate the complete business processes, including all resources representing the process. This helps clients understand the business process, fosters a consistent design, and eliminates implicit dependencies between APIs. Additionally, it prevents services from being designed as thin wrappers around databases, which often shifts business logic to the clients.

    • Example:

      http
      /workflows
      /workflows/{workflow-id}/steps
      /workflows/{workflow-id}/actions

Resource Path Design

  • MUST identify resources and sub-resources via path segments.

    • Some API resources may contain or reference sub-resources. Embedded sub-resources, which are not top-level resources, are parts of a higher-level resource and cannot be used outside its scope. Sub-resources should be referenced by their name and identifier in the path segments as follows:

      http
      /resources/{resource-id}/sub-resources/{sub-resource-id}
      • Aim for intuitively understandable URLs where each sub-path is a valid reference to a resource or a set of resources. For instance, if /partners/{partner-id}/addresses/{address-id} is valid, then /partners/{partner-id}/addresses, /partners/{partner-id}, and /partners should also be valid.

      • Example:

        http
        /orders/5678/items/1234
        /orders/5678/items
        /orders/5678
        /orders
  • MAY expose compound keys as resource identifiers.

    • If a resource is best identified by a compound key consisting of multiple other resource identifiers, it is allowed to reuse the compound key in its natural form containing slashes in the resource path:

      http
      /resources/{compound-key-1}[delim-1]...[delim-n-1]{compound-key-n}
    • Example paths:

      http
      /tickets/{event-id}/{seat-number}
      /tickets/{event-id}/{seat-number}/details
      /assignments/{course-id}/{student-id}/grades
      /assignments/{course-id}/{student-id}/submissions/{submission-id}
  • MAY consider using (non-) nested URLs.

    • If a sub-resource is only accessible via its parent resource and may not exist without it, consider using a nested URL structure:

      http
      /projects/{project-id}/milestones/{milestone-id}
      • If the resource can be accessed directly via its unique id, then it should be exposed as a top-level resource:

        http
        /projects/1234
        /milestones/5678

Resource Complexity and Levels

  • SHOULD limit the number of resource types:
    • To maintain manageability and service evolution, follow "functional segmentation" and "separation of concern" design principles. Avoid mixing different business functionalities in the same API definition. Aim to limit the number of resource types exposed via an API. For example, the following resources count as three resource types: students, courses, and student’s related courses.

      http
      /students
      /students/{id}
      /students/{id}/settings
      /students/{id}/courses
      /students/{id}/courses/{course-id}
      /courses
      /courses/{course-id}
      • /students and /students/id are both student resource.
      • /students/{id}/settings where settings won’t have an identifier and cannot exist without student, it is treated as part of the student resource.
      • /students/{id}/courses and /students/{id}/courses/{course-id} is a course type resource which has 1 to 1 and 1 to many relationship with the specific student /student/{id}.
  • SHOULD limit the number of sub-resource levels:
    • Use sub-resources if their lifecycle is loosely coupled to the main resource. You should use no more than three sub-resource (nesting) levels, as more levels increase API complexity and URL path length.

    • Example:

      DON’T

      http
      /libraries/{library-id}/books/{book-id}/chapters/{chapter-id}
      /companies/{company-id}/departments/{department-id}/employees/{employee-id}