REST API URL design best practices
Future proof an API against changing business requirements.
Problem statement
Establishing an API platform can be an alluring strategy for businesses because it allows the business's customer base to create generate new value from the platform in ways that the business could not necessarily foresee. This, in turn, makes the platform more attractive to new customers, creating a virtuous cycle.
API platforms continously evolve as the business learns more about how their API gets used. Successful APIs easily accomodate this natural evolution, rather than resisting it to avoid disruption.
URL design directly impacts the scalabilty, resiliance, evolvability, discoverability, and developer experience of an API. It is important to get right from the beginning.
Success criteria
URL design will impact business and product metrics, more so than performance or engineering metrics. A key concept is product depth, which measures how relevant and useful new features are to customers.
Goal | Signal | Metric |
---|---|---|
Improve customer activation | Customers onboard faster | Time to value, The average time from account creation to production release is less than X days or weeks. |
Increase API longevity | Number of breaking changes | The average number of breaking changes released per month, quarter or year. |
Suport API innovation | Number of releases | The average number of updates released per month, quarter or year. |
Product depth | Depth of usage | The ratio of the average number of distinct endpoints used by a customer in a given period out of the total number of endpoints. |
API efficiency | Requests per business transaction | The average number of API requests needed to perform a meaningful business action or use case. |
Improve developer experience | Developer satisfaction | Net promotor score (NPS), customer effort score (CES), or similar. |
Product requirements
Designing the URLs for a REST API is actually an exercise in resource modelling. Determine the main concepts that the API works with, the relationships between them, and whether they are top level resources or embedded values. Then map these resources to URLs.
See Domain-driven design. https://learn.microsoft.com/en-us/archive/msdn-magazine/2009/february/best-practice-an-introduction-to-domain-driven-design
Regardless of how the API names endpoints, they should be consistent above all. This entails gramatical conventions like using plural forms for collections, the use of underscores or dashes, and the semantic meaning of words.
REST APIs are inherently evolvable, and this is due in part to their use of different endpoints to model different resources.
Adding a new resource can be achieved by simply adding a new URL, which is a backwards compatible change. However, changing the semantics of an existing resource may warrent renaming it, which would be a breaking change. Therefore it is important the each URL is carefully considered both in the context of curernt functionalty and possible future functionality.
When integrating with an API developers often need to work with URLs manually. Choose spellings and case conventions for the path segments that allow the entire URL to be easily typed, selected and copied.
Personally Identifiable Information (PII) is any information related to an identifiable person, such as their name, email address, postal code, date of birth. An increasing amount of jurisdictions have enacted laws protecting personal data and restricting its collection and/or distribution.
Consider a collection of user resources, where each user has a unique email address. The following endpoint might be used to retrieve a User resource:
GET /users/{email}
This is problematic because if any system logs the URL to an insecure location, there is a risk of leaking the list of email addresses known by the system.
Instead give each resource a random identifier and use that as the path parameter in the resource's URL:
GET /users/{user_id}
Client credentials typically appear in the URI if the API key is passed as a query parameter.
See [/authentication] for alternatives and best practices.
If a client is authorized to update certain fields of an object resource but not others, model those fields as a separate resource. This ensures that the security model of your API is straightfoward to reason about.
For example, a support platform might allow customers to create and update support tickets. However the assignee field cannot be updated by the customer as it must be managed by the support team. By factoring the assignee to a separate resource, the RBAC permision model now aligns to the resource structure rather than having different behaviour for different fields:
PUT /tickets/{ticket_id}/assignee
Explore design patterns
Nouns
Address resources with unique URLs.
Nested resources
Describe hierarchical relationships between resources with subpaths.
Plural vs singular
Apply predictable spelling conventions to URLs.
API examples
Here are some examples of public APIs and the URL structures they employ:
Twitter API: Uses a resource-based URL structure to represent tweets, users, and relationships. For example, /users/{user_id}/tweets/{tweet_id}.
GitHub API: Adopts a resource-based URL structure to represent repositories, issues, and pull requests. For instance, /repos/{owner}/{repo}/issues/{issue_number}.
Further reading
- https://www.restapitutorial.com/lessons/restfulresourcenaming.html
According to the URI standard the path is for hierarchical parameters and the query is for non-hierarchical parameters. Ofc. it can be very subjective what is hierarchical for you. https://www.rfc-editor.org/rfc/rfc3986
https://terem.tech/api-design-guidelines-essentials/