Links & Callbacks
These decorators document advanced OpenAPI features: response-driven navigation (links) and webhook delivery (callbacks). Both are optional — most APIs don't need them.
Response links
OpenAPI links describe how values from a response can be used as input to another operation. This is useful for HATEOAS-style navigation in the generated spec.
Basic usage
import { SwaggerLink } from '@moostjs/swagger'
@SwaggerLink('GetUser', {
operationId: 'getUser',
parameters: { userId: '$response.body#/id' },
})
@SwaggerResponse(201, UserDto)
@Post()
create(@Body() dto: CreateUserDto) {
// The 201 response includes a link: "use the id from this response to call getUser"
}Target modes
A link must reference a target operation. Three modes are supported:
By operationId string — references any operation by its operationId:
@SwaggerLink('GetUser', {
operationId: 'getUser',
parameters: { userId: '$response.body#/id' },
})By handler reference — resolved to the actual operationId at mapping time:
@SwaggerLink('GetUser', {
handler: [UserController, 'getUser'],
parameters: { userId: '$response.body#/id' },
})This is the recommended approach within a Moost application: the link survives operationId changes because it is resolved from the controller at mapping time. Note that only the controller class reference is checked by TypeScript — the method name is a plain string, and a stale name causes the link to be silently omitted from the spec (see Options reference).
By operationRef — JSON pointer for cross-document or non-standard references:
@SwaggerLink('ExternalOp', {
operationRef: '#/paths/~1users~1{id}/get',
parameters: { id: '$response.body#/userId' },
})Multiple links
Stack multiple @SwaggerLink decorators to add several links to the same response:
@SwaggerLink('GetUser', {
handler: [UserController, 'getUser'],
parameters: { userId: '$response.body#/id' },
})
@SwaggerLink('ListOrders', {
handler: [OrderController, 'listByUser'],
parameters: { userId: '$response.body#/id' },
})
@SwaggerResponse(201, UserDto)
@Post()
create(@Body() dto: CreateUserDto) { /* ... */ }Status codes
By default, a link attaches to the default success status code for the HTTP method (200 for GET/PUT, 201 for POST, 204 for DELETE). Target a specific status code with the 3-argument form:
@SwaggerLink(201, 'GetCreated', {
operationId: 'getItem',
parameters: { id: '$response.body#/id' },
})
@SwaggerLink(200, 'GetUpdated', {
operationId: 'getItem',
parameters: { id: '$response.body#/id' },
})Options reference
The options object is exported as TSwaggerLinkOptions:
| Field | Type | Description |
|---|---|---|
operationId | string | Target operation by operationId |
operationRef | string | Target operation by JSON pointer |
handler | [Class, string] | Target by controller class + method name (resolved at mapping time) |
parameters | Record<string, string> | Map of parameter names to runtime expressions |
requestBody | string | Runtime expression for the request body |
description | string | Human-readable description of the link |
server | { url, description? } | Alternative server for the link target |
Exactly one of operationId, operationRef, or handler must be provided. If handler cannot be resolved (e.g., the target controller is not registered, or the method name no longer matches a handler), the link is silently skipped.
Callbacks (webhooks)
OpenAPI callbacks document requests your server sends to a client-provided URL — typically for webhook delivery after an event.
Basic usage
import { SwaggerCallback } from '@moostjs/swagger'
@SwaggerCallback('onEvent', {
expression: '{$request.body#/callbackUrl}',
requestBody: EventPayloadDto,
description: 'Event notification sent to subscriber',
})
@Post('subscribe')
subscribe(@Body() dto: SubscribeDto) {
// Documents: "after subscribing, server POSTs EventPayloadDto to the callbackUrl"
}The expression is an OpenAPI runtime expression that resolves to the callback URL at runtime. The most common pattern is '{$request.body#/callbackUrl}' — a URL provided in the request body.
Custom method, content type, and response
By default, callbacks use POST, application/json, and expect a 200 OK response. Override any of these:
@SwaggerCallback('onUpdate', {
expression: '{$request.body#/webhookUrl}',
method: 'put',
contentType: 'text/plain',
responseStatus: 204,
responseDescription: 'Acknowledged',
})
@Post('subscribe')
subscribe(@Body() dto: SubscribeDto) { /* ... */ }Multiple callbacks
Stack multiple @SwaggerCallback decorators to document several webhooks on the same operation:
@SwaggerCallback('onCreated', {
expression: '{$request.body#/callbackUrl}',
requestBody: CreatedEventDto,
})
@SwaggerCallback('onUpdated', {
expression: '{$request.body#/callbackUrl}',
requestBody: UpdatedEventDto,
})
@Post('subscribe')
subscribe(@Body() dto: SubscribeDto) { /* ... */ }Options reference
The options object is exported as TSwaggerCallbackOptions:
| Field | Type | Default | Description |
|---|---|---|---|
expression | string | (required) | Runtime expression resolving to the callback URL |
requestBody | type/schema | — | Schema for the payload your server sends. Resolved via the schema pipeline |
method | string | 'post' | HTTP method your server uses |
contentType | string | 'application/json' | Content type for the payload |
description | string | — | Description for the callback operation |
responseStatus | number | 200 | Expected response status from the receiver |
responseDescription | string | 'OK' | Description for the expected response |