Skip to content

Webhook secrets

Every workflow with a webhook trigger has its own per-workflow webhook secret. The secret is mandatory — a webhook with no secret configured returns 401 and never starts the workflow. Secrets are generated when the trigger is created, stored encrypted, and shown on the Triggers page in the dashboard.

A workflow’s webhook trigger has an auth mode that controls how the caller proves it knows the secret. The default mode works for any HTTP client; the HMAC mode is for systems like GitHub that sign requests.

Mode How the caller authenticates When to use
secret (default) Authorization: Bearer <secret> header or ?token=<secret> query param Internal services, manual curl, any client that can set a header
hmac X-Hub-Signature-256: sha256=<HMAC-SHA256(body, secret)> header — POST only GitHub webhooks (and any GitHub-style signed delivery)

HMAC mode verifies the signature against the raw request body, so a tampered payload fails verification even with a valid header. Wrong secret, missing signature, or non-POST all return 401.

The dashboard offers two distinct actions per webhook row in AI Workflows → Triggers:

Action What it does When to use
Reveal 👁 Shows the current secret. Does not change it. Safe to click anytime; the value stays valid in every existing integration. You need to copy the secret into a new integration, or you’ve lost track of where you stored it.
Rotate 🔄 Generates a new secret and invalidates the previous one. Always behind a confirmation prompt that spells out the impact. The secret has leaked, or you’re cycling secrets on a schedule. After rotating, update every integration that uses the secret — anything still presenting the old one will start failing.

The Triggers page shows each webhook’s URL. It is on your dashboard host:

https://dashboard.quantcdn.io/webhooks/ai/workflows/<workflowId> # QuantCDN
https://dash.quantgov.cloud/webhooks/ai/workflows/<workflowId> # QuantGov

Give external services (GitHub, Stripe, your own scripts) this URL. Quant checks the secret or signature, then starts the workflow with the raw request body.

This is the most common HMAC setup — pointing GitHub’s pull_request (or any other event) webhook at a workflow.

  1. In the dashboard: open the workflow’s webhook trigger, set Auth to HMAC, save.

  2. Reveal the secret for that trigger and copy it.

  3. In GitHub: on the target repository, go to Settings → Webhooks → Add webhook and enter:

    Field Value
    Payload URL the webhook URL from the Triggers page
    Content type application/json
    Secret the secret from step 2
    Which events the events you want — typically “Let me select individual events” → just “Pull requests”
    Active ✓
  4. Save. GitHub sends an immediate ping event to confirm the URL is reachable. After that, every matching event fires a signed delivery.

Three quick checks, in order:

Terminal window
# 1. The webhook host is reachable (no secret needed — expect 404 because the workflow id is fake)
curl -sS -X POST https://dash.quantgov.cloud/webhooks/ai/workflows/nope \
-H 'Content-Type: application/json' -d '{}'
# → 404 {"error":"Workflow webhook not configured"}
# 2. A wrong-secret HMAC delivery is rejected (proves the signature check runs)
BODY='{"smoke":true}'
SIG="sha256=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac 'WRONG' | awk '{print $NF}')"
curl -sS -X POST <your-webhook-url> \
-H 'Content-Type: application/json' -H "X-Hub-Signature-256: $SIG" --data-binary "$BODY"
# → 401 {"error":"Unauthorized"}
# 3. A valid signature returns 202 and creates a workflow execution.
SIG="sha256=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac '<your-real-secret>' | awk '{print $NF}')"
# → 202 with executionId in the body

If GitHub later shows red ❌ deliveries on the webhook settings page, click any delivery → Response tab to see the exact body the workflow returned (typically a clear 401 reason or 404 if the workflow was deleted).