Send contacts to a webhook (payload reference)
Add a Send to a webhook step and Textiful posts the contact as JSON to your URL when someone reaches that step. This page lists every field and header.
Add a Send to a webhook step to a flow and paste your URL. When someone reaches that step, Textiful sends a POST with everything it knows about the contact as JSON.
Steps
- Open the flow under Data Capture Flows.
- Click the + where the webhook should run (usually after your last question), or Add a step.
- Under Actions and integrations, choose Send to a webhook.
- Paste your URL into Webhook URL. It must be a public
httporhttpsaddress. - Check the Sample request under the field, then save the step.
The step runs as soon as someone reaches it, so anyone who stops answering before then isn't sent.
The request
POST /your-url
Content-Type: application/json
X-Textiful-Signature: sha256=…
X-Textiful-Delivery: 2f6d1c0e-…
X-Textiful-Attempt: 1
{
"favorite_session": "My answer",
"zip": "55401",
"city": "Minneapolis",
"state": "MN",
"timezone": "America/Chicago",
"zip_code": "55401",
"company_name": null,
"email": "jane@example.com",
"first_name": "Jane",
"last_name": "Smith",
"mobile_number": "+13195550100",
"keyword": "SLIDES",
"dialed_number": "33777",
"campaign_id": 123,
"campaign_name": "Keynote at Summit 2026",
"timestamp": "2026-11-03T15:04:05+00:00"
}
Payload fields
The contact's saved answers come first, then these fixed fields, always in this order:
| Field | What it is |
|---|---|
zip_code |
Same as zip, under the older name. null if unknown |
company_name |
Same as company, under the older name. null if unknown |
email |
Email address, or null |
first_name, last_name |
Name, or null |
mobile_number |
Their phone number, with country code (+1…) |
keyword |
The keyword they texted. null if they scanned a QR code |
dialed_number |
The short code they texted: 33777 or 55444 |
campaign_id, campaign_name |
The flow's ID and name (the field names predate the word "flow") |
timestamp |
When the request was built, ISO 8601 |
The answer keys at the top depend on what's been collected:
- Built-in questions:
email,first_name,last_name,company,city,state,zip. - A zip code also adds
city,state, andtimezone, looked up from the zip. - Custom data uses the Field name in snake case, so "Favorite session" becomes
favorite_session. - Poll answers use
poll_plus the poll's ID, such aspoll_42.
Answers the contact gave in other flows are included too, so don't assume every key comes from this flow.
Headers
X-Textiful-Delivery: a unique ID for this delivery. It stays the same on every retry, so use it to ignore repeats.X-Textiful-Attempt: which try this is, starting at 1.X-Textiful-Signature:sha256=plus an HMAC-SHA256 of the raw body.
Responses and retries
- Reply with any
2xxstatus to accept the delivery. - Any other status (including redirects,
4xx, and5xx), or no answer within 15 seconds, is retried. Retries start after 30 seconds and spread out over a little under three days, 10 tries in all, before the delivery is marked Gave up. - A
410 Gonetells Textiful to stop. It isn't retried.
Every delivery is listed in the Sync and delivery log on Settings > Integrations, with its status, attempts, last error, and next try. History shows each attempt, Retry sends a failed one again, and Retry all failed does them all.
Frequently asked questions
- Can I see what my webhook will receive before going live?
- Yes. The Send to a webhook step shows a Sample request built from that flow's own questions.
- What happens if my server is down?
- Textiful keeps retrying for a little under three days, with the same body and Delivery ID each time. You can also retry by hand from the Sync and delivery log.
- Can I send to a webhook without a developer?
- You need something that receives the request. If you don't have that, Zapier is usually the easier route.