OpenAPI Tips
Webhooks & Callbacks in OpenAPI/Swagger
Nolan Di Mare Sullivan
December 5, 2023
Announcing: OpenAPI Reference
Hi! These blog posts have been popular, so we’ve built an entire OpenAPI Reference Guide to answer any question you have.
It includes detailed information on webhooks & callbacks.
Happy Spec Writing!
What Are Webhooks and Callbacks and When Are They Used in OpenAPI?
A traditional REST API functions by allowing users to trigger a request that the API immediately sends a response to; this is known as a pull mechanism. Webhooks and callbacks expand the possible ways of working with the API beyond this traditional call/response interface.
webhooks
are a mechanism that allows an API to send real-time data to a user as soon as an event occurs (without requiring the user to take any action). The user simply needs to subscribe to the event stream and provide a URL to start receiving data.callbacks
are a mechanism that allows a user to specify a URL to which an API request should send a certain response.
Which Should You Use?
Both webhooks and callbacks are a way of defining asynchronous communication with an API. You can use webhooks and callbacks somewhat interchangeably, but we recommend sticking to the following convention:
- If users will be receiving a stream of data over time with a consistent format, you should use webhooks.
- If the initial API request triggers a long-running job and the user wants to receive the response asynchronously, use callbacks.
A Short History of Webhooks and Callbacks in OpenAPI
Callbacks were added to the OpenAPI Specification in version 3 (opens in a new tab) in 2017; webhooks in version 3.1 (opens in a new tab) in 2021.
OpenAPI Version | Date | Notes |
---|---|---|
3.0.0 (opens in a new tab) | 2017-07 | Callbacks added |
3.0.1 (opens in a new tab) | 2017-12 | |
3.0.2 (opens in a new tab) | 2018-10 | |
3.0.3 (opens in a new tab) | 2020-02 | |
3.1.0 (opens in a new tab) | 2021-02 | Webhooks added |
In OpenAPI, webhooks and callbacks are defined as follows:
webhooks
are a top-level entry represented by a map of Path Item Objects or OpenAPI Reference Objects that are keyed by the unique name of the webhook. Webhooks specify what is pushed to a given URL but provide no way of setting the target URL. The subscription itself might be configured by a sales representative, entered during the sign-up process when a user creates an account on your system, or even set by a separate API endpoint (duplicating how callbacks work).- A
callback
is a map of runtime expressions (that represent a URL the callback request is sent to) to a Path Item Object or Reference that defines a request to be initiated by the API provider and a potential response to be returned. The expression, when evaluated at runtime, will resolve to a URL represented in the parameters, request body, or response body of the parent operation.
A valid API schema can comprise only webhooks. For your schema to be valid, it needs only an info
element and at least one of paths
, webhooks
, or components
.
Creating a Webhook in OpenAPI
Below is the same notification service described as a webhook.
Add a Webhook Description
Add a webhook named concertAlert
that describes what information will be pushed to a subscriber. This is the only requirement for a valid schema with a webhook.
Notice that there is no way for a user to register for this alert using the API, nor is the URL on which the user will be notified specified.
Add a Subscription Path
To allow users to register for alerts without using a callback, you can optionally mimic callback functionality by proving a subscription endpoint in a /path
.
OpenAPI has no way to explicitly link the webhook with the registration. You will have to make this clear to users in your description
elements or by grouping the operations with tags.
openapi: 3.1.0info:title: SpeakeasyClubversion: 1.0.0webhooks:concertAlert:post:summary: Concert alertdescription: Notify the registered URL with details of an upcoming concertrequestBody:required: truecontent:text/plain:schema:type: stringexample: "The Swing Machine will be playing at 19h30 tomorrow. $10 cover charge."responses:"200":description: Notification received by the external service.
Creating a Callback in OpenAPI
Let’s create a simple callback example. We use YAML rather than JSON for readability.
Add a Subscription Path
Now add a single /registerForAlert
endpoint that a user can pass a URL to for concert notifications. We disregard error responses for brevity.
Add a Callback to the Path
Finally, add a callback to the endpoint. The callback gets the URL using {$request.body#/url}
from the POST to send a string describing the next concert.
Selecting parameters in a POST request in this way is called a runtime expression (opens in a new tab). Read more about the syntax in the specification.
openapi: 3.1.0info:title: SpeakeasyClubversion: 1.0.0paths:/registerForAlert:post:summary: Register for concert alertsdescription: Register a URL to be called when new concerts are scheduled.requestBody:required: truecontent:application/json:schema:type: objectproperties:url:type: stringformat: uridescription: The URL to be notified about approaching concerts.example:url: "http://example.com/notify"responses:"200":description: Registration successful.callbacks:concertAlert:"{$request.body#/url}":post:summary: Concert alertdescription: Notify the registered URL with details of an upcoming concert.requestBody:required: truecontent:text/plain:schema:type: stringexample: "The Swing Machine will be playing at 19h30 tomorrow. $10 cover charge."responses:"200":description: Notification received by the external service.
Syntax Rules
The webhooks
element has identical syntax to the paths
element. Both are lists of Path Item Objects (opens in a new tab). (This makes sense if you consider that a webhook is like a reverse path: Just as paths describe endpoints on the server’s API, webhooks describe endpoints on the user’s API.)
A callback
is also a Path Item Object.
This means a webhook or callback has all the following path properties available to it: $ref
, summary
, description
, get
, put
, post
, delete
, options
, head
, patch
, trace
, servers
, and parameters
.
Callbacks and Webhooks in Speakeasy
Speakeasy will automatically include your webhook types in generated code and documentation. You don’t need to do anything extra or include Speakeasy extensions (x-speakeasy
) to use these features.
Tips
Here are a few more considerations when designing your API’s use of webhooks and callbacks:
- If using callbacks, you can manage multiple subscriptions in the same endpoint using multiple parameters — one for each URL. This might be neater than creating one registration path per callback.
- If using webhooks, be sure to explain in the summary or description exactly how users can subscribe and unsubscribe, as well as any associated fees for the service.
- Any
description
elements may use CommonMark syntax (opens in a new tab). - Callbacks and webhooks must have unique names in the schema. The names are case-sensitive.
- Make your webhooks idempotent. Sending or receiving the same event multiple times should not cause side effects.
- Protect your API from DDoS attacks by making sure webhooks are protected from spam registrations with authentication and that limits are in place for the rate and size of your messages.
What About AsyncAPI Standard?
OpenAPI is a general-purpose API specification that can be used for asynchronous APIs, but it is not necessarily optimized for them. If you find that OpenAPI is insufficient for your use case, you should check out AsyncAPI (opens in a new tab). Just be aware that AsyncAPI is still in the early stages of development and is not yet widely supported by the tooling ecosystem.