Skip to Content
AdministrationWebhooks Configuration

Webhooks

Outbound webhooks let Veriproof push event notifications to your own systems in real time. When an event matches a registered webhook, the platform sends an HTTPS POST request to your endpoint with a signed JSON payload.

Webhook management requires the CustomerAdmin role. All other roles can view registered webhooks.

Event Types

Event typeFired when
alert.triggeredAn alert rule threshold is crossed
alert.resolvedA triggered alert returns below threshold
session.flaggedA session receives an attention flag
session.review.approvedA session review decision is approved
session.review.rejectedA session review decision is rejected
governance.threshold_breachedGovernance score crosses a configured threshold
gdpr.erasure_completedA GDPR erasure request has been cryptographically completed
gdpr.legal_hold_placedA legal hold is placed on a data subject
application.purge_completedAn application purge has finished
quality.score_computedSession quality scoring result is available
evidence_package.readyAn evidence package export is ready for download

Creating a Webhook

Open Webhook Settings

In the Customer Portal, navigate to Settings → Webhooks and click Add webhook.

Enter the endpoint URL

Provide the HTTPS URL of your endpoint. Plain HTTP endpoints are rejected — TLS is required.

Select events

Choose which event types this webhook should receive. You can register multiple webhooks, each subscribed to different events, or a single webhook that receives all events.

(Optional) Add a secret

Enter a signing secret. Veriproof will use this secret to compute an HMAC-SHA256 signature of the request body and include it in the X-Veriproof-Signature header. This allows your endpoint to verify the payload is genuine.

Save

Click Save webhook. The endpoint is immediately active.

Webhook Payload Format

All webhooks use the same envelope:

{ "id": "evt_01J7...", "type": "alert.triggered", "timestamp": "2025-06-15T14:30:00Z", "tenantId": "t_abc123", "applicationId": "app_xyz789", "data": { // Event-specific fields } }

Example: alert.triggered

{ "id": "evt_01J7abcdef", "type": "alert.triggered", "timestamp": "2025-06-15T14:30:00Z", "tenantId": "t_abc123", "applicationId": "app_xyz789", "data": { "alertRuleId": "rule_01H9...", "alertRuleName": "High refusal rate (production)", "metricName": "refusal_rate", "currentValue": 0.34, "threshold": 0.25, "severity": "warning" } }

Example: gdpr.erasure_completed

{ "id": "evt_01J7ghijkl", "type": "gdpr.erasure_completed", "timestamp": "2025-06-15T02:01:05Z", "tenantId": "t_abc123", "applicationId": null, "data": { "dataSubjectId": "ds_01H5...", "erasureRequestId": "era_01H6...", "completedAt": "2025-06-15T02:01:05Z", "certificateUrl": "https://app.veriproof.app/erasure-certificates/..." } }

Verifying Signatures

If you set a signing secret, every delivery includes the X-Veriproof-Signature header:

X-Veriproof-Signature: sha256=a3f5c9...

To verify the signature in your endpoint handler:

import hmac import hashlib def verify_signature(payload_bytes: bytes, signature_header: str, secret: str) -> bool: expected = "sha256=" + hmac.new( secret.encode("utf-8"), payload_bytes, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, signature_header)
import { createHmac, timingSafeEqual } from "crypto"; function verifySignature(payload: Buffer, header: string, secret: string): boolean { const expected = "sha256=" + createHmac("sha256", secret).update(payload).digest("hex"); return timingSafeEqual(Buffer.from(expected), Buffer.from(header)); }

Always use a constant-time comparison function (e.g. hmac.compare_digest in Python, timingSafeEqual in Node.js) when checking signatures. String equality operators (==) are vulnerable to timing attacks.

Delivery and Retry Policy

Veriproof delivers webhooks with the following guarantees:

ParameterValue
Timeout10 seconds per delivery attempt
Retry attempts3 (on non-2xx response or connection failure)
Retry backoffExponential: 5s, 25s, 125s
Failure handlingAfter 3 failures the event is marked failed

Your endpoint must return a 2xx status code within the timeout to acknowledge delivery. Returning any other status code (including 3xx redirects) causes a retry.

Idempotency

Each event has a unique id field. If your endpoint receives the same event ID more than once (due to retries), it should process it idempotently. Store the id and skip re-processing if already handled.

Delivery Logs

Every webhook delivery attempt is logged and visible in the Customer Portal:

  1. Navigate to Settings → Webhooks.
  2. Click on a webhook endpoint.
  3. Click Delivery logs.

The log shows every attempt for the last 7 days, including the HTTP response status, latency, and request/response body.

API

GET /v1/webhooks/{id}/delivery-logs

Testing a Webhook

Use the Test button in the portal to send a sample alert.triggered payload to your endpoint and verify it responds correctly, without waiting for a real event.

POST /v1/webhooks/{id}/test

Managing Webhooks via API

GET /v1/webhooks # List all webhooks POST /v1/webhooks # Create a webhook PUT /v1/webhooks/{id} # Update a webhook DELETE /v1/webhooks/{id} # Delete a webhook POST /v1/webhooks/{id}/test # Send a test delivery GET /v1/webhooks/{id}/delivery-logs # View delivery history

Notification Channels (Slack / Teams)

For human-readable alert notifications in Slack or Microsoft Teams instead of raw webhook payloads, see Notification Channels. These are configured separately under Settings → Notification Channels and use the same underlying event system with a pre-formatted message template.

Last updated on