Webhooks & Events
Receive real-time HTTP notifications for governance decisions, agent actions, compliance changes, and billing updates.
Why Webhooks?
Push-based event delivery so your systems stay in sync without polling.
Real-Time Delivery
Events are dispatched within seconds of occurrence. HTTPS POST to your endpoint with JSON payloads, signed with HMAC-SHA256.
Cryptographically Signed
Every payload includes a timestamp and HMAC-SHA256 signature so you can verify authenticity and reject tampered requests.
Automatic Retries
Failed deliveries are retried with Fibonacci-based backoff. Delivery logs and health monitoring keep you informed.
Event Filtering
Subscribe to specific event types per endpoint. Receive only the events your system needs — no noise.
Tenant-Scoped
Webhooks are isolated per tenant. Each endpoint receives events only for its own organization, enforced at the platform level.
Developer Tools
Test endpoints, inspect delivery logs, replay events, and debug locally with CLI tools and the webhook dashboard.
Event Categories
35+ event types organized by domain. Subscribe to exactly what you need.
Governance Events
Fired when actions flow through the governance engine — requests, approvals, rejections, and policy enforcement.
| Event Type | Description |
|---|---|
action.requested | An action has been submitted for governance evaluation |
action.approved | An action was approved (automatically or by a human) |
action.rejected | An action was rejected by a reviewer or governance policy |
action.auto_executed | An AUTO-tier action was executed without human review |
policy.updated | A governance policy was created or modified |
policy.violated | An action triggered a policy violation |
Agent Events
Lifecycle events for AI agents — creation, execution, failures, and completions.
| Event Type | Description |
|---|---|
agent.created | A new AI agent was registered |
agent.executed | An agent began executing a task |
agent.failed | An agent execution encountered an error |
agent.completed | An agent finished its task successfully |
ara.action.triggered | Ara triggered an autonomous action |
Evidence Events
Emitted when audit evidence is created, verified, or shared across the evidence chain.
| Event Type | Description |
|---|---|
evidence.emitted | A new evidence artifact was recorded |
evidence.chain.verified | The evidence chain integrity was verified |
artifact.created | A governance artifact (report, decision log) was created |
artifact.shared | An artifact was shared with external stakeholders |
Compliance Events
Compliance framework evaluations, violations, and regulatory change notifications.
| Event Type | Description |
|---|---|
compliance.check.completed | A compliance check finished (pass or fail) |
compliance.framework.updated | A compliance framework configuration changed |
compliance.violation.detected | A compliance violation was identified |
User Events
User lifecycle — account creation, profile changes, provisioning, and authentication.
| Event Type | Description |
|---|---|
user.created | A new user account was created |
user.updated | A user profile or role was modified |
user.deprovisioned | A user was deactivated or removed via SCIM |
user.login | A user authenticated successfully |
user.mfa.enabled | Multi-factor authentication was enabled for a user |
Integration Events
Connection lifecycle for third-party integrations — OAuth flows, syncs, and disconnections.
| Event Type | Description |
|---|---|
integration.connected | A new integration was connected via OAuth |
integration.disconnected | An integration was disconnected or revoked |
integration.sync.completed | A data sync from an integration finished |
Billing Events
Subscription changes, invoice payments, and usage threshold alerts.
| Event Type | Description |
|---|---|
subscription.created | A new subscription was created |
subscription.updated | A subscription plan or quantity changed |
subscription.canceled | A subscription was canceled |
invoice.paid | An invoice payment was processed successfully |
usage.threshold.reached | API usage reached a configured threshold |
Webhook Configuration
Register endpoints via the dashboard or the REST API.
Via Dashboard
- Navigate to Settings → Webhooks in the ARQERA app.
- Click Add Endpoint and enter your HTTPS URL.
- Select the event types you want to receive, or choose All Events.
- Copy the generated signing secret and store it securely in your application.
- Click Send Test Event to verify your endpoint responds with a 2xx status.
Via REST API
Create a webhook endpoint programmatically with a POST request:
curl -X POST https://app.arqera.io/api/webhooks \
-H "Authorization: Bearer ak_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Production Governance Alerts",
"url": "https://your-app.com/webhooks/arqera",
"events": [
"action.approved",
"action.rejected",
"policy.violated",
"compliance.violation.detected"
],
"secret": "whsec_your_signing_secret"
}'Response:
{
"id": "wh_a1b2c3d4e5f6",
"name": "Production Governance Alerts",
"url": "https://your-app.com/webhooks/arqera",
"events": [
"action.approved",
"action.rejected",
"policy.violated",
"compliance.violation.detected"
],
"status": "active",
"created_at": "2026-02-19T14:00:00.000Z"
}Payload Format
Every webhook delivers a consistent JSON structure regardless of event type.
{
"id": "evt_01HX7V9K3M2N4P5Q6R8S0T1U2V",
"type": "action.approved",
"timestamp": "2026-02-19T14:23:07.000Z",
"version": "2026-02-01",
"data": {
"action_id": "act_9f8e7d6c5b4a3210",
"action_type": "data.export",
"approved_by": "user_a1b2c3d4e5f6",
"approval_method": "manual",
"agent_id": "agent_x7y8z9",
"risk_tier": "HARD",
"evidence_artifact_id": "art_f0e1d2c3b4a5"
},
"tenant_id": "ten_4k7m2n8p1q3r",
"signature": "t=1740000187,v1=5d41402abc4b2a76b9719d911017c592..."
}| Field | Type | Description |
|---|---|---|
id | string | Unique event identifier. Use for idempotency. |
type | string | Dot-notation event type (e.g. action.approved). |
timestamp | string | ISO 8601 timestamp of when the event occurred. |
version | string | API version that generated this event. |
data | object | Event-specific payload. Schema varies by event type. |
tenant_id | string | Tenant the event belongs to. |
signature | string | HMAC-SHA256 signature for verification. |
The data object varies by event type. Refer to the API reference for the full schema of each event payload.
Signature Verification
Verify that webhook payloads originated from ARQERA using HMAC-SHA256.
How Signatures Work
- ARQERA serializes the payload as canonical JSON (sorted keys, no whitespace).
- A signed string is constructed:
{timestamp}.{canonical_json} - The signed string is hashed with HMAC-SHA256 using your webhook secret.
- The result is sent in the
X-Webhook-Signatureheader ast=timestamp,v1=hash. - Your server reconstructs the same hash and compares using constant-time comparison.
import hmac
import hashlib
import json
def verify_webhook(payload_body: bytes, signature_header: str, secret: str) -> bool:
"""Verify ARQERA webhook signature.
Args:
payload_body: Raw request body bytes.
signature_header: Value of X-Webhook-Signature header.
secret: Your webhook signing secret.
Returns:
True if the signature is valid.
"""
# Parse the signature header: "t=<timestamp>,v1=<hash>"
parts = dict(p.split("=", 1) for p in signature_header.split(","))
timestamp = parts["t"]
received_sig = parts["v1"]
# Reconstruct the signed payload
payload_str = json.dumps(
json.loads(payload_body),
sort_keys=True,
separators=(",", ":"),
)
signed_payload = f"{timestamp}.{payload_str}"
# Compute expected signature
expected_sig = hmac.new(
secret.encode("utf-8"),
signed_payload.encode("utf-8"),
hashlib.sha256,
).hexdigest()
# Constant-time comparison
return hmac.compare_digest(expected_sig, received_sig)import crypto from "crypto";
function verifyWebhook(
payloadBody: string,
signatureHeader: string,
secret: string
): boolean {
// Parse the signature header: "t=<timestamp>,v1=<hash>"
const parts = Object.fromEntries(
signatureHeader.split(",").map((p) => {
const [k, ...v] = p.split("=");
return [k, v.join("=")];
})
);
const timestamp = parts["t"];
const receivedSig = parts["v1"];
// Reconstruct the signed payload
const parsed = JSON.parse(payloadBody);
const canonical = JSON.stringify(parsed, Object.keys(parsed).sort());
// Remove spaces after separators to match Python's separators=(",",":")
const compact = canonical.replace(/: /g, ":").replace(/, /g, ",");
const signedPayload = `${timestamp}.${compact}`;
// Compute expected signature
const expectedSig = crypto
.createHmac("sha256", secret)
.update(signedPayload)
.digest("hex");
// Constant-time comparison
return crypto.timingSafeEqual(
Buffer.from(expectedSig),
Buffer.from(receivedSig)
);
}# Python SDK
from arqera import Arqera
client = Arqera(api_key="ak_...")
is_valid = client.webhooks.verify(
payload=request.body,
signature=request.headers["X-Webhook-Signature"],
secret="whsec_...",
)
# TypeScript SDK
import { Arqera } from "@arqera/sdk";
const client = new Arqera({ apiKey: "ak_..." });
const isValid = client.webhooks.verify(
req.body,
req.headers["x-webhook-signature"],
"whsec_..."
);Retry Policy
Failed deliveries are retried automatically with Fibonacci-based backoff.
| Attempt | Delay | Cumulative |
|---|---|---|
| 1 | 60 s | 1 min |
| 2 | 60 s | 2 min |
| 3 | 120 s | 4 min |
| 4 | 180 s | 7 min |
| 5 | 300 s | 12 min |
| 6 | 480 s | 20 min |
| 7 | 780 s | 33 min |
Fibonacci Backoff
Retry delays follow the Fibonacci sequence multiplied by a 60-second base. This provides natural, logarithmic growth that is gentler than exponential backoff.
Exhaustion
After all retry attempts are exhausted, the delivery is marked as failed. The event is preserved in the delivery log and can be manually replayed via the API or CLI.
Health Monitoring
Endpoints that repeatedly fail are moved to an error state. The webhook dashboard shows delivery success rates, failure counts, and last-delivered timestamps.
Manual Re-delivery
Replay any event via the API (POST /api/webhooks/replay) or the CLI. Useful for recovering from outages.
Testing Webhooks
Tools for developing and debugging your webhook integration.
CLI Tools
Send test events, list deliveries, and replay failed events from the command line.
# Send a test event to your endpoint arqera webhooks test \ --endpoint wh_a1b2c3d4e5f6 \ --event action.approved # List recent deliveries arqera webhooks deliveries \ --endpoint wh_a1b2c3d4e5f6 \ --limit 20 # Replay a specific event arqera webhooks replay \ --delivery dlv_x7y8z9w0 \ --endpoint wh_a1b2c3d4e5f6
Local Development
Use ngrok or a similar tunnel to expose your local server and receive webhooks during development.
# Use ngrok to expose your local server
ngrok http 3000
# Then register the ngrok URL as your webhook endpoint
curl -X POST https://app.arqera.io/api/webhooks \
-H "Authorization: Bearer ak_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Local Development",
"url": "https://abc123.ngrok.io/webhooks/arqera",
"events": ["*"]
}'Webhook Dashboard
The webhook dashboard in Settings → Webhooks provides:
Best Practices
Production guidance for reliable webhook consumption.
Always Verify Signatures
Check the HMAC-SHA256 signature on every request before processing. Reject unsigned or tampered payloads immediately.
Implement Idempotency
Use the event id field to deduplicate. Store processed event IDs and skip duplicates. Webhooks may be delivered more than once.
Respond Within 5 Seconds
Return a 2xx status within 5 seconds. If processing takes longer, accept the event, queue it internally, and process asynchronously.
Handle Retries Gracefully
ARQERA retries failed deliveries with increasing delays. Ensure your endpoint is idempotent so retried events do not cause duplicate side effects.
Filter by Event Type
Subscribe only to the events you need. Fewer events mean less noise, lower latency, and simpler processing logic.
Use IP Allowlisting
Restrict your webhook endpoint to ARQERA's IP ranges for defence in depth. Fetch the current list from GET /api/webhooks/ips.
Monitor Delivery Health
Check the webhook dashboard for delivery success rates. Set up alerts for elevated failure rates or endpoints in error state.
Test Before Going Live
Use the test endpoint or CLI to send synthetic events. Verify your handler processes them correctly before subscribing to production events.
Event Type Quick Reference
All supported event types at a glance.
| Event Type | Category | Description |
|---|---|---|
action.requested | Governance Events | An action has been submitted for governance evaluation |
action.approved | Governance Events | An action was approved (automatically or by a human) |
action.rejected | Governance Events | An action was rejected by a reviewer or governance policy |
action.auto_executed | Governance Events | An AUTO-tier action was executed without human review |
policy.updated | Governance Events | A governance policy was created or modified |
policy.violated | Governance Events | An action triggered a policy violation |
agent.created | Agent Events | A new AI agent was registered |
agent.executed | Agent Events | An agent began executing a task |
agent.failed | Agent Events | An agent execution encountered an error |
agent.completed | Agent Events | An agent finished its task successfully |
ara.action.triggered | Agent Events | Ara triggered an autonomous action |
evidence.emitted | Evidence Events | A new evidence artifact was recorded |
evidence.chain.verified | Evidence Events | The evidence chain integrity was verified |
artifact.created | Evidence Events | A governance artifact (report, decision log) was created |
artifact.shared | Evidence Events | An artifact was shared with external stakeholders |
compliance.check.completed | Compliance Events | A compliance check finished (pass or fail) |
compliance.framework.updated | Compliance Events | A compliance framework configuration changed |
compliance.violation.detected | Compliance Events | A compliance violation was identified |
user.created | User Events | A new user account was created |
user.updated | User Events | A user profile or role was modified |
user.deprovisioned | User Events | A user was deactivated or removed via SCIM |
user.login | User Events | A user authenticated successfully |
user.mfa.enabled | User Events | Multi-factor authentication was enabled for a user |
integration.connected | Integration Events | A new integration was connected via OAuth |
integration.disconnected | Integration Events | An integration was disconnected or revoked |
integration.sync.completed | Integration Events | A data sync from an integration finished |
subscription.created | Billing Events | A new subscription was created |
subscription.updated | Billing Events | A subscription plan or quantity changed |
subscription.canceled | Billing Events | A subscription was canceled |
invoice.paid | Billing Events | An invoice payment was processed successfully |
usage.threshold.reached | Billing Events | API usage reached a configured threshold |
Ready to receive real-time events?
Create your free account and configure your first webhook in minutes.