Payload
Custom webhooks only. When you add a destination without picking a built-in provider, Formspring POSTs the JSON below to your URL and signs the raw body with X-Formspring-Signature. Built-in providers (Slack, Mailchimp, HubSpot, …) use each vendor’s own JSON shape and do not send this envelope or the HMAC header.
Headers
X-Formspring-Signature: t=<unix>,v1=<hmac_sha256_hex>
X-Formspring-Event: submission.created
X-Formspring-Delivery: <delivery row id>
Content-Type: application/json
User-Agent: formspring/1.0 (webhook delivery)
The signature is computed as HMAC_SHA256(whsec_…, "<t>.<raw_body>") where <t> is the t= unix timestamp and <raw_body> is the exact JSON string we POST. This is the industry-standard t=…,v1=… HMAC convention so existing verification code can be reused.
There is no separate X-Formspring-Timestamp header; parse the timestamp from the signature prefix.
Envelope (api_version 2026-05-07)
{
"event": "submission.created",
"api_version": "2026-05-07",
"data": {
"id": "01HFXX0X9R7KZJVN9VS6TG2C5T",
"form_id": "r2EdO-orF-3S",
"created_at": "2026-05-07T16:09:10Z",
"status": "processed",
"payload": {
"email": "ada@example.com",
"name": "Ada Lovelace",
"message": "Loved the docs."
},
"consent_snapshot": [],
"assigned_to_user_id": null,
"due_at": null,
"resolved_at": null,
"files": [
{
"field": "resume",
"original_name": "cv.pdf",
"mime": "application/pdf",
"size_bytes": 184213
}
]
}
}
| Field | Type | Notes |
|---|---|---|
event |
string | Currently submission.created for clean submissions. |
api_version |
string | Version of this envelope; bump when breaking changes ship. |
data.id |
string | Submission id (ULID-style). Use as your idempotency key. |
data.form_id |
string | The form’s public id (/f/{form_id}). |
data.created_at |
ISO 8601 | When the submission was stored. |
data.status |
string | Submission workflow status at send time. |
data.payload |
object | Raw submitted fields. |
data.consent_snapshot |
array | Consent records captured with the submission. |
data.assigned_to_user_id |
int|null | Inbox assignment when set. |
data.due_at |
string|null | ISO 8601 due time when set. |
data.resolved_at |
string|null | ISO 8601 when resolved. |
data.files |
array | File metadata only (field, name, mime, size). Binary downloads use signed routes in the app, not inline URLs in this payload. |
Size and reliability
Large payloads may be truncated at ingestion time; very heavy file bodies are never inlined. Failed deliveries are retried automatically with exponential backoff (see Retries →).