Understand Prefect Cloud webhooks, their configuration, and how to use templates to transform incoming HTTP requests into Prefect events.
https://api.prefect.cloud/hooks/
. For example: https://api.prefect.cloud/hooks/AERylZ_uewzpDx-8fcweHQ
.
Prefect Cloud assigns this URL when you create a webhook; it cannot be set through the API. You may rotate your webhook URL at any time without losing the associated configuration.
All webhooks may accept requests with the most common HTTP methods:
GET
, HEAD
, and DELETE
for webhooks that define a static event template, or a template that does not depend on the body of the HTTP request. The headers of the request will be available for templates.POST
, PUT
, and PATCH
when the webhook request includes a body. See How HTTP request components are handled for more details on how the body is parsed.204 No Content
response when they are successful or a 400 Bad Request
error when there is any error interpreting the request. For more visibility when your webhooks fail, see the Troubleshooting Webhook Configuration section below.
Authorization
header of your webhook requests:
jinja2-humanize-extensions
package.
Your goal when defining an event template is to produce a valid JSON object that defines (at minimum) the event
name and the resource["prefect.resource.id"]
, which are required of all events. The simplest template is one in which these are statically defined.
json.loads
.recommendations
machine learning model has been updated. Those models are produced on a daily schedule by another team that is using cron
for scheduling. They aren’t able to use Prefect for their flows yet, but they are happy to add a curl
to the end of their daily script to notify you. Because this webhook is only used for a single event from a single resource, your template can be entirely static:
GET
request with no body, so the team you are integrating with can include this line at the end of their daily script:
event
and resource
definition, which is not a completely fleshed out event. Prefect Cloud sets default values for any missing fields, such as occurred
and id
, so you don’t need to set them in your template. Additionally, Prefect Cloud adds the webhook itself as a related resource on all of the events it produces.
If your template does not produce a payload
field, the payload
defaults to a standard set of debugging information, including the HTTP method, headers, and body.
cron
scripts to POST
a small body that includes the ID and name of the model that was updated:
POST
request and the body will include a traditional URL-encoded form with two fields describing the model that was updated: model
and friendly_name
. Here’s the webhook code that uses Jinja to receive these values in your template and produce different events for the different models:
POST
requests will produce events with those variable resource IDs and names. The other statically defined parts, such as event
or the producing-team
label you included earlier, will still be used.
default
filter to handle missing valuesJinja2 has a helpful default
filter that can compensate for missing values in the request. In this example, you may want to use the model’s ID in place of the friendly name when the friendly name is not provided: {{ body.friendly_name|default(body.model) }}
.method
is the uppercased string of the HTTP method, like GET
or POST
.headers
is a case-insensitive dictionary of the HTTP headers included with the request. To prevent accidental disclosures, the Authorization
header is removed.body
represents the body that was posted to the webhook, with a best-effort approach to parse it into an object you can access.dict
-like object, but you may access them with header names in any case. For example, these template expressions all return the value of the Content-Length
header:
Content-Type
of the request is application/json
, the body will be parsed as a JSON object and made available to the webhook templates. If the Content-Type
is application/x-www-form-urlencoded
(as in our example above), the body is parsed into a flat dict
-like object of key-value pairs. Jinja2 supports both index and attribute access to the fields of these objects, so the following two expressions are equivalent:
body.friendly-name
will not work. Use body['friendly-name']
in those cases.text/plain
) as if it were JSON first. In any case where the body cannot be transformed into JSON, it is made available to your templates as a Python str
.
POST
of a partial Prefect event as in this example:
occurred
, id
, and other fields as described above.
subject
as the resource (or the source
if no subject
is available). The CloudEvent’s data
attribute becomes the Prefect event’s payload['data']
, and the other CloudEvent metadata will be at payload['cloudevents']
. To handle CloudEvents in a more specific way tailored to your use case, use a dynamic template to interpret the incoming body
.
prefect cloud webhook
command group. For example, to create a webhook:
prefect cloud webhook --help
for more commands like ls
, get
, toggle
, and rotate
. For detailed template guidance, see Webhook Templates.
prefect-cloud.webhook.failed
event in your workspace. This event includes critical information about the HTTP method, headers, and body it received, as well as what the template rendered. Keep an eye out for these events when something goes wrong with webhook processing or template rendering. You can inspect these events in the event feed in the UI to understand what might have gone wrong.