Webhooks
Webhooks notify your server when contract lifecycle events happen in SpotDraft. Register one or more HTTPS endpoints in Settings -> Developer settings -> Webhooks, choose the event types, and SpotDraft delivers an HTTP POST with a JSON payload.
Return a 2xx response quickly. Queue slow work so timeouts do not count as failed deliveries.
Retry behavior
SpotDraft retries a delivery when your endpoint does not return a 2xx response, including timeouts and connection failures.
The first delivery is immediate. If it fails, SpotDraft schedules retries for that event at 5, 10, 20, 40, 80, then 160 minutes after the previous failed attempt. A worker picks up due retries about every minute, so the actual POST can land slightly after the scheduled time.
Each attempt waits up to 5 seconds to connect and 60 seconds for a response. A timeout counts as a failed delivery.
Retry and disablement are separate counters:
- Every failed
POST(the first attempt and later retries) increments a consecutive-failure counter on the webhook subscription. A successful delivery resets that counter to 0. - After 6 consecutive failed deliveries, SpotDraft disables the subscription. Any later scheduled retry is skipped, not sent.
- For an endpoint that never returns
2xx, you receive 6POSTs: the first delivery plus retries at 5, 10, 20, 40, and 80 minutes. The 160-minute retry is not delivered because the subscription is already disabled.
Re-enable the webhook in Settings -> Developer settings -> Webhooks after you fix the endpoint.
Because a retry can send the same event more than once, persist a dedupe key before you return 2xx and make downstream writes idempotent.
Delivery requirements
- Use
HTTPSwith a publicly trusted certificate. - Keep the endpoint publicly reachable from SpotDraft.
- Support multiple webhook URLs per account when different systems need separate receivers.
- Subscribe only to the event types your integration needs.
- Acknowledge quickly and process downstream work asynchronously.
Verification
Use X-SD-WEBHOOK-CONTENT-HASH for verification. Validate the raw request body with HMAC-SHA512 using the hmac_key returned by the HMAC key API.
import base64
import hashlib
import hmac
signature = hmac.new(
base64.b64decode(sample_hmac_key),
request.body,
digestmod=hashlib.sha512,
).hexdigest()
assert signature == request.headers["X-SD-WEBHOOK-CONTENT-HASH"]
Compare against the raw request body bytes before any JSON parsing or normalization.
Processing model
Use this production shape:
- read the raw request body
- verify
X-SD-WEBHOOK-CONTENT-HASH - parse the JSON payload
- persist a delivery id, event id, payload hash, or other dedupe key
- enqueue downstream work
- return
2xxquickly - let a worker update CRM, ERP, storage, warehouse, notification, or internal systems
Webhook delivery is a change signal. If downstream systems need the latest complete record, fetch the contract, document, metadata, or status from the API after receiving the event.
Reconciliation
Keep webhooks as the primary path. Add a scheduled job that compares recent SpotDraft state with your internal records and repairs drift.
Do not poll every contract on a short interval just to detect lifecycle changes. Do not treat the webhook payload as the only durable source of truth. Do not run slow downstream writes inside the webhook request thread.
Common activity types
Subscribe only to the events your integration needs. The values below are the only_for_activities options on POST /api/v2.1/public/webhooks/.
Contract lifecycle
activity value | When it fires |
|---|---|
CONTRACT_CREATED | A new contract is created |
CONTRACT_DATA_UPDATED | Contract data changes |
CONTRACT_VERSION_UPLOADED | A new contract version is uploaded |
CONTRACT_DELETED | The contract is deleted |
CONTRACT_VOIDED | The contract is voided |
CONTRACT_SENT_TO_COUNTERPARTY | The contract is sent for counterparty review or redlining |
CONTRACT_REVIEW_REQUESTED | Internal review is requested |
CONTRACT_REVIEW_COMPLETED | Internal review is completed |
CONTRACT_MARK_FOR_EXECUTION | The contract is marked for execution |
CONTRACT_UNMARK_FOR_EXECUTION | The contract is unmarked for execution |
CONTRACT_SIGNATURE_REQUESTED | The contract is marked or sent for signature |
CONTRACT_SIGNATURE_DECLINED | A signatory declines to sign |
CONTRACT_SIGNED | A required signatory completes signing |
CONTRACT_EXECUTED | All required signatures are complete |
CONTRACT_PROCESS_METRIC_UPDATED | Workflow metrics change |
CONTRACT_ENTITY_UPDATED | The contract entity changes |
CONTRACT_ACTIVITY_LOG_COMMENT_CREATED | A comment is added to the contract activity log |
Approvals and structured data
activity value | When it fires |
|---|---|
CONTRACT_APPROVAL_REQUESTED | An approval is requested |
CONTRACT_APPROVAL_COMPLETED | An approval is completed |
CONTRACT_EXTERNAL_METADATA_CREATED | External metadata is created on the contract |
CONTRACT_EXTERNAL_METADATA_UPDATED | External metadata on the contract is updated |
CONTRACT_KEY_POINTER_CREATION | A key pointer is created |
CONTRACT_KEY_POINTER_UPDATION | A key pointer is updated |
Counterparties
activity value | When it fires |
|---|---|
COUNTER_PARTY_CREATED | A counterparty is created |
COUNTER_PARTY_UPDATED | A counterparty is updated |
COUNTER_PARTY_CONTACT_CREATED | A counterparty contact is created |
COUNTER_PARTY_CONTACT_UPDATED | A counterparty contact is updated |
COUNTER_PARTY_ADDRESS_CREATED | A counterparty address is created |
COUNTER_PARTY_ADDRESS_UPDATED | A counterparty address is updated |
Email and notification events
activity value | When it fires |
|---|---|
POSTMARK_EMAIL_EVENT | A Postmark email event is recorded |
SIGNING_EMAIL_DELIVERED | A signing email is delivered |
SIGNING_EMAIL_OPENED | A signing email is opened |
SIGNING_EMAIL_NOT_DELIVERED | A signing email is not delivered |
SIGNING_EMAIL_LINK_CLICKED | A signing email link is clicked |
REDLINING_EMAIL_DELIVERED | A redlining email is delivered |
REDLINING_EMAIL_OPENED | A redlining email is opened |
REDLINING_EMAIL_NOT_DELIVERED | A redlining email is not delivered |
REDLINING_EMAIL_LINK_CLICKED | A redlining email link is clicked |
CONTRACT_SIGNATURE_REQUESTED_NOTIFICATION_SENT | A signature-requested notification is sent |
Use the API reference POST /api/v2.1/public/webhooks/ operation for request schema, examples, and version-specific payload fields.
Debugging expectations
SpotDraft shows webhook logs in the app. Successful delivery records are retained for 30 days; failed delivery records are retained for 90 days. API logs are not exposed. Your receiver should still keep its own logs for signature verification, queue jobs, retries, and downstream processing.
At minimum, log:
- endpoint URL and environment
- event type or activity
- contract id or reference id when present
- delivery id, event id, or payload hash
- signature verification result
- queue job id
- response status returned to SpotDraft
- downstream processing result
When investigating failures, confirm that the destination URL belongs to the same region and environment strategy you use for the rest of the integration and that your endpoint returns a 2xx quickly.