What are OpenAPI runtime expressions and how are they used? #
Runtime expressions are a specialized feature of the OpenAPI Specification that allows certain fields to reference values from the HTTP request or response at the time the API call is made. Unlike static values in an OpenAPI document — which are known at design time — runtime expressions are evaluated dynamically against the actual HTTP message. They appear in two specific contexts: Links (defining relationships between operations) and Callbacks (defining webhook URLs derived from request data).
What Problem Do Runtime Expressions Solve? #
OpenAPI documents describe static contracts: the shape of requests and responses is defined once and applies to all calls. But some API behaviors are inherently dynamic: the URL for a follow-up request depends on the ID returned in the first response; a webhook callback URL is provided by the client in the original request.
Runtime expressions provide a standardized way to express these dynamic references without resorting to free-text descriptions. A runtime expression like $response.body#/id unambiguously means “the value of the id field in the response body” — a machine-readable reference that tools can understand and use.
Runtime Expression Syntax #
The syntax follows this pattern:
expression = ( "$url" | "$method" | "$statusCode" | "$request." source | "$response." source )
source = ( header-reference | query-reference | path-reference | body-reference )
header-reference = "header." token
query-reference = "query." name
path-reference = "path." name
body-reference = "body" ["#" json-pointer]
Source References #
| Expression | Description |
|---|---|
$url | The full URL of the request |
$method | The HTTP method of the request (GET, POST, etc.) |
$statusCode | The HTTP status code of the response |
$request.header.{name} | A specific request header value |
$request.query.{name} | A specific query parameter value |
$request.path.{name} | A specific path parameter value |
$request.body | The entire request body |
$request.body#/pointer | A field in the request body using a JSON Pointer |
$response.header.{name} | A specific response header value |
$response.body | The entire response body |
$response.body#/pointer | A field in the response body using a JSON Pointer |
JSON Pointer syntax (RFC 6901) is used to navigate nested objects. A pointer like #/data/user/id navigates to body.data.user.id in the response body.
Use in Links #
Links are the primary use case for runtime expressions. A Link describes how the result of one operation can be used as input to another operation, modeling the hypermedia-like relationships between operations in the API.
Links are defined in components/links and referenced from response objects:
paths:
/users:
post:
summary: Create a user
operationId: createUser
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserRequest'
responses:
"201":
description: User created
content:
application/json:
schema:
$ref: '#/components/schemas/User'
links:
GetUserById:
operationId: getUser
parameters:
userId: '$response.body#/id'
description: >
The `id` value returned in the response can be used as
the `userId` parameter in `GET /users/{userId}`
ListUserOrders:
operationId: listUserOrders
parameters:
userId: '$response.body#/id'
description: >
The `id` value can be used as `userId` in
`GET /users/{userId}/orders`
/users/{userId}:
get:
summary: Get a user
operationId: getUser
parameters:
- name: userId
in: path
required: true
schema:
type: string
In this example:
- The
createUseroperation returns a User object with anidfield - The
GetUserByIdlink says: “use$response.body#/id(theidfrom the create response) as theuserIdparameter of thegetUseroperation” - Documentation tools can render this as a clickable link between operations; API clients can use it to automatically chain operations
Link Parameters vs. requestBody #
Links can reference parameters (path, query, header, cookie) or a requestBody. The parameters object maps parameter names to runtime expressions:
links:
CreateOrderForUser:
operationId: createOrder
parameters:
userId: '$response.body#/id'
requestBody:
description: Use the user ID from the create response
$ref: '#/components/requestBodies/CreateOrderRequest'
Use in Callbacks #
Callbacks describe webhook-style notifications that the server will send to the client. The callback URL is often provided by the client in the original request body. Runtime expressions allow the callback URL to be derived from request fields:
paths:
/subscriptions:
post:
summary: Subscribe to order status updates
operationId: createSubscription
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [callbackUrl]
properties:
callbackUrl:
type: string
format: uri
description: URL to receive order status updates
example: https://myapp.example.com/webhooks/orders
eventTypes:
type: array
items:
type: string
callbacks:
onOrderStatusUpdate:
'{$request.body#/callbackUrl}':
post:
summary: Order status update notification
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/OrderStatusEvent'
responses:
"200":
description: Callback received successfully
The callback path key '{$request.body#/callbackUrl}' is the runtime expression wrapped in curly braces. It means: “when sending the webhook, use the callbackUrl value from the subscription request body as the URL.”
This makes the callback’s destination URL dynamic and derived from the actual API call, which is the correct model for webhook registration APIs.
Runtime Expressions vs. Template Expressions #
It’s worth distinguishing runtime expressions from OpenAPI’s Server Variable template syntax ({variable}). Server variable templates use {name} without a dollar sign and are substituted at configuration time (before any API calls), while runtime expressions use $source.path syntax and are evaluated against actual HTTP messages at runtime.
Tooling Support #
Runtime expression support varies across tools:
- Documentation renderers (Swagger UI, Redoc, Scalar) display Links as navigable relationships between operations, showing which operations can follow from a given response
- SDK generators may use Links to generate client-side helper methods that automatically chain operations (e.g.,
createUser().then(user => getUser(user.id))) - Mock servers like Prism display link information in responses but generally don’t automatically execute linked operations
- API explorers may use Links to pre-populate operation inputs with values from previous response outputs
Limitations #
Runtime expressions in OpenAPI are descriptive, not executable:
- They do not instruct the server to perform any action
- They cannot express complex transformations (only simple field references)
- They have no conditional logic
- Tools are not required to act on them; their presence in the document does not guarantee any behavior
For more complex API workflow definitions — including sequencing, conditions, and transformations across multiple operations — the Arazzo Specification (an OpenAPI Initiative specification) provides a dedicated workflow description language built on top of OpenAPI.
Conclusion #
OpenAPI runtime expressions are a focused mechanism for referencing HTTP request and response values in Links and Callbacks. In Links, they express the relationships between operations — how one operation’s output feeds another’s input — enabling documentation renderers and SDK generators to surface navigation paths through the API. In Callbacks, they allow webhook URLs to be derived from client-provided request data. While their use is limited to these two specific contexts and their tooling support varies, runtime expressions provide a machine-readable vocabulary for describing the dynamic data flows that exist between API operations.
Last updated on April 30, 2026.