"Webhooks" are a popular pattern to deliver notifications between applications and via HTTP endpoints. In spite of pattern usage being widespread, there is no formal definition for Web Hooks. This specification aims to provide such a definition for use with CNCF CloudEvents, but is considered generally usable beyond the scope of CloudEvents.
- 1.1. Conformance
- 1.2. Relation to HTTP
"Webhooks" are a popular pattern to deliver notifications between applications and via HTTP endpoints. Applications that make notifications available, allow for other applications to register an HTTP endpoint to which notifications are delivered.
This specification defines a HTTP method by how notifications are delivered by the sender, an authorization model for event delivery to protect the delivery target, and a registration handshake that protects the sender from being abused for flooding arbitrary HTTP sites with requests.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC2119.
This specification prescribes rules constraining the use and handling of specific HTTP methods and headers.
This specification also applies equivalently to HTTP/2 (RFC7540), which is compatible with HTTP 1.1 semantics.
Notifications are delivered using a HTTP request. The response indicates the resulting status of the delivery.
HTTP-over-TLS (HTTPS) RFC2818 MUST be used for the connection.
The HTTP method for the delivery request MUST be POST.
The Content-Type
header MUST be carried and the request MUST
carry a notification payload of the given content type. Requests without
payloads, e.g. where the notification is entirely expressed in HTTP headers, are
not permitted by this specification.
This specification does not further constrain the content of the notification, and it also does not prescribe the HTTP target resource that is used for delivery.
If the delivery target supports and requires Abuse
Protection, the delivery request MUST include the
WebHook-Request-Origin
header. The WebHook-Request-Origin
header value is a
DNS name expression that identifies the sending system.
The delivery response MAY contain a payload providing detail status information in the case of handling errors. This specification does not attempt to define such a payload.
The response MUST NOT use any of the 3xx HTTP Redirect status codes and the client MUST NOT follow any such redirection.
If the delivery has been accepted and processed, and if the response carries a
payload with processing details, the response MUST have the 200 OK or
201 Created status code. In this case, the response MUST carry a
Content-Type
header.
If the delivery has been accepted and processed, but carries no payload, the response MUST have the 201 Created or 204 No Content status code.
If the delivery has been accepted, but has not yet been processed or if the processing status is unknown, the response MUST have the 202 Accepted status code.
If a delivery target has been retired, but the HTTP site still exists, the site SHOULD return a 410 Gone status code and the sender SHOULD refrain from sending any further notifications.
If the delivery target is unable to process the request due to exceeding a
request rate limit, it SHOULD return a 429 Too Many Requests status code
and MUST include the Retry-After
header. The sender MUST
observe the value of the Retry-After header and refrain from sending further
requests until the indicated time.
If the delivery cannot be accepted because the notification format has not been understood, the service MUST respond with status code 415 Unsupported Media Type.
All further error status codes apply as specified in RFC7231.
The delivery request MUST use one of the following two methods, both of which lean on the OAuth 2.0 Bearer Token RFC6750 model.
The delivery target MUST support both methods.
The client MAY use any token-based authorization scheme. The token can take any shape, and can be a standardized token format or a simple key expression.
Challenge-based schemes MUST NOT be used.
The access token is sent in the Authorization
request header
field defined by HTTP/1.1.
For OAuth 2.0 Bearer tokens, the "Bearer" scheme MUST be used.
Example:
POST /resource HTTP/1.1
Host: server.example.com
Authorization: Bearer mF_9.B5f-4.1JqM
When sending the access token in the HTTP request URI, the client adds the access token to the request URI query component as defined by "Uniform Resource Identifier (URI): Generic Syntax" RFC3986, using the "access_token" parameter.
For example, the client makes the following HTTP request:
POST /resource?access_token=mF_9.B5f-4.1JqM HTTP/1.1
Host: server.example.com
The HTTP request URI query MAY include other request-specific parameters, in which case the "access_token" parameter MUST be properly separated from the request-specific parameters using "&" character(s) (ASCII code 38).
For example:
https://server.example.com/resource?access_token=mF_9.B5f-4.1JqM&p=q
Clients using the URI Query Parameter method SHOULD also send a Cache-Control header containing the "no-store" option. Server success (2XX status) responses to these requests SHOULD contain a Cache-Control header with the "private" option.
Because of the security weaknesses associated with the URI method (see RFC6750, Section 5), including the high likelihood that the URL containing the access token will be logged, it SHOULD NOT be used unless it is impossible to transport the access token in the "Authorization" request header field or the HTTP request entity-body. All further caveats cited in RFC6750 apply equivalently.
Any system that allows registration of and delivery of notifications to arbitrary HTTP endpoints can potentially be abused such that someone maliciously or inadvertently registers the address of a system that does not expect such requests and for which the registering party is not authorized to perform such a registration. In extreme cases, a notification infrastructure could be abused to launch denial-of-service attacks against an arbitrary web-site.
To protect the sender from being abused in such a way, a legitimate delivery target needs to indicate that it agrees with notifications being delivered to it.
Reaching the delivery agreement is realized using the following validation handshake. The handshake can either be executed immediately at registration time or as a "pre-flight" request immediately preceding a delivery.
It is important to understand is that the handshake does not aim to establish an
authentication or authorization context. It only serves to protect the sender
from being told to a push to a destination that is not expecting the traffic.
While this specification mandates use of an authorization model, this mandate is
not sufficient to protect any arbitrary website from unwanted traffic if that
website doesn't implement access control and therefore ignores the
Authorization
header.
Delivery targets SHOULD support the abuse protection feature. If a target does not support the feature, the sender MAY choose not to send to the target, at all, or send only at a very low request rate.
The validation request uses the HTTP OPTIONS method. The request is directed to the exact resource target URI that is being registered.
With the validation request, the sender asks the target for permission to send notifications, and it can declare a desired request rate (requests per minute).
The delivery target will respond with a permission statement and the permitted request rate.
The following header fields are for inclusion in the validation request.
The WebHook-Request-Origin
header MUST be included in the validation request
and requests permission to send notifications from this sender, and contains a
DNS expression that identifies the sending system, for example
"eventemitter.example.com". The value is meant to summarily identify all sender
instances that act on the behalf of a certain system, and not an individual
host.
After the handshake and if permission has been granted, the sender MUST use the
WebHook-Request-Origin
request header for each delivery request, with the value matching that
of this header.
Example:
WebHook-Request-Origin: eventemitter.example.com
The WebHook-Request-Callback
header is OPTIONAL and augments the
WebHook-Request-Origin
header. It allows the delivery target to grant send
permission asynchronously, via a simple HTTPS callback.
If the receiving application does not explicitly support the handshake described here, an administrator could nevertheless still find the callback URL in the log, and call it manually and therewith grant access.
The delivery target grants permission by issuing an HTTPS GET or POST request against the given URL. The HTTP GET request can be performed manually using a browser client.
The delivery target MAY include the WebHook-Allowed-Rate
response in the
callback.
The URL is not formally constrained, but it SHOULD contain an identifier for the delivery target along with a secret key that makes the URL difficult to guess so that 3rd parties cannot spoof the delivery target.
For example:
WebHook-Request-Callback: https://example.com/confirm?id=12345&key=...base64...
The WebHook-Request-Rate
header MAY be included in the request and asks for
permission to send notifications from this sender at the specified rate. The
value is the string representation of a positive integer number greater than
zero and expresses the request rate in "requests per minute".
For example, the following header asks for permission to send 120 requests per minute:
WebHook-Request-Rate: 120
If and only if the delivery target does allow delivery of the events, it MUST
reply to the request by including the WebHook-Allowed-Origin
and
WebHook-Allowed-Rate
headers.
If the delivery target chooses to grant permission by callback, it withholds the response headers.
If the delivery target does not allow delivery of the events or does not expect delivery of events and nevertheless handles the HTTP OPTIONS method, the existing response ought not to be interpreted as consent, and therefore the handshake cannot rely on status codes. If the delivery target otherwise does not handle the HTTP OPTIONS method, it SHOULD respond with HTTP status code 405, as if OPTIONS were not supported.
The OPTIONS response SHOULD include the Allow header indicating the POST method being permitted. Other methods MAY be permitted on the resource, but their function is outside the scope of this specification.
The WebHook-Allowed-Origin
header MUST be returned when the delivery target
agrees to notification delivery by the origin service. Its value MUST either be
the origin name supplied in the WebHook-Request-Origin
header, or a singular
asterisk character ('*'), indicating that the delivery target supports
notifications from all origins.
WebHook-Allowed-Origin: eventemitter.example.com
or
WebHook-Allowed-Origin: *
The WebHook-Allowed-Rate
header MUST be returned if the request contained the
WebHook-Request-Rate
, otherwise it SHOULD be returned.
The header grants permission to send notifications at the specified rate. The value is either an asterisk character or the string representation of a positive integer number greater than zero. The asterisk indicates that there is no rate limitation. An integer number expresses the permitted request rate in "requests per minute". For request rates exceeding the granted notification rate, the sender ought to expect request throttling. Throttling is indicated by requests being rejected using HTTP status code 429 Too Many Requests.
For example, the following header permits to send 100 requests per minute:
WebHook-Allowed-Rate: 100
- RFC2119 Key words for use in RFCs to Indicate Requirement Levels
- RFC2818 HTTP over TLS
- RFC6750 The OAuth 2.0 Authorization Framework: Bearer Token Usage
- RFC6585 Additional HTTP Status Codes
- RFC7230 Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
- RFC7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
- RFC7235 Hypertext Transfer Protocol (HTTP/1.1): Authentication
- RFC7540 Hypertext Transfer Protocol Version 2 (HTTP/2)