Skip to content

Webhook Payloads

Each webhook delivery is an HTTP POST request with a JSON body. DocSpring waits up to 30 seconds for your endpoint to respond, and treats any 2xx status code as a successful delivery.

Every request includes these headers:

HeaderValue
Content-Typeapplication/json
Acceptapplication/json
User-AgentDocSpring/Webhooks
X-DocSpring-Event-IdThe event ID, the same as the body’s id (see Event IDs below)
X-DocSpring-SignatureThe signature used to verify the request (see below)

Any custom Headers you configured on the webhook are added as well.

Submission events on a legacy v1/v2 webhook are sent without a signature or event ID and with a DocSpring User-Agent — see Webhook versions below.

The body is a JSON object with four top-level keys:

{
"id": "6f1c2e8a-3b4d-4c5e-9f60-7a8b9c0d1e2f",
"event": "submission.processed",
"timestamp": "2026-06-27T03:16:07Z",
"data": {
"resource": {
"type": "Submission",
"id": "sub_0XYZ..."
},
"id": "sub_0XYZ...",
"state": "processed",
"test": false,
"template_id": "tpl_0ABC...",
"download_url": "https://...amazonaws.com/...pdf?X-Amz-Signature=...",
"metadata": { "customer_id": "cus_123" },
"data": {
"name": "Jane Doe",
"amount": "1234.00"
}
}
}
FieldDescription
idThe event ID. It stays the same when a delivery is retried.
eventThe event type, e.g. submission.processed.
timestampUTC ISO 8601 time the event was sent.
dataThe event payload (see below).

Every timestamp in the body — timestamp and any *_at field on the serialized resource, such as processed_at or updated_at — is a UTC ISO 8601 string with second precision, e.g. 2026-06-27T03:16:07Z. The same format is used for timestamps in API responses.

data contains:

  • resource — a small pointer to the resource that triggered the event, with its type (e.g. Submission) and id (e.g. sub_0XYZ...).
  • The rest of data is the serialized resource itself. For a submission this is the same object the API returns — including its id, state, download_url, metadata, and so on.

The fields in data for each resource type (data.resource.type):

data.resource.typeFields
SubmissionThe API’s submission object
CombinedSubmissionThe API’s combined submission object
SubmissionBatchThe API’s submission batch object, without its submissions
TemplateThe API’s template object, as returned when listing templates
SubmissionDataRequestid, submission_id, name, email, completed_at, fields
Folderid, name, path, parent_folder_id
CustomFileid, url
APITokenid, name, test, revoked_at, created_at
Userid, name, email, created_at, invitation_sent_at, invitation_accepted_at
AccountIntegrationid, service, enabled, created_at, updated_at
Webhookid

See the API Reference for the fields of the objects the API returns.

Every v3 delivery has an event ID, sent as the body’s top-level id and in the X-DocSpring-Event-Id header. The ID stays the same when DocSpring retries a delivery, so you can use it to recognize an event you’ve already processed and ignore the repeat.

Each webhook gets its own event ID. If two of your webhooks receive the same event, their deliveries have different IDs.

Use the body’s id for deduplication. It’s covered by the signature, so it can’t be changed without breaking the signature. The header is a copy for convenience and isn’t signed.

Every webhook has a version that controls the payload format used for submission events — submission.processed, submission.failed, and the other submission.* events:

VersionFormat
v3 (current)The event envelope shown above (id, event, timestamp, data).
v2 (legacy){ "submission": { ... } } — the serialized submission as a JSON object.
v1 (legacy)A form-encoded body with a single submission field holding the serialized submission as a JSON string.

New webhooks default to v3, which we recommend for all new integrations. The v1 and v2 formats exist only so that endpoints created before the current webhook system keep receiving the exact payloads they were built for.

Include submission data and strip fields still apply to legacy payloads; they filter the serialized submission before it is wrapped in the v1/v2 envelope. Legacy deliveries are sent with a DocSpring User-Agent and are not signed, matching the original webhook behavior.

By default the submitted form values are included (under data.data). If you only need to know that an event happened — and want to avoid sending field data to your endpoint — turn Include submission data off. DocSpring then omits the data.data object from the payload while keeping the rest of the event.

Use strip fields to remove individual fields from the payload — for example to keep sensitive values like SSNs or card numbers out of your logs.

List dot-separated paths from the root of the event’s data object. Form field values live under its data key, so a form field is removed with data.<field name>. A bare name removes a whole top-level key, such as metadata or password:

data.ssn
data.card_number
metadata.internal_note
password

The example above removes the ssn and card_number form fields, the internal_note metadata value, and the submission’s password field. Entries that don’t match anything are ignored.

Add custom Headers to every request — for example a static bearer token or a routing header your endpoint expects. Note that custom headers are a convenience, not a security mechanism: always rely on the signature to authenticate requests.