Settings — Webhooks
The Settings ▸ Webhooks page is the admin surface for registering real-time HTTP callbacks. Each webhook is an HTTPS URL plus a list of typed events; when a matching event fires in your tenant, the platform POSTs a signed JSON payload to your endpoint.
This is the primary integration mechanism for hooking Athenty into your own systems — Slack notifications, internal CRMs, regulator reporting pipelines, ETL jobs.

Anatomy of the page
Section titled “Anatomy of the page”1. Page header
Section titled “1. Page header”Standard PageHeader with the title Webhooks and a one-line description. The Add Webhook button sits to the right.
2. Webhooks list
Section titled “2. Webhooks list”Each row carries:
- The endpoint URL (with a copy-button)
- A badge group of subscribed events
- Active toggle
- Last delivery timestamp + status pill
- Row actions (Test, Edit, Rotate secret, Delete)
Clicking the chevron expands the row to show the per-webhook delivery history with status codes and response bodies.
3. Add / edit slide-out
Section titled “3. Add / edit slide-out”The slide-out captures URL, description, and an event multi-select. Save creates the webhook server-side, generates a signing secret (shown once), and dispatches a one-time test ping.
Event taxonomy
Section titled “Event taxonomy”The same typed event names used by Settings ▸ Audit Log are available as subscription keys here. Common subscriptions:
| Event | Triggered by |
|---|---|
request.created | New verification opened |
request.approved / request.rejected | Reviewer decision |
request.expired | Auto-expiry |
envelope.completed | Every recipient signed |
envelope.declined | A signer refused |
matter.created / matter.updated | Matter lifecycle |
client.created | New client added |
user.invited / user.deactivated | Team change |
The full list lives in packages/api/src/webhooks/events.ts.
Payload format
Section titled “Payload format”Every payload is a JSON document with this shape:
{ "id": "01jdc233-4dae-7776-...", "type": "request.approved", "created_at": "2026-05-07T20:15:00Z", "tenant_id": "01jdc234-...", "data": { /* event-specific payload */ }, "metadata": { "test": false, "delivery_attempt": 1 }}metadata.test is true for synthetic test deliveries; false
otherwise. delivery_attempt is 1-indexed and increments on each retry.
Signing
Section titled “Signing”Every POST carries an HMAC-SHA-256 signature in X-Athenty-Signature,
computed over the raw request body using your registered secret:
import crypto from 'crypto'const sig = req.headers['x-athenty-signature']const expected = crypto .createHmac('sha256', SECRET) .update(req.rawBody) .digest('hex')if (sig !== expected) throw new Error('invalid signature')Always verify against the raw body; many frameworks parse JSON before your handler sees it, which mutates whitespace and breaks the signature.
Delivery + retry
Section titled “Delivery + retry”- Initial POST: 5-second timeout
- Failure retries with exponential backoff: 1m, 5m, 15m, 1h, 6h, 24h
- 6 attempts total; after that the webhook stays active but flags as failed on the row
- All retries are visible in the per-webhook delivery history
A delivery is considered successful when the endpoint returns any 2xx status code. 3xx, 4xx, and 5xx all count as failure.
Test delivery
Section titled “Test delivery”The Test action POSTs a synthetic payload with metadata.test = true.
The synthetic event has the schema of a real event but doesn’t reflect
any actual record state — useful for verifying your handler in
production without polluting downstream systems.
Signing secret rotation
Section titled “Signing secret rotation”Click Rotate signing secret on the row’s More menu. The platform:
- Generates a new secret (shown once)
- Sends both old and new signatures on the next 24 hours of deliveries (graceful overlap)
- After 24 hours, only the new secret is used
This lets you update your verifier without dropping events.
Permissions and scope
Section titled “Permissions and scope”| Role | View | Manage |
|---|---|---|
| Owner / Admin | ✓ | ✓ |
| Member | ✗ | ✗ |
| Viewer | ✗ | ✗ |
Webhooks are tenant-scoped — your endpoint only receives events from your own tenant.
Audit logging
Section titled “Audit logging”| Action | Event |
|---|---|
| Create | webhook.created |
| Edit | webhook.updated |
| Rotate secret | webhook.secret_rotated |
| Delete | webhook.deleted |
| Disable / enable | webhook.toggled |
All events surface in Settings ▸ Audit Log.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Most likely cause | Fix |
|---|---|---|
| Test delivery fails | Endpoint not reachable | Verify DNS + TLS; check egress IP allowlist |
| Signature mismatch | Verifying parsed JSON, not raw body | Use the raw body for HMAC |
| Missing some events | Not subscribed | Edit and add the event |
| Failed deliveries pile up | Endpoint 5xx persistently | Fix endpoint; pause the webhook to stop retries |
| Lost signing secret | One-time-shown only | Rotate to get a new secret + update verifier |
Related pages
Section titled “Related pages”- Settings ▸ Audit Log — same event taxonomy, server-side persistence
- Settings ▸ API Keys — credentials for the inbound REST API
- Settings ▸ Integrations — first-party connectors (Slack, Teams, Zapier)