OpenAPI Servers
The servers section of OpenAPI is a straightforward yet powerful way to communicate the base URLs of API across different stages of the API lifecycle, or in different environments the end-users might be interested in. There may only be one API, but there is a development server, testing server, maybe a mocking server, or a sandbox for interacting with the API without real-world consequences, as well as the production API. People need to be able to find these servers and guessing is not a fun or productive solution.
Here is an example of defining API servers in OpenAPI:
servers:- url: https://speakeasy.bardescription: Production- url: https://sandbox.speakeasy.bardescription: Sandbox- url: http://localhost:8088description: Developmentx-internal: true
Servers can be defined at the Document level, the Path level, or the Operation level, and since OpenAPI v3.0 can be a combination of domain names, subdirectories, ports, protocols, and even variables. This all gives flexibility in how everything “before the path” is defined, especially helping APIs that might have multiple domains, or dynamic domains.
Server Object in OpenAPI
A Server Object describes a single server that is available for the API.
Field | Type | Required | Description |
---|---|---|---|
url | String | ✅ | A URL to the server. This can be an absolute URL or a relative URL to the hosted location of the OpenAPI document. The URL also supports variable substitutions via Templating. |
description | String | A description of the server. CommonMark syntax (opens in a new tab) can be used to provide a rich description. | |
variables | Server Variables | A map of variable names to Server Variable Objects that can be used for variable substitution via Templating. | |
x-* | Extensions | Any number of extension fields can be added to the Server Object (for example, x-speakeasy-server-id that allows IDs to be assigned to each server for easier selection via Speakeasy SDKs) that can be used by tooling and vendors. |
Absolute or relative
The server URL can be a full URL or it could be a relative path.
If the URL is an absolute path, it must conform to RFC 3986 (opens in a new tab) (schema://host{:port}{/path}
) and not include the query string, and must be URL encoded (except for the templating delimiters {}
if not part of the URL).
The URL can also be a relative path to where the OpenAPI document is hosted (/api
), at which point it will take the server from wherever the OpenAPI is hosted. For a document hosted at https://speakeasy.bar/openapi.yaml
, the resulting URL will be https://speakeasy.bar/api
.
Path or operation servers
If a list of servers is provided at the paths
level, the servers will override any servers provided at the document level. If a list of servers is provided at the operation
level, the servers will override any servers provided at the paths
and document levels.
openapi: 3.1.0servers:- url: https://speakeasy.bardescription: Productionpaths:/drinks/{id}/image:servers:- url: https://uploads.speakeasy.bardescription: Upload serverput:summary: Upload an image for a drinkparameters:- name: idin: pathrequired: truedescription: The ID of the drink to upload an image for.schema:type: stringrequestBody:content:image/png:schema:type: stringformat: binaryresponses:"200":description: Image uploaded successfully.
In this example, the servers
defined at the operation level will override the servers
defined at the document level. The server URL for the operation will be https://uploads.speakeasy.bar
, while the rest of the API will still use https://speakeasy.bar
.
Splitting out functionality like this can happen as APIs evolve, especially in this case of an upload operation moving a dedicated endpoint to avoid spamming the main API server with large files.
Server variables
Server variables offer a convenient way to modify server URLs, covering simple patterns such as environment names, geographical regions, or covering wildcards like user-generated subdomains. These variables are part of the server object, and allow for more flexible API configurations without hardcoding every possible server option.
For instance, consider an API that is deployed across multiple regions, such as the United States, Europe, and Asia. Instead of listing each server URL separately, use a server variable to represent the region.
servers:- url: "https://{region}.api.speakeasy.bar"description: Edge Servervariables:region:default: usdescription: Please select the appropriate server.enum:- us- eu- asia
In this example, {region}
is a server variable, and the enum
restricts this to three possible values: us
, eu
, and asia
. The default value is us
, which means if the region is not specified, tooling can know which value to use. This setup allows clients to dynamically select the appropriate regional server by substituting the {region}
variable in the URL template, resulting in https://asia.api.example.com
.
Learn more about server variables in OpenAPI.
Best practices
Best server first
Depending on what tools are being used, servers can be used to do different things. For documentation the first server in the list is usually considered to be the default server to use, with logic to select other servers to use left up to tooling or the API consumer.
Use x-internal to hide internal servers
The x-internal
attribute is not officially part of the specification, but it is a popular extension supported by many tools. Setting x-internal: true
will hide these servers from public facing documentation for example. This allow them to be displayed for development and testing information in OpenAPI, but avoids confusing end-users with details about the internal setup.
servers:- url: http://localhost:8088description: Developmentx-internal: true