Webhooks
Receive each lead as a JSON POST on your own https address: the headers, the body, how to answer, and how retries work.
A webhook sends every captured lead to an address on your own server. Zapier, Make, n8n and Pabbly Connect receive the same body.
What you need
- An https address that accepts a POST request. Plain http is refused.
- The webhook connected in the app. See Webhook.
The request
One POST per lead, with a JSON body and these headers:
- user-agent: Tafsee-Popup-Webhook/1.0
- x-tafsee-event: popup.lead.captured
- x-tafsee-delivery: the lead's reference. It is the same on every retry of the same lead, so you can drop duplicates.
- x-tafsee-timestamp: the time of sending, in Unix seconds.
- x-tafsee-signature: sha256= followed by a hex value (see below).
The body
{
"event": "popup.lead.captured",
"leadId": "…",
"leadRef": "…",
"capturedAt": "2026-10-12T10:15:00.000Z",
"workspaceId": "…",
"site": { "id": "…", "domain": "example.com" },
"campaign": { "id": "…", "name": "Welcome offer", "type": "lightbox" },
"variantId": null,
"lead": {
"email": "shopper@example.com",
"firstName": "…", "lastName": "…", "phone": "…", "company": "…",
"consent": true,
"couponCode": "WELCOME10",
"customFields": { "size": "M" }
},
"fields": { "…": "…" },
"page": { "url": "…", "title": "…", "referrer": "…" },
"utm": { "utm_source": "instagram" },
"device": "mobile",
"country": "SA",
"locale": "ar"
}- lead holds the standard details. customFields holds the answers to your own form questions, by field ID.
- fields holds the rows you chose in the campaign's table What to send, named as you named them. Without rows it holds the raw form values.
- variantId is set when the lead came through a version of an A/B test.
- A test lead sent from the app also carries "test": true. Skip those in your own system.
How to answer
- Answer with any 2xx status to accept the lead.
- Answer within 8 seconds. A slower answer counts as a failure and is tried again.
- A 408, a 429 or any 5xx status is tried again: after 1 minute, then 5 minutes, 30 minutes, 2 hours and 12 hours, six attempts in all.
- Any other 4xx status is taken as a refusal. The lead is marked failed for this webhook at once and is not tried again by itself.
The lead is safe in Tafsee in every case, and a failed delivery can be sent again by hand. See Lead delivery and Send again.
The signature
The x-tafsee-signature header is the HMAC-SHA256 of the timestamp, a dot, and the raw body, made with a signing secret that belongs to the connection, and written as hex after sha256=.
The app does not show the signing secret at the moment, so you cannot check the signature yet. Until it does, protect your endpoint in another way: use an address that is long and hard to guess, and keep it to yourself.
Tips
- Use x-tafsee-delivery as an idempotency key.
- Do the slow work after you answer, not before.
- Use Send test lead on the webhook's card to send a sample to your address.
If it does not work
- Nothing arrives: no campaign is ticked for the webhook. See Connecting a tool: how it works.
- Leads show Failed: open one to read your server's answer and its status code.
- You receive the same lead twice: your server answered too slowly or with an error the first time. Drop duplicates by x-tafsee-delivery.