Skip to content
Docs/Connect services

Sensors and inbound webhooks

Sensors connect an external event to a registered flow. Use a webhook sensor when another application can make an HTTP request, a polling sensor when you must check a readiness endpoint, or an S3 sensor when bucket events are already routed to your Dagy environment.

On this pageBefore you startCreate a webhook sensorCheck readiness without starting a runDeliver an eventHandle webhook retries and limitsPoll a readiness endpointReact to S3 objectsManage sensor lifecycle

For a self-service integration, start with an inbound webhook: create a sensor, send parameters to its URL, and monitor the returned run ID.

Before you start

Register the flow you want to trigger and confirm that a normal run request succeeds. A webhook sensor resolves the latest registered version of its flow_name on every request. It does not pin a deployment or select an environment through the webhook body. Use the runs API when you need those controls.

Managing sensors requires authentication, with sensors.read for reads and sensors.write for create, delete, and dry-run tests. The generated webhook URL uses its secret URL token instead of normal API authentication.

Create a webhook sensor

In the web app, open Events, add a sensor, choose Webhook, and select a registered flow. The equivalent API request is:

Shell
curl --fail-with-body "$DAGY_API_URL/sensors" \
  -H "Authorization: Bearer $DAGY_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{
    "name":"Process incoming orders",
    "sensor_type":"webhook",
    "flow_name":"process-orders",
    "flow_params_json":{"source":"partner-a"}
  }'

The 201 response includes sensor_id, webhook_token, enabled, and the configured flow details. Construct the callback URL as $DAGY_API_URL/webhooks/{webhook_token}. Anyone holding this URL can trigger the flow; store it as a secret and avoid including it in application logs or browser pages.

Check readiness without starting a run

Shell
curl --fail-with-body -X POST \
  "$DAGY_API_URL/sensors/$SENSOR_ID/test" \
  -H "Authorization: Bearer $DAGY_TOKEN"

Example response:

JSON
{
  "status":"ok",
  "dry_run":true,
  "sensor_id":"sensor_example",
  "flow_name":"process-orders",
  "flow_version":"YOUR_REGISTERED_VERSION",
  "would_trigger":true,
  "reason":null,
  "parameters":{"source":"partner-a"}
}

This checks that the sensor is enabled and the flow can be resolved. It does not execute the flow, test provider credentials, or request a polling URL. Always perform a real development run before relying on the integration.

Deliver an event

Shell
curl --fail-with-body "$DAGY_API_URL/webhooks/$WEBHOOK_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{"parameters":{"order_id":"order-1042","source":"partner-b"}}'

Request parameters override flow_params_json defaults. This example triggers process-orders with {"order_id":"order-1042","source":"partner-b"}.

If the body contains a parameters object, its contents are used. Otherwise, top-level JSON object fields are parameters. Empty, non-JSON, and non-object bodies are treated as no additional parameters. Use an explicit JSON object to avoid silently dropping event data.

The response confirms run creation:

JSON
{
  "triggered":true,
  "sensor_id":"sensor_example",
  "flow_name":"process-orders",
  "flow_version":"YOUR_REGISTERED_VERSION",
  "run_id":"YOUR_RUN_ID"
}

triggered:true does not mean the flow completed. Save run_id and inspect its status and logs.

Handle webhook retries and limits

There is no incoming HMAC signature check or automatic event-ID deduplication on this endpoint. If the event source requires signature validation, validate its request in your own application and then call Dagy. Include the source event ID in parameters and make your flow's writes idempotent.

Each accepted request may create a new run, including a retry after a client timeout. Before replaying a request with an uncertain result, inspect recent runs or your application's event record.

The default webhook limit is 60 requests per minute per URL token and can vary by service deployment. On 429, respect Retry-After and retry with backoff. Run quotas may also reject a request. Per-sensor webhook_rpm and cooldown_seconds are not applied by the public webhook route.

HTTP resultMeaning and resolution
404Invalid or deleted URL token; copy the current sensor URL
409Sensor is disabled; inspect the sensor configuration
422The flow is not registered or run parameters are invalid; register it and validate inputs
429Rate or usage limit reached; inspect the response and delay retries
5xx or network timeoutRun creation may be uncertain; reconcile before resending

Poll a readiness endpoint

Create a polling sensor with a config_json object:

JSON
{
  "name":"Partner export ready",
  "sensor_type":"polling",
  "flow_name":"load-partner-export",
  "flow_params_json":{"source":"partner-a"},
  "config_json":{
    "url":"https://api.example.com/export/status",
    "interval_seconds":300,
    "timeout_seconds":10,
    "expected_status":200,
    "json_path":"data.ready",
    "expected_value":true,
    "allow_concurrent":true
  }
}

Polling performs an HTTP GET. It matches an explicit expected_status, or any successful 2xx status if none is provided. Optional json_path uses dotted object keys or numeric array indices, such as data.exports.0.ready; it is not a full JSONPath expression. With expected_value, the selected value must equal it; otherwise the value must be truthy.

Optional headers supplies request headers. Treat those values as sensitive: sensor configuration is returned to callers with sensors.read. A matched poll sends only the configured flow parameters; it does not inject the response body into the flow.

The default interval is 300 seconds and the minimum accepted interval is 30 seconds. Actual timing depends on scheduler cadence, so this is not a precise timer. Network errors and invalid JSON conditions do not trigger a run.

Current polling limitation: without allow_concurrent:true, a sensor stops triggering after its first match because its pending-trigger state is not automatically cleared. With allow_concurrent:true, it can fire on each matching poll and runs may overlap. Use an idempotent flow and a readiness endpoint that clears consumed events, or use webhooks for repeatable event delivery.

React to S3 objects

S3 sensors require bucket events to be delivered to your Dagy environment. Creating the sensor does not configure event delivery on an arbitrary customer bucket. Confirm this prerequisite with your administrator; otherwise have your existing event handler invoke a webhook sensor.

JSON
{
  "name":"New order files",
  "sensor_type":"s3",
  "flow_name":"load-order-file",
  "config_json":{"bucket":"example-orders","prefix":"incoming/","suffix":".json"}
}

A delivered event matches the exact bucket and optional key prefix/suffix. The flow receives s3_bucket and s3_key parameters. If you already set those names in flow_params_json, the configured values take precedence; omit them to receive the triggering object. A matching event does not grant read permission to the object. Configure data access separately in your flow.

Manage sensor lifecycle

GET /sensors returns {"items":[...]}. GET /sensors/{id} returns a sensor, including its webhook token when present. DELETE /sensors/{id} returns {"deleted":true} and invalidates that webhook URL.

There is currently no public sensor update, token rotation, or enable/disable operation. To change configuration or replace a leaked URL, create a replacement sensor, update your sender, and delete the old sensor.

To receive notifications about completed runs, configure alert channels and outbound webhooks.