- A webhook added to a funnel. See Send your leads to a webhook.
- The webhook’s signing secret, if your server checks signatures. You find it in “Edit webhook”, under Advanced.
The request
AskFunnel sends a POST request with a JSON body. Along with any headers you added, it always includes these:webhook-idandidempotency-keyare the lead’s event ID, the same value asidin the body. They stay the same on every retry, so use them to ignore repeats.webhook-timestampis the time of this attempt, in seconds since 1970 (Unix time). Each retry has a new timestamp and a new signature.webhook-signatureis the signature of this attempt. See Verify the signature.user-agentis alwaysAskFunnel-Webhooks/1.0 (+https://askfunnel.com)unless you add your own header with that name.
The JSON body
Here is a sample lead from a funnel called Buyer inquiry. JSON is a standard text format that software reads easily. The body is sent as compact JSON, shown here with line breaks to read it.
In a test,
test is true, lead.id is null, score is 0, consent.marketing is false, and attribution.utm and attribution.referrer are null. The answers are sample text built from your funnel’s questions.
Verify the signature
Each webhook has its own signing secret. AskFunnel signs every request with it, following the Standard Webhooksv1 format, so libraries that support that format can verify AskFunnel requests too. To check a request yourself:
- Read the body exactly as it arrived. Do not parse it and write it out again, because the signature covers the exact bytes.
- Build the signed text: the
webhook-idheader, a dot, thewebhook-timestampheader, a dot, then the body. - Take your signing secret, remove the
whsec_at the start and decode the rest from base64. That is the key. - Compute an HMAC with SHA-256 over the signed text using that key, and encode the result as base64.
- The
webhook-signatureheader isv1,followed by that value. Compare the two in constant time. - Reject requests with an old timestamp. We suggest 5 minutes.
Retries and what counts as success
AskFunnel only looks at the status code of your answer. The body of your answer is ignored.
A lead that can be retried is sent again after 1 minute, then 5 minutes, 30 minutes, 2 hours, 6 hours and 12 hours, each counted from the previous attempt. That is up to 7 attempts in about 21 hours. Each retry sends the same
webhook-id and the same body, with a new timestamp and signature.
- 429 Too Many Requests is treated as “slow down”, not as an outage. If your answer has a
Retry-Afterheader, in seconds or as an HTTP date, AskFunnel waits at least that long, up to 24 hours. It never retries sooner than the schedule above. It does not schedule a retry later than 72 hours after the first attempt. - After the last attempt fails, the lead shows Failed with the last error, the webhook shows Needs attention, and the organization owner gets an email.
- Clicking “Retry” in the delivery log starts a new set of up to 7 attempts.
- Failed leads stay in the delivery log for 30 days.
Troubleshooting
My signature check fails
My signature check fails
Check these, in order:
- You are using the raw body, not a parsed and re-written one.
- You are using the signing secret of this webhook. Each webhook has its own.
- You remove whsec_ and decode the rest from base64 before using it as the key.
- You did not rotate the secret without updating your server.
- The clock on your server is close to the real time, if you check the timestamp.
- You are not testing with an unsaved webhook. A test sent before you save is signed with a temporary secret.

