Webhook Client
Webhook Client
A webhook client consists of a HTTPS endpoint to receive the webhooks (and your relevant downstream processing), a client to obtain key sets (JWKS), a cache of the JWKS, and a scheduled job to poll for a new JWKS.
At a high level processing a webhook consists of (more details are provided in the following sections):
- Validating the signature in the
X-JWS-Signature
HTTP header - Returning a
400 Invalid Request
if the signature orce-time
is invalid - Parsing the HTTP request with the Cloud Events SDK
- Processing the webhook
- Returning a
200 OK
if processed successfully, otherwise returning an appropriate HTTP error code
Server Setup
Create an HTTPS endpoint which we will call to deliver webhooks. This endpoint can optionally be secured by basic auth, but must be HTTPS. Webhooks are cryptographically signed; the details to implement verification of this signature are given in the next section.
Received webhooks should be acknowledged with a 200 OK
response; you should respond only once you are certain you have persisted or processed the webhook as once it is successfully acknowledged it cannot be resent. Responding with any other HTTP status code will cause the webhook to be enqueued for periodic retry. If at the end of the retry period for the webhook we still have not received a 200 OK
acknowledgement the webhook will remain available for on-demand retry via the Events API
Idempotency
Webhooks are delivered at-least-once, therefore if you require once-and-only-once delivery you should use the ce-id
header, which is unique per webhook, to implement and idempotent client and handle possible duplicates. A simple implementation of this would keep a set of ce-id
's that you have successfully processed, check if this set contains the incoming ce-id
and respond with 200 Ok
without processing the message if the set does contain it.
It's important to compare
ce-id
only for events you have successfully processed, otherwise you will potentially discard retry attempts after failures!
Ordering
Webhooks are sent with best-effort ordering per topic. The topic is the portion prior to the '-' in the ce-type
. There is no guarantee to the ordering across topics.
Versioning
Entity versioning can be determined using the ce-time
header unless the specific entity provides a more precise version field defined in its schema. If a version field is provided, that should be used over ce-time
Replay Automation
You can follow along with actual code for this section in the Replay Event recipe.
List Events can be used in an ad hoc fashion to query about passed events, both failed and successful. However, this section covers how to build an automation to replay all failed events for a subscription. For this example, we will use a replay period of 24 hours.
- Call the
List events
endpoint with the following parameters:status.eq=FAILURE
from=time.Now() - 24 hours
//Adjust if replaying on a different schedulelimit=50
offset=0
- If
response.pagination.total
> 50- Repeat Step 1
ceiling(response.pagination.total/50)
times adjusting offset as needed, e.g. if the total is 102, thenList events
needs to be called a total of 3 times with a limit of 50- Call 1: limit=50, offset=0
- Call 2: limit=50, offset=50
- Call 3: limit=50, offset=100
- Merge all results into a single array of events. It's important to maintain ordering as we return them in chronological order.
- Repeat Step 1
It's important to get the complete list of events before starting to request their replay as successfully replaying an event affects the pagination results.
For each event returned from List events
, in chronological order (as returned from List events
), call the Replay An Event
endpoint. A successful retry is indicated by a 200 Ok
response with a status of SUCCESS
in the body. As event ordering is important, you should not move on to replaying a subsequent event until the prior one has been replayed successfully.
Ad Hoc Replay
These APIs can also be used outside of automation. List events
can be used simply to get counts for your subscription. The additional filters (statuses other than FAILURE
and the to
time) can be used in this case. The status enum has the following meanings:
Status | Definition |
---|---|
FAILURE | We were unable to send you the event and our automated retries have been exhausted. To get this event you must use the Replay API |
PENDING | We are in the process of sending this event to you but haven't successfully delivered it yet. This could be either because it has just arrived or because the initial delivery attempt failed and it is in the automated retry process |
SUCCESS | We delivered the event and you responded with a 200 Ok |
Updated almost 2 years ago