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

  1. Open the flow under Data Capture Flows.
  2. Click the + where the webhook should run (usually after your last question), or Add a step.
  3. Under Actions and integrations, choose Send to a webhook.
  4. Paste your URL into Webhook URL. It must be a public http or https address.
  5. 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, and timezone, 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 as poll_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 2xx status to accept the delivery.
  • Any other status (including redirects, 4xx, and 5xx), 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 Gone tells 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.

Related articles