Browse documentation
2026-09-28AutoDataOpen in dashboard

Webhooks

Get an HTTP call when your runs complete or fail: events, payload, signature verification, delivery log and API.

What webhooks do

A webhook is a URL of yours that AutoData calls with a JSON POST when one of your runs finishes. Manage them on Listeners → Webhooks or at /api/v1/webhooks. To start a run from an incoming request instead, see Triggers.

Creating a webhook

  1. Click Add Webhook.
  2. Enter an optional name and the URL. It must be http or https, resolve, and point to a public address.
  3. Select events (the form pre-selects error, job.completed, job.failed).
  4. Optionally enter a secret to sign calls.
  5. Save, then use the test button.

Events

EventSent when
job.completedOne of your runs completes, from any surface.
job.failedOne of your runs fails.
errorPlatform-wide error notices from the operators only; not sent for your runs.
warningAccepted, not currently sent.
infoAccepted, not currently sent.
successAccepted, not currently sent.
quality.breachAccepted, not currently sent.

A webhook created through the API without events subscribes to ["error"] only. Quality alert rules store webhook_ids, but those webhooks are not called when a rule fires. There is no job.cancelled event.

Choosing webhooks per run

A finished run calls every active webhook subscribed to the event, unless the run names webhook_ids; then only those are called. Set it as webhookIds on a dashboard upload, webhook_ids on a connector run, or pipeline_config.webhook_ids on listeners, the SFTP inbox and schedules (target_pipeline_config.webhook_ids on triggers).

Payload

{
  "event": "job.completed",
  "data": {
    "session_id": "3971e9cc-...",
    "status": "completed",
    "original_filename": "orders.csv",
    "timestamp": "2026-09-28T14:32:00.123456",
    "files": ["dsm_output.csv", "dsg_output.csv"]
  },
  "timestamp": "2026-09-28T14:32:00.130001",
  "webhook_id": "b6a4c1f0-..."
}

job.failed has "status": "failed" and error instead of files. The test call has "event": "test".

Verifying the signature

With a secret, each call carries X-Webhook-Signature: sha256=<hex>: HMAC-SHA256 with your secret over the payload serialised with sorted keys, exactly as Python's json.dumps(payload, sort_keys=True) produces it. The body on the wire is not sorted, so parse and re-serialise before hashing.

import hashlib, hmac, json

def verify(raw_body: bytes, header: str, secret: bytes) -> bool:
    canonical = json.dumps(json.loads(raw_body), sort_keys=True).encode("utf-8")
    expected = "sha256=" + hmac.new(secret, canonical, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header or "")

Delivery

  • One attempt, 10-second timeout, no automatic retries.
  • 2xx counts as delivered; redirects are not followed.
  • The URL is re-checked at delivery; private addresses are blocked.
  • The delivery log keeps the 50 most recent attempts with event, status code, duration, response excerpt and error.

API

MethodPathNotes
GET/api/v1/webhooksList.
POST/api/v1/webhooksurl (required), name, events, secret. 201.
GET/api/v1/webhooks/{id}One webhook.
PUT/api/v1/webhooks/{id}Any of url, name, events, secret, active.
DELETE/api/v1/webhooks/{id}Also deletes its log.
POST/api/v1/webhooks/{id}/testSends the test payload; reports your status code.
GET/api/v1/webhooks/{id}/deliveriesLatest 50 attempts.

Python SDK: list_webhooks(), create_webhook(url, events=None, name=None, secret=None), get_webhook(id), update_webhook(id, **fields) (use active=), delete_webhook(id), test_webhook(id), webhook_deliveries(id).