Receiving status webhooks

Subscribe an HTTPS endpoint to get a signed POST when a signature task changes status, instead of polling alone.

After Create Task, prefer status webhooks to learn when a task moves (for example to Pending, Completed, Rejected, Retracted, or Failed). SutureHealth POSTs to your HTTPS URL for each change. Keep Read Task / Bulk Read for downloading the signed PDF, ad-hoc checks, and reconciliation if a delivery was missed.

You manage subscriptions with the Partner API (x-api-key). Delivery is a separate outbound call from SutureHealth to your server — no API key on that POST. Authenticity comes from an HMAC signature and a per-subscription secret returned only at create time.

Reference: Register Webhook, List Webhooks, Update Webhook, Delete Webhook.


When to use webhooks vs polling

ApproachRole
WebhooksPreferred for status changes — near real time, no tight poll loop
Read by idFetch the signed PDF after Completed, or confirm a single task if needed
Bulk readReconciliation, catch-up after downtime, or listing many tasks

Recommended pattern: register a webhook for status changes, then on Completed call Read Task By Id with includeOutputAttachment=true (or false if you only need metadata) and update the task with your saved-document id.


Register a subscription

POST /api/v1/signature/webhooks

POST /api/v1/signature/webhooks
Host: partner-api.demo.suturehealth.com
x-api-key: YOUR_API_KEY
Content-Type: application/json

{
  "url": "https://partner.example.com/suture/webhooks",
  "description": "Production status receiver"
}
FieldRequiredNotes
urlYesAbsolute HTTPS URL SutureHealth will POST to
descriptionNoUp to 255 characters

201 response (shape):

{
  "id": 42,
  "url": "https://partner.example.com/suture/webhooks",
  "secret": "base64-encoded-256-bit-secret",
  "description": "Production status receiver"
}
⚠️

Store secret immediately. It is returned only on create. List and update responses do not include it. You need it to verify X-Suture-Signature on every delivery.

The subscription is active as soon as it is created. It is scoped to the organization on your API key: you only receive events for that org’s tasks.


Delivery request

SutureHealth sends:

POST https://partner.example.com/suture/webhooks
Content-Type: application/json
X-Suture-Signature: sha256=<hex>
X-Suture-Timestamp: <unix-seconds>
X-Suture-Event-Id: <guid>
X-Suture-Event-Type: document.status_changed

Example body (camelCase JSON):

{
  "eventId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "eventType": "document.status_changed",
  "taskId": 184392,
  "documentId": 77821,
  "status": "Pending",
  "statusReason": null,
  "occurredAtUtc": "2026-08-14T15:02:48Z"
}
FieldMeaning
eventIdUnique id for this delivery event (use for idempotency)
eventTypeAlways document.status_changed for this release
taskIdPartner API task id (same as create / read)
documentIdSutureHealth inbox request id when known; may be null early
statusTask status string (Pending, Completed, Rejected, …) — same values as tracking
statusReasonOptional reason (for example on Failed)
occurredAtUtcWhen the status change occurred (UTC)

The webhook body does not include the signed PDF. On Completed, read the task (or list with filters) to download output.attachment.

What your endpoint should do

  1. Verify the signature (below).
  2. Treat eventId as idempotent — retries can deliver the same event more than once.
  3. Return 2xx quickly. Non-success responses are treated as delivery failures and may be retried.
  4. Do heavy work (download PDF, write to your EMR) asynchronously after acknowledging the POST.

Verify the signature

The signed content is the UTF-8 string:

{X-Suture-Timestamp}.{raw request body}

Compute HMAC-SHA256 with your subscription secret as the key. Encode the digest as lowercase hex. The X-Suture-Signature header value is:

sha256=<hex>

Compare in constant time. Also reject requests whose timestamp is too far from your clock (replay window — choose a limit that fits your ops, for example a few minutes).

Pseudocode:

signed = timestamp + "." + rawBodyBytes
expected = hex_lower(hmac_sha256(secret, signed))
header  = "sha256=" + expected
accept if timing_safe_equal(header, X-Suture-Signature)

List, pause, and remove subscriptions

List

GET /api/v1/signature/webhooks → 200 array of subscriptions (id, url, description, isActive, createdAt, updatedAt). No secrets.

Deactivate or change URL

PATCH /api/v1/signature/webhooks/{id}

{ "active": false }

or

{ "url": "https://partner.example.com/suture/webhooks-v2" }

Inactive subscriptions do not receive deliveries. Reactivate with "active": true.

Delete

DELETE /api/v1/signature/webhooks/{id} → 204. Soft-deletes the subscription; it no longer receives events.

All of these require x-api-key and only affect subscriptions for your organization.


Recommended integration pattern

  1. Register one HTTPS endpoint per environment and store id + secret.
  2. On each delivery, verify the signature, then enqueue work keyed by eventId / taskId.
  3. When status is Completed (or Rejected), read the task for the PDF or rejection outcome, then update with your externalSavedDocumentId.
  4. Keep periodic bulk read as a safety net for missed events.
  5. Deactivate or delete the subscription when rotating endpoints; create a new one if you need a new secret.

Errors (management API)

SituationTypical response
Missing or invalid x-api-key401 or 403
Invalid create/update body (for example missing url)400
Unknown webhook id for this key400

Did this page help you?