Let an external system trigger a Definition — create a signed inbound webhook, copy its receive URL, and POST HMAC-signed deliveries
Inbound webhooks let external systems (Five9, Stripe, anything that can POST) trigger one of your Definitions. You create a webhook config bound to an active Definition; the sender POSTs signed deliveries to a per-customer receive URL; each verified delivery starts a normal job (source: "webhook").
This surface is inbound-only — deliveries coming into GetDialed. Outbound webhooks (a flow calling an external URL) are a separate catalog action, not receiver machinery.
The X-API-Key header is admin-equivalent; a Clerk JWT needs the admin role. Only provider: "standard" (Standard Webhooks, HMAC-SHA256) and mode: "trigger" are implemented today — other values are rejected with 422.
const res = await fetch("https://api.getdialed.ai/flows/webhooks", { method: "POST", headers: { "X-API-Key": process.env.API_KEY, "Content-Type": "application/json", }, body: JSON.stringify({ definition_id: "def_a1b2c3d4", description: "Five9 call-completed events", }),});const webhook = await res.json();// Store webhook.signing_secret NOW — it is never returned again.
import osimport httpxres = httpx.post( "https://api.getdialed.ai/flows/webhooks", headers={"X-API-Key": os.environ["API_KEY"]}, json={ "definition_id": "def_a1b2c3d4", "description": "Five9 call-completed events", },)webhook = res.json()# Store webhook["signing_secret"] NOW — it is never returned again.
The 201 response carries two show-once fields, signing_secret and receive_url:
The signing_secret is returned exactly once — here, and again only if you explicitly rotate it. It is never retrievable from any GET. Copy it into the sending system immediately. If you lose it, use POST /webhooks/{webhook_id}/rotate-secret (24h old-secret overlap).
For the example above that is https://api.getdialed.ai/flows/webhooks/acme/8a9c86a8b78c48d3a3e5e00ad0ed5b96. The webhook_id is a 128-bit opaque hex value, so the URL is unguessable by construction. The tenant is identified by the slug; the webhook by the webhook_id.
The receiver carries noX-API-Key/Authorization requirement — the trust boundary is the HMAC-SHA256 signature over the raw request body, verified per the Standard Webhooks spec before the body is parsed. Every delivery must carry three headers:
Header
Description
webhook-id
Sender-chosen unique delivery ID. This is the idempotency key — resending the same webhook-id is safe (dedups to one job).
webhook-timestamp
Unix seconds. Deliveries outside a 5-minute replay window are rejected with 401.
webhook-signature
v1,<base64 HMAC-SHA256> computed over {webhook-id}.{webhook-timestamp}.{raw body} with the signing secret.
The standardwebhooks library computes the signature for you — never hand-roll the HMAC.