Introduction
APIs evolve. The Web Function Versioning extension lets a package declare that it supports multiple versions, which version it currently describes, and which versions callers may request. Version identifiers are opaque strings: the specification does not define semver, integers, or any other format.
This extension is optional. Packages that do not set the versioned flag are not subject to the rules in this document.
Activation
A package activates versioning by including the versioned flag in its flags array. When this flag is present, the package MUST also include the version and versions keys described below. Clients that implement this extension SHOULD check for the versioned flag before sending the Api-Version header or interpreting version metadata.
Package keys
When the versioned flag is set, the package MUST contain the following keys in addition to the standard package definition:
| Key and type | Description |
|---|---|
version string | The version that this package describes. An opaque string. |
versions array of strings | The versions that are available. Each entry is an opaque string. The value of version MUST be an element of this array. |
The format of version strings is left to the API developer. Examples include "1", "v2", "2024-06-01", or "beta". Clients MUST treat version strings as opaque and compare them case-sensitively unless the API documentation states otherwise.
HTTP Api-Version header
When interacting with a versioned package, clients MAY select a version by sending the following request header:
Api-Version: <version>Here, <version> must be one of the strings listed in the package's versions array. The server uses this header to determine which version of the API to apply for the request. How the server resolves an unknown or missing version (for example, defaulting to the current version or returning an error) is left to the API developer and SHOULD be documented in the package's docs field.
The Api-Version header is the mechanism defined by this extension. Servers that honor the versioned flag SHOULD read this header on endpoint invocations under the package's base_url.
Client behavior
Clients that implement this extension SHOULD follow this logic:
- Retrieve or load the package definition.
- If the
versionedflag is absent, do not sendApi-Versionand ignoreversionandversions. - If the
versionedflag is present, note theversionandversionsvalues for display, configuration, or validation. - When the user or application selects a version, include
Api-Version: <version>on requests to endpoints in that package, where<version>is one of the strings inversions.
Clients MUST NOT infer semantics from the shape of version strings (for example, assuming that "2" is newer than "1").
Alternative versioning strategies
The Web Function endpoint model treats the function name as the last path segment and the request body as the sole carrier of parameters. That design allows two additional versioning strategies that require no changes to generic clients and no use of the versioned flag or Api-Version header. API developers may use these alone or alongside the extension.
Function suffixing
The version can be encoded in the endpoint name. For example, get-users and get-users-v2 are distinct endpoints discovered from the package's endpoints array. Clients invoke the appropriate URL by name, exactly as they would for any other endpoint. No header or package flag is required.
Version in base_url
The version can be encoded in base_url. For example, https://api.example.com/v1/ and https://api.example.com/v2/ can be separate packages (or the same logical API with different base URLs). Endpoint names remain unversioned; the version is selected by which base URL the client calls. Again, no header or package flag is required.
These strategies are complementary. A service might publish a versioned package for discoverability while also exposing list-items-v2 for backward compatibility, or serve /v1/ and /v2/ base URLs without declaring versioned at all.
Example package definition
The following package declares versioning and describes version "2" of the API:
{
"base_url": "https://api.example.com",
"name": "ExamplePackage",
"flags": ["versioned"],
"version": "2",
"versions": ["1", "2"],
"docs": "Example API. Send Api-Version to select a version; defaults to the current version when omitted.",
"errors": [],
"endpoints": [
{
"name": "find-user-by",
"returns": ["object"],
"flags": [],
"group": "users",
"docs": "Retrieves user data for the selected API version.",
"errors": [],
"arguments": [
{
"name": "id",
"type": "string",
"flags": ["required"],
"docs": "Identifier of the user."
}
]
}
]
}
Example request with Api-Version
POST /find-user-by
Content-Type: application/json
Accept: application/json
Api-Version: 1
{
"id": "user_abc123"
}