Skip to main content
For AI agents: a documentation index is available at https://docs.coverbase.com/llms.txt. This page is also available in markdown by appending .md to the URL.
Webhooks are the outbound half of an integration. This page documents how events are delivered, how to verify signatures, retry behavior, and the event catalog. To register, list, update, delete, test, or inspect the delivery history of a subscription, see the Webhooks API. For the audit trail of every attempt, see Webhook delivery history. Admins can do the same from the dashboard under Configuration → Webhooks. Add webhook takes an Endpoint URL, a Signing secret of at least 16 characters (shown only once), the Events to subscribe to, an optional Description, and an Enabled switch. Each row has Send test, Delivery history, Edit and Delete buttons, and the Health column shows the last delivery’s status and the share of recorded deliveries that got a response.

When deliveries happen

When a subscribed event occurs, Coverbase POSTs a JSON envelope to every active webhook subscribed to that event type. Deliveries originate from three sources, and all of them are recorded in delivery history:
  • Domain-event fan-out: a domain event (e.g. a vendor is created) fans out to every subscription for that event type.
  • Workflow send_webhook action: a workflow automation explicitly delivers its triggering event, either to the webhooks the action names or to every subscription for the event type. See Workflow engine → Actions.
  • Manual test: the test endpoint, or Send test on the Webhooks page, sends a one-off delivery to a single subscription.
For one source event, the same event_id is shared across all webhooks in the fan-out. Receivers can use it to dedupe a fan-out and to correlate a multi-subscription delivery. A workflow send_webhook action generates its own event_id each time it runs, so an event delivered by both the fan-out and a workflow action arrives with two different IDs.
A webhook with no events selected receives nothing from the fan-out. Use that for an endpoint that should only receive what a workflow’s send_webhook action addresses to it.

Delivery format

A delivery is an HTTP POST with a JSON body in this exact envelope:
The envelope is exactly these four keys; there is no top-level workflow_run_id or any other field.

Request headers

Signature verification

The signature is HMAC-SHA256(secret, raw_request_body) rendered as a lowercase hex string, sent in the Coverbase-Signature header. The key is the secret you registered with the subscription. Verify it against the raw bytes of the request body, before parsing JSON, with a constant-time comparison. To reject replayed deliveries, compare Coverbase-Timestamp with your own clock and drop anything outside a window you choose (five minutes is typical). The same value is inside the signed body as occurred_at, so an attacker cannot change the header without the body no longer matching it.
Python
Node.js

Delivery & retries

occurred_at and event_id are generated at send time. Make your receiver idempotent: dedupe on X-Coverbase-Event-Id and process the same event id at most once. Respond with a 2xx within 10 seconds. Because a failed attempt is not retried, events sent while your receiver is down or returning errors are not redelivered: after an outage, use delivery history to see which events you missed and read the affected records back through the API.

Source IP

Coverbase does not publish a fixed egress IP range for outbound webhook deliveries. Authenticate the sender by HMAC signature verification (see Signature verification), not by source IP. The compute fleet is autoscaled and the public IPs that originate deliveries change frequently. If you operate behind a network perimeter that requires a static allow-list, route deliveries through a customer-controlled HTTPS proxy with a stable egress IP and forward to the real receiver after re-verifying the signature.

Delivery history retention

Every delivery attempt is recorded in delivery history for 90 days. Older rows are deleted by a daily background job; the API still serves the window inside retention via GET /v1/webhooks/{id}/deliveries. Capture deliveries you need beyond that window from your receiver side at delivery time.

URL restrictions

Webhook URLs must be public HTTPS endpoints. A URL is rejected at create/update time (400 invalid_url) if it is not HTTPS, carries credentials, uses a non-standard port, or resolves to a private, loopback, link-local, or metadata address (e.g. 169.254.169.254). The same check is re-applied with DNS resolution at delivery time, so a hostname that is repointed to an internal address after registration (DNS rebinding) is still blocked. A delivery blocked this way is recorded with status error in delivery history.

Event catalog

These are the only values valid in a subscription’s events array and the only event types emitted. The events field is strictly validated against this set; see the behavior change below. Use the exact, case-sensitive strings. The same list is what the Events picker on the Webhooks page offers.
*.Updated events carry a field_diffs object mapping each changed field to its { "old_value", "new_value" }, so a status change arrives as Vendor.Updated (or Assessment.Updated, Review.Updated, and so on) with the status field in field_diffs. A soft-archive (is_archived → true) surfaces as *.Deleted, not *.Updated.A radar alert is a RadarDetectorResult: subscribe to RadarDetectorResult.Created to be notified of new alerts and RadarDetectorResult.Updated (whose field_diffs will include is_dismissed) for triage activity. A signal is a RadarSignal. See the Radar and Reassessments APIs.

Supplier profile events

The VendorBankAccount, VendorContact, SupplierSite, SupplierTaxRegistration, SupplierDiversityRecord, SupplierUpdateRequest and SupplierLegalEntityAssignment events describe changes to a supplier’s profile. Besides their own ID, each carries: A sensitive change fires its event only after a reviewer approves it, not when it is requested. All IDs are opaque prefixed strings (e.g. cbvndr_..., cbqsrw_...); see API conventions → IDs. Every event’s data also echoes its own event_type.
webhook.test is a valid value only for the test endpoint’s event_type field. It is not a subscribable event type; it will be rejected if used in a subscription’s events array.

Strict event-type validation

Breaking change. events is now strictly validated against the catalog above. Previously any free-form string was accepted. A POST /v1/webhooks or PATCH /v1/webhooks/{id} whose events contains a value not in the catalog now fails with 422 invalid_event_types. Integrations that registered non-canonical strings (e.g. lowercase vendor.created) must switch to the exact catalog value (e.g. Vendor.Created).