Skip to main content
An incoming webhook starts a Bolt schedule when another tool sends a POST request to its URL. When the request has a JSON body, every command in the run can read it from an environment variable. Use this when the run must know which event started it, for example which source finished loading, or up to which time it loaded data. In this guide, an ingestion job calls the webhook when it finishes a load. The body tells the run which source loaded. A dbt™ macro logs the event, and a dbt™ model reads the load time from the body. You can also read the body in a Python script.
Prerequisites
  • A Bolt schedule you can edit.
  • The Admin, Workspace Admin, or Developer role, to create incoming webhooks.
  • A tool that can send a POST request with a custom header and a JSON body, such as a CI job, Zapier, Jira Automation, or curl.
Estimated time: 15 minutes.To start a DinoAI agent from a webhook, see Run an agent from a webhook.

How the payload reaches the run

Every run that an incoming webhook starts gets two environment variables: PARADIME_WEBHOOK_PAYLOAD is set only when the body is a JSON object or array of 64 KB or less. It isn’t set when:
  • The request is a Send test request from Bolt, which has no body.
  • The request has no body, or a body over 1 MB.
  • The body isn’t a JSON object or array, such as plain text or a single number.
  • The body is over 64 KB.
The run still starts in each case. So always give a default when you read the variable.

Steps

1

Read the payload in your commands

You don’t need Python. dbt™ reads the payload with env_var and fromjson.In a model, read the load time from the body:
models/staging/stg_orders_latest_load.sql
To write the event to the run’s logs, add a macro and call it with dbt run-operation:
macros/log_webhook_event.sql
The schedule’s commands, in order:
The body comes from outside Paradime. Check each value before you put it in SQL or in a shell command, for example that loaded_until is a timestamp. Otherwise, whoever can call the webhook can change the SQL that runs.
In a dbt command, Bolt replaces $PARADIME_WEBHOOK_PAYLOAD with the body, as one argument. See Environment variables in commands. When the body is a JSON object, pass it as dbt vars:
Models then read {{ var('loaded_until') }}. Use this only when every request has a JSON object body. When PARADIME_WEBHOOK_PAYLOAD isn’t set, such as on a test request, Bolt doesn’t replace the placeholder, and the command fails. The env_var approach above works in both cases.
In a Python script, parse the variable with json:
scripts/log_webhook_event.py
Add python scripts/log_webhook_event.py as a command in place of dbt run-operation log_webhook_event.
2

Create the Trigger URL

  1. In the schedule’s edit form, under Trigger type, select Incoming webhook.
  2. In the Trigger URLs card, click New Trigger URL, enter a Name such as Orders ingestion, and click Create.
  3. Copy the URL and the Authorization header, then click Done. The secret shows only once.
  4. Click Deploy.
3

Send the event from the other tool

At the end of the ingestion job, send a POST request with the Authorization header and a JSON body:
The response has "accepted": true and a run_id when a run started. Store the secret in the tool’s secret store, not in the job’s code.
Open the run in Bolt. It says Triggered by an incoming webhook. The logs of the dbt run-operation command show Event <id>: orders loaded until 2026-10-27T06:00:00Z.

Define it as code

If you manage schedules as code, declare the trigger with trigger_on_webhook: true:
The file doesn’t create the Trigger URL. After you deploy, open the schedule in Bolt and create the URL in the Trigger URLs card.

Things to know

  • Requests aren’t queued. A request that arrives while the schedule is running gets "skipped": "already_running", and no run starts for it. If every event must start a run, make the sender retry on that response, or send one request after a batch of loads.
  • Retries keep the payload. A retry of the run gets the body of the original request.
  • One schedule, many senders. Give each sender its own Trigger URL, and put a field such as source in the body, so a command can tell the senders apart.
  • See every request. Go to Bolt > Webhooks > Incoming to see the requests each Trigger URL received and the run each one started.

Next steps

Incoming webhooks reference

Responses, deliveries, rotation, and limits.

Run an agent from a webhook

Give the payload to a DinoAI agent.