Core Plugins and tasks Webhook

Core Plugins and tasks Webhook

Certified

Trigger a Flow via an authenticated webhook URL.

Exposes a signed endpoint .../executions/webhook/{Namespace}/{flowId}/{key} that accepts GET/POST/PUT to start a Flow. Secured by the required key; keep it secret.

Request data is available as trigger.body, trigger.headers, and trigger.parameters. A binary body is base64-encoded on trigger.body, unless fetchType is set to STORE to stream it into Kestra's internal storage and expose it as trigger.uri instead. A multipart/form-data body is available as trigger.parts (files, always stored in Kestra's internal storage) and trigger.formFields. Supports wait/returnOutputs to block and return Flow outputs, and optional responseContentType. Conditions are allowed except MultipleCondition.

Responses: 404 (not found), 200 (triggered), 204 (conditions not met), 422 (inputs could not be rendered).

yaml
type: io.kestra.plugin.core.trigger.Webhook

Add a webhook trigger to the current flow with the key 4wjtkzwVGBM9yKnjm3yv8r; the webhook will be available at the URI /api/v1/{tenant}/executions/webhook/{namespace}/{flowId}/4wjtkzwVGBM9yKnjm3yv8r.

yaml
id: webhook_flow
namespace: company.team

tasks:
  - id: log_hello_world
    type: io.kestra.plugin.core.log.Log
    message: Hello World! 🚀

triggers:
  - id: webhook
    type: io.kestra.plugin.core.trigger.Webhook
    key: 4wjtkzwVGBM9yKnjm3yv8r

Add a trigger matching specific webhook event condition. The flow will be executed only if the condition is met.

yaml
id: condition_based_webhook_flow
namespace: company.team

tasks:
  - id: log_hello_world
    type: io.kestra.plugin.core.log.Log
    message: Hello World! 🚀

triggers:
  - id: webhook
    type: io.kestra.plugin.core.trigger.Webhook
    key: 4wjtkzwVGBM9yKnjm3yv8r
    when: "{{ trigger.body.hello == 'world' }}"

Webhook with text/plain response for Microsoft Graph validation handshakes. When a service like Microsoft Graph validates the webhook endpoint, it sends a validationToken that must be echoed back as plain text.

yaml
id: microsoft_graph_webhook
namespace: company.team

tasks:
  - id: handle_request
    type: io.kestra.plugin.core.debug.Return
    format: "{{ trigger.parameters.validationToken[0] ?? 'notification processed' }}"

outputs:
  - id: response
    type: STRING
    value: "{{ outputs.handle_request.value }}"

triggers:
  - id: webhook
    type: io.kestra.plugin.core.trigger.Webhook
    key: 4wjtkzwVGBM9yKnjm3yv8r
    wait: true
    returnOutputs: true
    responseContentType: "text/plain"

Receive a file uploaded as multipart/form-data. Each file part is available under trigger.parts, its content stored in Kestra's internal storage and reachable through its uri, and the parts that are not files under trigger.formFields.

yaml
id: upload_webhook
namespace: company.team

tasks:
  - id: log_upload
    type: io.kestra.plugin.core.log.Log
    message: "Received {{ trigger.parts[0].filename }} ({{ trigger.parts[0].size }} bytes, {{ trigger.parts[0].contentType }}), note: {{ trigger.formFields.note[0] }}"

  - id: measure_upload
    type: io.kestra.plugin.core.storage.Size
    uri: "{{ trigger.parts[0].uri }}"

triggers:
  - id: webhook
    type: io.kestra.plugin.core.trigger.Webhook
    key: 4wjtkzwVGBM9yKnjm3yv8r

Receive a payload that is not a form - a large JSON export, or a binary file sent as the request body - without carrying it through the execution. fetchType: STORE streams the body into Kestra's internal storage and exposes its URI as trigger.uri instead of its content as trigger.body. Note that a condition on the trigger can no longer read the body.

yaml
id: stored_body_webhook
namespace: company.team

tasks:
  - id: measure_body
    type: io.kestra.plugin.core.storage.Size
    uri: "{{ trigger.uri }}"

