A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://blog.stoplight.io/consistent-api-urls-with-openapi-and-style-guides below:

Consistent API URLs with OpenAPI and Style Guides

This is the second blog in our Style Guide Rulebook Series, for the first part, go here.

REST APIs are designed around resources, which are any kind of object, data, or service that can be accessed by the client. A resource has an identifier, which is a URL that uniquely identifies that resource. Having consistent and robust URLs – will prove one of the best design decisions to build a good developer experience.

A URL consists of the following parts:

Here are some style guide rules that you can create and enforce using spectral to ensure best practices and consistency within API URLs while designing APIs.

Protocol Always use HTTPS

APIs must use HTTPS protocol unless being called in a local environment i.e. localhost

Example Rule (OAS3.x)


oas3-always-use-https:
	given: $.servers[*].url
	then:
		function: pattern
		functionOptions:
			match:   http://localhost)|(https).*
	message: Servers must use the HTTPS protocol except when using localhost
	formats: oas3
	severity: error

oas2-always-use-https:
	given: $.schemes.*
	then:
		function: enummeration
		functionOptions:
	    values:
		    - https
	message: Servers must use the HTTPS protocol
	formats: oas2
	severity: warn
Host Must be lowercase

URLs are case sensitive but it is bad practice for them to differ based only on capitalization. This can cause a lot of confusion among developers. It is usually expected for URLs to be lowercase.


server-lowercase:
	given: $.servers[*].url
	then:
		function: pattern
		functionOptions:
			match: ^[^A-Z]*$
	message: Server URL must be lowercase
	formats: oas3
	severity: error
Structure

There are multiple conventions that organizations follow to structure their hosts. Some organizations might use *{domain}/api* while others might go for a *api.{name}.com* structure.

Popular URL conventions

Either way, whatever convention you decide on, it is important to stick to it across your API suite. For example, if you want to use `/api` convention, make sure all APIs have that in their hostnames defined in the OpenAPI.


server-has-api:
	given: $.servers[*].url
	then:
		function: pattern
		functionOptions:
	# change match to notMatch if looking to never have /api
			match: ^/api
	message: Server must have /api
	formats: oas3
	severity: error

In case you are going with another convention, it would be a good idea to never have `/api` in the path, in which case change the `Match` to `notMatch`

Versioning

There can be multiple versioning strategies for APIs. Some organizations might use URL versioning while others might go for path-level versioning.

Popular versioning strategies

URL Versioning

One common way to version is on the basepath level e.g. api.example.com/v1. If you go for this versioning strategy, make sure that all basepaths have version numbers in them.


server-version:
	given: $.servers[*].url
	then:
		function: pattern
		functionOptions:
	# use version[1-9] if looking for /version1 instead of /v1
	# change match to notMatch if looking to never have version on host level
			match: ^.*/v[1-9]
	message: Server must have end with a version
	formats: oas3
	severity: error

Moreover, it’s a good idea to just have major versions within your base path. You can enforce that with the following configuration.


server-major-version-only:
	given: $.servers[*].url
	then:
		function: pattern
		functionOptions:
			notMatch: .
	message: Server should only have major versions
	formats: oas3
	severity: error
Path Versioning

If you are using path versioning, make sure that all paths have version numbers in them.


path-casing:
	given: $.paths
	then:
	# Targeting the key of paths object i.e. /products/{productId}
		field: @key
		function: pattern
		functionOptions:
	# For underscore_case: ^/([a-z0-9]+(_[a-z0-9]+)*)?(/[a-z0-9]+(_[a-z0-9]+)*|/{.+})*$
	# For camelCase case: ^/([a-z][a-zA-Z0-9]+)?(/[a-z][a-zA-Z0-9]+|/{[a-z][a-zA-Z0-9]+})*$
			match: ^/([a-z0-9]+(-[a-z0-9]+)*)?(/[a-z0-9]+(-[a-z0-9]+)*|/{.+})*$
	message: Paths must be kebab-case
	severity: error
Path Must be kebab-case

Paths are usually one of the following across popular APIs: kebab-case, underscore_case, or camelCase. It is advisable to use kebab-case, as It typically looks clearer and hence more user-friendly than using underscores (_).

Popular URL casing conventions

Again irrespective of the casing you choose it’s important to stay consistent.

In general, it’s usually preferred to use plural nouns for resources unless a plural doesn’t exist for the noun.


resource-names-plural:
	given: $.paths
	then:
	# Targeting the key of paths object i.e. /products/{productId}
		field: @key
		function: pattern
		functionOptions:
			match: ^((/vd+)*((/[w+-]*s)(/{.*})*)*)$
	message: Resource names should generally be plural
	# Don’t create this as an error, but rather a warning or info level rule,
	# considering there are exceptions for singleton resources.
	severity: warn
Must not have a trailing slash

