← API

Resource Nesting in API Paths

Context and Problem Statement

Some existing API endpoints contain redundant info (e.g. user ID, institution ID, or account ID) in the path. As an example, the user ID in /users/:userId/accounts/:accountId seems to be redundant because an account can only belong to one user – it could conceivably be flattened to /accounts/:accountId.

Decision Drivers

  • Use cases and technical reasons why the redundant path info is required
  • Ease of use and intuitiveness of API
  • Ease of migrating to a new pattern
  • Consistency across API

Decision Outcome

For technical reasons and to be flexible for future changes, we should continue with the existing “nesting” pattern.

Considered Options

  • Keep the existing “nesting” pattern, e.g. /users/:userId/accounts/:accountId
  • Use flatter paths when possible, e.g. /accounts/:accountId

Pros and Cons of the Options

Nesting pattern

Pros

  • Existing services don’t need to be migrated/converted.
  • Having IDs in the path segments that are validated by the API gateway mean they do not need to be validated by the downstream services.
  • The API gateway has existing checks for some path variables. If concerned about a check complicating a service, it’s possible that the API gateway could implement it instead.

Cons

  • Services need to check that resources are valid and match, otherwise errors are introduced.
  • It can be hard to use the API if most endpoints are grouped in the documentation under a few resources (users, institutions).

Flatter pattern

Pros

  • Could reduce complexity in the service logic, which could also indirectly benefit security.
  • Some checks can be offloaded to the API gateway.

Cons

  • Some endpoints are used in both Online and Enterprise Admin. There are cases where a user can make a request on behalf of a resource, in which that user may or may not be the owner of that resource:
    • An enterprise user who can make a request on behalf of a consumer user
    • Consumer users who have a joint account where either user can make requests on the shared account
    • Consumer users where a parent can make requests on the child’s account
    • Business users where an agent/subordinate can make requests on behalf of the business owner’s account
  • It’s inflexible if we ever want to change the underlying data model, e.g. drop a constraint of being tied to only one resource, or a user ID belonging to only 1 institution.
  • The MDS architecture currently uses path info (like user ID) for routing.