HTTP Webhook
inputTrigger your workflow via HTTP requests. This input type creates an HTTP server that listens for incoming requests and triggers the workflow when a request is received.
Configuration
Add an HTTP webhook input to your workflow to create an endpoint that can receive HTTP requests:
workflow:
name: my-webhook-workflow
description: "Receives HTTP requests"
input:
type: http_webhookConfiguration Options
Required and optional configuration fields for this input type:
| Parameter | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Set to "http_webhook" |
Workflow Endpoint
After creating your workflow, the webhook endpoint details will be available on the workflow details tab. The endpoint URL follows this pattern:
https://pipeline.etlr.io/v1/webhooks/{organization_id}/{workflow_id}/{security_hash}The URL contains three components:
- organization_id - Your organization's unique identifier
- workflow_id - The specific workflow's unique identifier
- security_hash - A security token that provides authentication through obscurity
Triggering the Webhook
Send an HTTP POST request to your workflow's endpoint to trigger execution. The request body will be available in the workflow state:
curl -X POST \
https://pipeline.etlr.io/v1/webhooks/a7b3c468-2e1d-49af-8ea0-fb9edc2dd847/752d84fe-cadf-48c0-ba69-ce4bf792gd7e/d448feb6c9da97b60847f1c21cbf9e6c8b378bfb7f04cc6cc0c4d4f992f75ed5 \
-H "Content-Type: application/json" \
-d '{
"user": {
"name": "John Doe",
"email": "[email protected]"
},
"action": "signup"
}'Request Data
The HTTP request body is automatically parsed and made available in your workflow state. The JSON request body fields are available at the root of the state, allowing you to access them directly in your workflow steps.
For example, if you send this request body:
{
"user": {
"name": "John Doe",
"email": "[email protected]"
},
"action": "signup"
}You can access the data in your workflow in two ways:
- Using
input_from- Most steps have aninput_fromparameter to read data from specific paths in the state (e.g.,input_from: user.name). See the State documentation for more details. - Using template strings - When a step supports templates (like
text_template), you can inject values using${user.name}syntax for string interpolation.
Example Workflow
Here's a complete example that receives webhook data, adds a timestamp, and sends it to Slack:
workflow:
name: webhook-to-slack
description: "Receives webhooks and posts to Slack"
input:
type: http_webhook
steps:
- type: add_timestamp
field: received_at
- type: slack_webhook
webhook_url: "${env:SLACK_WEBHOOK_URL}"
text_template: "New event: ${user.name} performed ${action} at ${received_at}"Response
By default, the webhook is fire-and-forget: it responds with a 200 OK immediately after accepting the request and continues running the workflow in the background.
{
"status": "ok",
"upstream_status": 200,
"upstream_body": "{\"status\":\"accepted\",\"request_id\":\"157b931ef623a667\"}"
}Synchronous Mode (?wait=true)
Append ?wait=true to the webhook URL to make the request block until the workflow finishes. The response body contains the final workflow state, so you can use a webhook as a request/response endpoint — for example, to trigger an LLM step and return its answer inline.
curl -X POST \
'https://pipeline.etlr.io/v1/webhooks/{org}/{workflow}/{hash}?wait=true' \
-H "Content-Type: application/json" \
-d '{"ticket": {"subject": "Cannot log in"}}'
The response uses a consistent envelope with a status field your client can switch on:
| Status | HTTP code | Meaning |
|---|---|---|
"ok" | 200 | Workflow finished successfully. The event field contains the final state after all steps. |
"dropped" | 200 | A step filtered out the event (returned None). No event field. |
"timed_out" | 200 | The workflow didn't finish within 30 seconds. It keeps running in the background — check your logs for completion. |
"error" | 200 | A step raised an exception. The error field contains the exception type and message. |
Example success response:
{
"status": "ok",
"request_id": "157b931ef623a667",
"event": {
"ticket": { "subject": "Cannot log in" },
"triage": { "urgency": "high", "category": "account" },
"request_id": "157b931ef623a667"
}
}Example timeout response (workflow still running in the background):
{
"status": "timed_out",
"request_id": "157b931ef623a667"
}Key points:
- 30-second cap — if the workflow takes longer, the response returns with
"timed_out"but the workflow continues to completion. It is never cancelled by the webhook. - Accepted truthy values —
?wait=true,?wait=1, or?wait=yes. Any other value (or absence) falls back to the default fire-and-forget behaviour. - Choose wait for short, interactive workflows — it's ideal for synchronous LLM calls, enrichment, and validation. Long-running pipelines should stay fire-and-forget and signal completion another way.
Best Practices
- Endpoint Security - Keep your webhook URL private, as the security hash provides authentication
- Validation - Use filter steps to validate incoming data structure and content
- Error Handling - Handle invalid requests gracefully with proper error responses
- Rate Limiting - Be aware of rate limits on your workflow executions
- Testing - Test your webhooks thoroughly before deploying to production