*/users* and */users/* are considered to be separate paths but it is bad practice for them to differ based only on a trailing slash. This can cause confusion among users of your API.

It is usually preferred to not have a trailing slash.

Again, either way, be consistent by creating a rule.


paths-no-trailing-slash:
	given: $.paths
	then:
	# Targeting the key of paths object i.e. /products/{productId}
		field: @key
		function: pattern
		functionOptions:
			notMatch: /$
	message: Paths must not end with a trailing slash
	severity: error
Don’t use file extensions in Paths

The use of file extensions is simply seen as unnecessary in URLs. This is because it can cause some issues for the end-users if you change the file type of the results. Hence, it might add unnecessary complexity that you would like to avoid.


paths-no-trailing-slash:
	given: $.paths
	then:
	# Targeting the key of paths object i.e. /products/{productId}
		field: @key
		function: pattern
		functionOptions:
	# Feel free to add other extensions to this list
			notMatch: (JSON|json|XML|xml)
	message: Paths must not have file extensions
	severity: error
Don’t add HTTP methods to paths

When you design a REST API, you don’t usually need to mention terms like `get`, `delete` and so on in your `paths`, because this information is conveyed by the HTTP method.


paths-no-trailing-slash:
	given: $.paths
	then:
	# Targeting the key of paths object i.e. /products/{productId}
		field: @key
		function: pattern
		functionOptions:
	# Feel free to add other verbs to this list
			notMatch: (GET|PUT|POST|DELETE|LIST|CREATE|REMOVE)
	message: Paths must not have HTTP verbs in them
	severity: error

paths-version-number:
	given: $.paths
	then:
	# Targeting the key of paths object i.e. /products/{productId}
		field: @key
		function: pattern
		functionOptions:
	# Change match to notMatch if you're not looking for versions on the path level
			match:  (/v[1-9]|/version[1-9])
	message: Paths must have a version in them
	severity: error
Avoid Special Characters

URLs can only be sent and received using the ASCII character set, your API URLs should contain only ASCII characters. However, that does not mean you can just use all the characters. Special characters like %20 should not be used in paths.


paths-avoid-special-characters:
	given: $.paths
	then:
	# Targeting the key of paths object i.e. /products/{productId}
		field: @key
		function: pattern
		functionOptions:
	# Change match to notMatch if you're not looking for versions on the path level
			notMatch:  ^[$&+,;=?@]*$
	message: Avoid using special characters in paths
	severity: warn
Use Nouns for Resource Names

Using nouns for resource names leads to easier-to-use APIs. This can be done via custom functions in Spectral which we’ll cover in another article in this series.

Parameters Don’t include query params as part of the URI

Query parameters in OpenAPI are defined separately. Adding them to the path itself should be avoided.


paths-no-query-params:
	given: $.paths
	then:
	# Targeting the key of paths object i.e. /products/{productId}
		field: @key
		function: pattern
		functionOptions:
			notMatch: ?
	message: Paths should not have query parameters in them. They should be defined separately in the OpenAPI.
	severity: warn
Path Parameter Casing

Path parameters are usually underscore_case or camelCase.

Popular path parameter casing conventions


path-parameters-camelcase:
	given: $..parameters[?(@.in == 'path')].name
	then:
		function: casing
		functionOptions:
			type: camel
			disallowDigits: true
	message: Path parameters should be camelCase and not contain digits
	severity: error
Query Parameter Casing

Query parameters are usually underscore_case or camelCase.

Popular query parameter casing conventions


query-parameters-camelcase:
	given: $..parameters[?(@.in == 'query')].name
	then:
		function: casing
		functionOptions:
			type: camel
			disallowDigits: true
	message: Query parameters should be camelCase and not contain digits
	severity: error

It is usually a good idea to have both query and path parameters follow the same conventions.

Path Parameters should not be defined on the operation level

Path parameters should be defined on the path level instead of the operation level.


path-parameters-camelcase:
	given: $.paths[*][*].parameters[?(@.in == 'path')]
	then:
		function: falsy
	message: Path parameters should be defined on the path level instead of the operation level.
	severity: warn
Mandatory Paths Always define a status path

APIs MUST have a status path defined (/status), to easily get started with an API and ping for status updates.

status-path-defined:
	given: $.paths[*][*]
	then:
		function: truthy
	message: APIs MUST have a status path defined (`/status`)
	severity: warn

With not much standardization and so many conventions to worry about when building REST APIs, a core set of guidelines that everybody agrees on is necessary. Convert them into style guide rules that can then be enforced as part of the design and governance process. A combination of these rules helps you create consistent REST API URLs, which leads to an enhanced developer experience. After all, over 50% of organizations use or plan on using internal style guidelines this year, and standardization is the #1 challenge teams are looking to overcome this year, according to the State of API report (2022). This is simply another way you can implement consistency and standardization in your own API program!

Get started with these rules in this sample project.

For more information on style guides, check out our feature blog or our open-source linting tool, Spectral. If you have other ideas on URL conventions and rules, submit an idea on our product roadmap.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4