Documentation Index
Fetch the complete documentation index at: https://docs.spitshake.io/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Webhooks let your application receive real-time notifications when events happen in DocuTrust. Instead of polling the API, DocuTrust sends an HTTP POST request to your configured endpoint whenever a relevant event fires. Each webhook delivery includes a JSON payload describing the event, a cryptographic signature for verification, and a unique delivery ID for deduplication.Supported Events
DocuTrust emits 14 event types across four resource categories:Form Events
Triggered when a submitter interacts with a signing form.| Event | Description |
|---|---|
form.created | A new signing form was generated and assigned to a submitter. |
form.started | The submitter began filling out the form (first field interaction). |
form.viewed | The submitter opened the signing link. |
form.completed | The submitter finished and submitted the form. |
form.declined | The submitter declined to sign the document. |
form.expired | The form’s expiration date passed without completion. |
signing.complete | Identity-bound only. Fires after form.completed when the submission was signed via the SpitShake Identity Engine handoff (JWT with verified_name + stripe_verification_id). Payload includes an identity block with the verified tuple. See Identity-bound signing. |
Field Events
| Event | Description |
|---|---|
field.updated | A submitter changed the value of a field in a form. |
Submission Events
Triggered when the overall submission (containing one or more submitters) changes state.| Event | Description |
|---|---|
submission.created | A new submission was created from a template. |
submission.completed | All submitters in the submission have completed their forms. |
submission.archived | The submission was archived by an admin. |
submission.expired | The submission expired before all submitters completed. |
Template Events
| Event | Description |
|---|---|
template.created | A new template was created. |
template.updated | A template’s fields, documents, or settings were modified. |
template.archived | A template was archived. |
Event Payloads
Every webhook delivery is an HTTP POST withContent-Type: application/json. The top-level structure is always:
Form Event Payload
All form events (form.created, form.started, form.viewed, form.completed, form.declined, form.expired) share this structure:
For
form.declined events, the declined_at field will contain a timestamp and completed_at will be null. For form.expired events, both completed_at and declined_at will be null.Submission Event Payload
Submission events include the full list of submitters and their statuses:Document download URLs in payloads
Thesubmission.completed and form.completed webhook payloads include a documents array with download URLs, so you can retrieve signed PDFs directly from the event without a follow-up API call:
download_url requires authentication (Bearer token or X-Auth-Token with submissions:read scope).
Template Event Payload
Template events include metadata about the template’s structure:Field Updated Payload
Fired each time a submitter changes a field value. Includes the old and new values for change tracking:Webhook Headers
Every webhook delivery includes the following HTTP headers:| Header | Description | Example |
|---|---|---|
Content-Type | Always JSON. | application/json |
X-Webhook-Signature | HMAC-SHA256 signature of the raw request body. | sha256=5d7b1e3a9f... |
X-Webhook-Secret | The shared secret configured for this webhook endpoint. | whsec_abc123def456 |
X-Webhook-Delivery-Id | Unique UUID identifying this delivery attempt (use for deduplication). | e7f8a9b0-c1d2-3456-e7f8-a9b0c1d23456 |
User-Agent | Identifies the sender. | DocuTrust-Webhook/1.0 |
HMAC Signature Verification
Every webhook includes anX-Webhook-Signature header containing an HMAC-SHA256 digest of the raw request body, signed with your webhook secret key:
Managing Webhooks via API
Create a Webhook Endpoint
Update a Webhook Endpoint
List All Webhook Endpoints
Delete a Webhook Endpoint
204 No Content on success.
Webhook Delivery Log
Retrieve the delivery history for a specific webhook endpoint. Each entry includes the HTTP status code, response time, payload, and any error details.| Parameter | Type | Default | Description |
|---|---|---|---|
status | string | — | Filter by delivery status: "success", "failed", "pending". |
event | string | — | Filter by event type (e.g., "form.completed"). |
after | integer | — | Cursor for pagination (return items after this delivery ID). |
before | integer | — | Cursor for pagination (return items before this delivery ID). |
limit | integer | 25 | Items per page (1-100). |
| Field | Type | Description |
|---|---|---|
id | integer | Unique delivery identifier. |
webhook_id | integer | The webhook endpoint this delivery belongs to. |
event | string | The event type that triggered this delivery. |
status | string | Delivery status: "success", "failed", or "pending". |
http_status | integer or null | The HTTP status code returned by your endpoint, or null if the request failed before receiving a response. |
url | string | The URL the delivery was sent to. |
request_headers | object | The HTTP headers sent with the delivery. |
request_body | object | The full JSON payload sent in the request body. |
response_status | integer or null | The response HTTP status code. |
response_body | string or null | The response body (truncated to 1KB). |
response_time_ms | integer or null | Response time in milliseconds. |
attempt | integer | The attempt number (1 = first delivery, 2+ = retries). |
max_attempts | integer | Maximum number of delivery attempts (always 6). |
error_message | string or null | Error description if the delivery failed. |
delivered_at | string or null | ISO 8601 timestamp when the delivery was successfully received. |
created_at | string | ISO 8601 timestamp when the delivery was created. |
Redelivering a failed webhook
If a delivery failed or was exhausted, you can trigger a redeliver:delivery_uuid.
Test a Webhook Endpoint
Send a test delivery to verify your endpoint is working correctly.Retry Policy
If your endpoint does not return an HTTP2xx response, DocuTrust retries the delivery up to 5 times with increasing delays:
| Attempt | Delay After Failure |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry | 12 hours |
- Connect timeout: 5 seconds. If DocuTrust cannot establish a TCP connection within 5 seconds, the attempt fails.
- Read timeout: 10 seconds. If your server does not send a complete response within 10 seconds of connection, the attempt fails.
X-Webhook-Delivery-Id, so you can use it to deduplicate deliveries on your end.
SSRF Protection
DocuTrust validates all webhook URLs before delivering events. The following restrictions apply to protect against Server-Side Request Forgery (SSRF) attacks: Blocked IP ranges:| CIDR Block | Description |
|---|---|
10.0.0.0/8 | Private network (Class A) |
172.16.0.0/12 | Private network (Class B) |
192.168.0.0/16 | Private network (Class C) |
127.0.0.0/8 | Loopback (localhost) |
169.254.0.0/16 | Link-local / cloud metadata |
100.64.0.0/10 | Carrier-grade NAT (shared address space) |
- HTTPS required in production. HTTP URLs are only accepted in development/test environments.
- Localhost blocked. URLs containing
localhost,127.0.0.1, or[::1]are rejected. - Cloud metadata endpoints blocked. URLs targeting
169.254.169.254and similar metadata service IPs are rejected.
Best Practices
Verify signatures on every request
Verify signatures on every request
Always validate the
X-Webhook-Signature header before processing any webhook payload. Never skip verification, even in development.Use the delivery ID for deduplication
Use the delivery ID for deduplication
Store the
X-Webhook-Delivery-Id header value and check for duplicates before processing. Retries will send the same delivery ID.Respond quickly, process asynchronously
Respond quickly, process asynchronously
Return a
200 status immediately and enqueue the payload for background processing. Long-running synchronous handlers risk timeouts and unnecessary retries.Handle events idempotently
Handle events idempotently
Your webhook handler may receive the same event more than once due to retries. Design your processing logic to be safe for repeated execution.
Subscribe only to events you need
Subscribe only to events you need
Selecting specific events reduces traffic to your endpoint and simplifies your handler logic. You can always add more events later.
Monitor your endpoint health
Monitor your endpoint health
Set up alerting for elevated error rates or slow response times on your webhook handler. DocuTrust will stop retrying after 5 failures.