triggers:
  - id: webhook
    type: io.kestra.plugin.core.trigger.Webhook
    key: 4wjtkzwVGBM9yKnjm3yv8r
    fetchType: STORE
Properties
Min length1
Max length256

The unique key that will be part of the URL.

The key is used for generating the webhook URL.

::alert{type="warning"} Make sure to keep the webhook key secure. It's the only security mechanism to protect your endpoint from bad actors, and must be considered as a secret. You can use a random key generator to create the key. ::

Defaultfalse

Specifies whether a trigger is allowed to start a new execution even if a previous run is still in progress.

DefaultFETCH
Possible Values
NONEFETCHSTORE

What the trigger does with the body of the webhook request.

  • FETCH: the body reaches the flow on the body output. A JSON body is deserialized, a binary one is base64-encoded. This is the default, and how a webhook has always behaved.
  • STORE: the body is streamed into Kestra's internal storage as it is received, and the flow reaches it through the uri output. Nothing of it travels through the execution, so this is the option to use for a large or binary payload - but note that a condition on the trigger can no longer read the body.
  • NONE: the body is read off the connection and dropped. Use it for a caller whose payload the flow does not need.

This only concerns the body of a request. The file parts of a multipart/form-data request are always stored in the internal storage and exposed on parts, whatever this property is set to, as a file part has no meaningful representation inside an execution.

The inputs to pass to the triggered flow

Custom response code.

If set, the webhook response code will use this response code instead of the default 200. Requires wait and returnOutputs to be true.

Possible Values
application/jsontext/plain

Custom response content type.

If set, the webhook response will use this content type instead of the default application/json. Requires wait and returnOutputs to be true. This is useful for webhook validation handshakes that require specific content types (e.g., Microsoft Graph Change Notifications require text/plain responses).

Defaultfalse

Send outputs of the flows as response for webhook caller.

Requires wait to be true.

SubTypestring
Possible Values
CREATEDSUBMITTEDRUNNINGPAUSEDRESTARTEDKILLINGSUCCESSWARNINGFAILEDKILLEDCANCELLEDQUEUEDRETRYINGRETRIEDSKIPPEDBREAKPOINTRESUBMITTED

List of execution states after which a trigger should be stopped (a.k.a. disabled).

Defaultfalse

Wait for the flow to finish.

If set to true the webhook call will wait for the flow to finish and return the flow outputs as response. If set to false the webhook call will return immediately after the execution is created.

Defaulttrue

A condition that determines whether the trigger should run.

A Pebble expression evaluated at trigger time. The trigger fires only when the expression evaluates to a truthy value (true, a non-empty string, a non-zero number). Use this to gate trigger execution on dynamic runtime values such as execution labels, flow variables, or environment conditions.

The full body for the webhook request

We try to deserialize the incoming request as JSON (array or object). If we can't deserialize, the full body will be available as a string. A binary body - one whose content type is neither text, JSON, XML, form-urlencoded, YAML nor CSV - is base64-encoded, as base64 is how bytes travel through the text-based trigger variables. Use the content-type request header to tell a base64-encoded body apart from a plain text one. Only set for a trigger whose fetchType is FETCH, and not for a multipart/form-data request, which is available as parts and formFields.

SubTypearray

The headers for the webhook request

SubTypearray

The parameters for the webhook request

SubTypearray

The form fields of a multipart/form-data webhook request

Only set for a multipart/form-data request; holds the parts that are not files.

The file parts of a multipart/form-data webhook request

Only set for a multipart/form-data request. The content of each part is stored in Kestra's internal storage, and the part carries its URI.

Definitions
contentTypestring

The content type of the part

Not set if the caller did not send one for this part.

filenamestring

The name of the uploaded file

namestring

The form field name of the part

sizeinteger

The size of the part content in bytes

uristring

The URI of the part content in Kestra's internal storage

The content of the part is streamed to the internal storage as it is received, so that a file of any size reaches the flow intact and without travelling through the execution. It is stored under the execution the webhook call creates, and purged with it.

The URI of the body of the webhook request in Kestra's internal storage

Only set for a trigger whose fetchType is STORE. The body is streamed to the internal storage as it is received, so that a payload of any size reaches the flow intact and without travelling through the execution. It is stored under the execution the webhook call creates, and purged with it.