jump to content

Webhooks Overview

Explains how the platform webhooks work, covering the signed JSON envelope, delivery requirements, HTTP headers, retry behavior, and a receiver checklist.

View as Markdown

Webhooks let your application react when resources change in the platform without polling the API. A subscription connects one HTTPS endpoint to a set of events in one organization. When an event occurs, the platform sends a signed POST request containing a JSON snapshot of the affected resource.

Common uses include synchronizing users and third parties, starting document approval workflows, and recording compliance events in another system.

Webhook subscriptions currently deliver events for:

DomainEvent families
Third partiesthird-party:*
Usersuser:*
Obligationsobligation:*
Rights requestsright-request:*
Documentsdocument:*, document-version:*, signature and approval quorum events

Other product areas — including frameworks, controls, measures, risks, access reviews, devices, and cookie consent — are available through GraphQL, the CLI, MCP, and n8n, but they do not emit webhook events today. Use polling or a scheduled reconcile job for those domains when your integration must stay current.

See Event types for the full payload reference for supported events.

sequenceDiagram
  participant P as Probo
  participant E as Your endpoint

  Note over P: A subscribed resource changes
  P->>P: Queue event, poll every ~5s
  P->>+E: POST signed JSON
  E->>E: Verify signature
  E->>E: Reject stale timestamp
  E->>E: Record eventId, enqueue
  E-->>-P: 2xx within 30s
  Note over P,E: Failed deliveries are not retried
One delivery, from the change in the platform to your acknowledgement.
  1. Expose an HTTPS endpoint

    Your endpoint must accept POST requests with an application/json body.

  2. Create a subscription

    In the platform, open Settings > Webhooks, enter the endpoint URL, and select the events to receive. You can also manage subscriptions with the CLI.

  3. Verify every delivery

    Verify the signature against the raw request body and reject stale timestamps before parsing or acting on the payload.

  4. Acknowledge quickly

    Persist or enqueue the event, then return an accepted 2xx response. Perform slow work asynchronously.

  • The URL must use HTTPS.
  • The endpoint must return 200, 201, 202, or 204.
  • The complete response must arrive within 30 seconds.

Any other status, connection error, or timeout marks the delivery as failed. the platform does not retry failed deliveries, so monitor delivery history and design a recovery process for missed events.

Every delivery body is a JSON object with a fixed root envelope. Resource-specific fields live under data (and optionally updatedFrom) — they are never promoted to the root.

{
  "eventId": "whevt_01ABC123",
  "subscriptionId": "whsub_01DEF456",
  "organizationId": "org_01GHI789",
  "eventType": "document:updated",
  "createdAt": "2026-07-15T10:30:00Z",
  "data": {
    "id": "doc_01VWX234",
    "title": "Information Security Policy"
  },
  "updatedFrom": {
    "id": "doc_01VWX234",
    "title": "InfoSec Policy"
  }
}
Root fieldTypeAlways presentDescription
eventIdstringYesUnique delivery ID. Use it as an idempotency key
subscriptionIdstringYesWebhook subscription that received the event
organizationIdstringYesOrganization where the event occurred
eventTypestringYesWire-format event name (e.g. document:updated, third-party:created)
createdAtstringYesWhen the event was created (RFC 3339)
dataobjectYesCurrent resource payload for the event. Shape depends on eventType — see Event Types
updatedFromobjectNoPresent only on *:updated events. Full snapshot of the same resource shape as data, taken before the update. Omitted for create, delete, archive, signature, and other non-update events
  1. Verify the signature using the headers and untouched request body.
  2. Parse the JSON only after verification succeeds.
  3. Confirm organizationId and eventType are ones your endpoint expects.
  4. Atomically record eventId before producing side effects. Ignore an ID you have already processed.
  5. Enqueue the event and return a successful response.

For update events, compare updatedFrom with data to identify the change. Resource IDs such as a document or user ID are nested under data; they are not root fields.

Each request also carries metadata in headers. Some headers mirror root envelope fields so you can route or reject a delivery before parsing the body.

HeaderMirrors body fieldDescription
Content-TypeAlways application/json
X-Probo-Webhook-EventeventTypeWire-format event name (e.g. document:updated)
X-Probo-Webhook-Organization-IdorganizationIdOrganization ID
X-Probo-Webhook-TimestampUnix timestamp in seconds used when computing the signature
X-Probo-Webhook-SignatureHex-encoded HMAC-SHA256 of {timestamp}:{rawBody}
X-Probo-Webhook-HostHostname of the the platform instance that sent the delivery (for multi-region / self-hosted receivers)
Use casePrefer
Signature verificationHeaders (X-Probo-Webhook-Timestamp, X-Probo-Webhook-Signature) + raw body bytes
Fast allow/deny before JSON parseHeaders (X-Probo-Webhook-Event, X-Probo-Webhook-Organization-Id, X-Probo-Webhook-Host)
Business logic / diffsRoot envelope + data / updatedFrom
IdempotencyRoot eventId

subscriptionId and createdAt exist only in the body root — they are not duplicated as headers.

the platform generates a signing secret prefixed with whsec_ for each subscription. Store it in a secret manager, scope it to the receiving service, and never log it or include it in client-side code. The secret is required to verify webhook signatures.

  • the platform polls for pending events approximately every 5 seconds and processes them sequentially.
  • A delivery succeeds only when the endpoint returns 200, 201, 202, or 204 within 30 seconds.
  • Failed deliveries are not retried automatically.
  • the platform stores the response status, headers, and up to 64 KB of the response body for troubleshooting.
  • Delivery status is PENDING, SUCCEEDED, or FAILED.

Review delivery history under Settings > Webhooks. Avoid returning secrets or sensitive records in your response body because the response is retained for debugging.

  • Preserve the raw body until signature verification is complete.
  • Accept requests only from expected organizations and event types.
  • Use eventId to make processing idempotent.
  • Queue work before sending the response.
  • Alert on FAILED deliveries and reconcile missed changes.
  • Ignore unknown JSON fields so additive payload changes do not break your receiver.

Ultima actualizare: