Skip to content

Webhook (Trigger)

Audience: Everyone / Developers · Tags: webhook, trigger

Webhook is the only trigger type in SnapLink today. Every flow has exactly one trigger, and if it's not a manual/test run, it's a webhook: a private URL that starts the flow whenever something sends a request to it. connectorKey is webhook, authType is none — there's no OAuth or account to connect, because the secret embedded in the URL itself is the authorization.

How it works

  1. Get (or create) the flow's webhook endpoint — SnapLink generates one automatically the first time you ask for it.
  2. Put that URL into whatever system should start your flow (a form tool, a CRM's outgoing webhook setting, another automation, your own backend).
  3. Every request to that exact URL starts a run of the flow.

No polling, no scheduling — the flow only runs when something POSTs to its URL.

Get the webhook URL

curl "https://api.snaplink.cloudsolutionaccelerators.com/api/v1/flows/flow_abc123/webhook" \
  -H "Authorization: Bearer $TOKEN"
{ "ok": true, "data": {
  "flowId": "flow_abc123",
  "secret": "9f2a1c...e04b",
  "path": "/api/v1/webhooks/flow_abc123/9f2a1c...e04b"
} }

The full trigger URL is https://api.snaplink.cloudsolutionaccelerators.com + path. Anyone with this URL can trigger the flow, so treat it like a password — never post it publicly, in a README, in a shared channel, or in client-side code.

Worked example: build and trigger a flow

1. Create a flow, then a draft with a webhook trigger and a REST action (REST needs no setup, so this example runs end-to-end with nothing else to install — see rest.md for the action's details):

FLOW_ID=$(curl -s -X POST "https://api.snaplink.cloudsolutionaccelerators.com/api/v1/flows" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"workspaceId":"ws_abc123","name":"Incoming lead"}' | jq -r .data.id)

curl -X POST "https://api.snaplink.cloudsolutionaccelerators.com/api/v1/flows/$FLOW_ID/drafts" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "definition": {
      "trigger": { "key": "t", "connectorKey": "webhook", "triggerType": "webhook" },
      "actions": [
        { "key": "a1", "connectorKey": "rest_sdk", "actionType": "request",
          "input": { "url": "https://postman-echo.com/post", "method": "POST",
                     "body": "New lead received" } }
      ]
    }
  }'
# → 201 { "data": { "id": "draft_...", "status": "proposed", ... } }

2. Promote the draft — this both creates the immutable flow version and activates the flow (a flow must be active for its webhook to accept traffic):

curl -X POST "https://api.snaplink.cloudsolutionaccelerators.com/api/v1/drafts/draft_xyz/promote" \
  -H "Authorization: Bearer $TOKEN"

3. Fetch the webhook URL (as above), then trigger it:

curl -X POST "https://api.snaplink.cloudsolutionaccelerators.com/api/v1/webhooks/flow_abc123/9f2a1c...e04b" \
  -H "Content-Type: application/json" \
  -d '{"name":"Ada Lovelace","email":"ada@example.com"}'
{ "ok": true, "data": { "runId": "run_01HF...", "status": "queued" } }
No Authorization header — the secret in the URL is the authorization. The response only ever confirms the run started; it never echoes your payload back.

4. Check the result — look up the run by runId in Execution History or GET /executions/:id.

What's captured

  • Request bodies are not stored. SnapLink records that a webhook was received — method, content type, size, timestamp — never the body or headers. Don't expect to inspect or replay the raw payload later.
  • The message SnapLink sends onward is fixed text you wrote when building the flow — it doesn't insert data from the incoming request into an action's fields. If you need the payload's content reflected downstream, that's not supported yet.
  • Requests are capped at 1MB; larger bodies are rejected.

Rotating the secret

If a URL leaks, rotate it — the old secret keeps working for a grace window so you have time to update the sender before it breaks.

curl -X POST "https://api.snaplink.cloudsolutionaccelerators.com/api/v1/flows/flow_abc123/webhook/rotate" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"graceSeconds": 86400}'
{ "ok": true, "data": {
  "flowId": "flow_abc123", "secret": "new-secret...", "secretVersion": 2,
  "path": "/api/v1/webhooks/flow_abc123/new-secret...",
  "previousSecretExpiresAt": "2026-07-03T12:00:00.000Z"
} }
graceSeconds defaults to 24 hours if omitted. Once the grace window passes, the old URL returns 404.

Rate limiting

Inbound requests are limited per IP, per endpoint, and per workspace to absorb bursts and abuse. Exceeding a limit returns 429. See Rate limiting.

If something goes wrong

  • 404 from the webhook URL — wrong or expired secret, or an unknown flow (we don't distinguish, to avoid leaking which flows exist). Re-copy the URL from GET /flows/:id/webhook.
  • 409 FLOW_NOT_ACTIVE — the flow exists but hasn't been promoted/activated yet. Promote a draft first.
  • 429 — you're sending faster than the rate limit allows.
  • Trigger succeeds (202) but nothing downstream happens — see Connector failed.

Related: Webhook issues · REST connector · Connector Catalog