Webhooks
A Webhook Trigger gives a workflow its own URL. Any system that can send an HTTP request (GitHub, Stripe, a form tool, your own service) can start the workflow by calling it. For the trigger itself in the builder, see Workflows.
The trigger URL
The URL appears on the Webhook Trigger node after the workflow is first saved:
https://graphqlworkspaces.burdenoff.com/api/webhooks/t/wht_…
- The URL starts the workflow's Active version. A workflow with no Active version answers
404until you activate one. - The request body, headers, query parameters, method and caller IP are the trigger's output, so later nodes can read them. Payload mapping on the trigger can turn the body into named workflow variables.
- Each URL reaches exactly one trigger. Treat it as a secret: anyone who has it can call it, so also set an authentication method.
Authenticating requests
Choose the method on the trigger node. The default is HMAC SHA-256 Signature.
| Method | What the sender must do |
|---|---|
| HMAC SHA-256 Signature | Sign the request with the shared secret (see below) |
| API Key Header | Send the secret in a header, X-API-Key unless you name another |
| Bearer Token | Send Authorization: Bearer <secret> |
| Basic Auth | Send HTTP Basic credentials |
| Custom Signature | Send a signature in a header you name, for providers with their own signing scheme |
| JWT | Send a JWT that matches the issuer, audience and algorithms you set, verified with a shared secret or a JWKS URL |
| None (Not Recommended) | Nothing. Anyone with the URL can start the workflow. |
On top of the method you can restrict allowed HTTP methods (POST by default) and an IP allowlist of addresses or CIDR ranges.
Signing with HMAC SHA-256
The sender sends two headers:
| Header | Value |
|---|---|
X-Webhook-Timestamp | The current Unix time in seconds |
X-Webhook-Signature | sha256= followed by the hex HMAC-SHA256 of <timestamp>.<raw request body>, keyed with the trigger's secret |
Requests whose timestamp is more than five minutes from the server's clock are rejected, so a captured request cannot be replayed later.
import { createHmac } from 'node:crypto';
const body = JSON.stringify({ orderId: 'ORD-12345' });
const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = createHmac('sha256', process.env.FG_WEBHOOK_SECRET ?? '')
.update(`${timestamp}.${body}`)
.digest('hex');
await fetch(process.env.FG_WEBHOOK_URL ?? '', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Webhook-Timestamp': timestamp,
'X-Webhook-Signature': `sha256=${signature}`,
},
body,
});
Sign the exact bytes you send. Re-serialising the JSON after signing changes the body and the signature no longer matches.
What the caller gets back
The trigger's Respond setting decides when FluidGrids answers:
| Respond | Answer |
|---|---|
| Immediately (default) | As soon as the run is queued, with the Response Code you set (200 by default) |
| When Last Node Finishes | When the run completes, with the last node's output: First Entry JSON, All Entries, or No Response Body |
| Using 'Respond to Webhook' Node | When a Respond to Webhook node in the workflow runs, with the status, headers and body it builds |
For the two waiting modes, Response Timeout (seconds) (up to 25) caps how long the caller is held. If the run is not done by then, the caller gets 202 and the run carries on.
The full list of status codes is in REST API › Responses.
Testing a trigger
In the builder, Listen for test event on the Webhook Trigger arms a separate test URL (/api/webhooks/test/…). The first request that passes the trigger's checks starts one test run of the version on the canvas, so you can build against a real payload before activating anything. A test URL never starts a production run, and the production URL never runs a draft.
Delivery log and retries
Every request that reaches a trigger is logged as a delivery, with its outcome. A delivery that failed or was filtered can be retried on its own, without asking the sender to send it again. Retrying needs Editor on webhook-delivery (Automation Owner, Automation Lead, Run Operator). From the CLI:
fluidgrids webhooks list --workflow-key <workflowKey>
fluidgrids webhooks activate <id>
fluidgrids webhooks deactivate <id>
Limits
- Webhook ingress is rate-limited per URL and per workspace. A throttled sender gets
429withRetry-After. - Each run a webhook starts counts toward your plan's monthly runs (
fluidgrids.runs.monthly). See Plans and Quotas.
Calling other webhooks from a workflow
To send a webhook from a workflow, use the HTTP Request node with the target URL, method, headers and body. Keep the target's secret in a credential rather than typing it into the node, so it is stored encrypted. To be told when a workflow fails or succeeds, use the webhook notifications on the workflow module's Settings screen.