Webhook Configuration

ARX can deliver event notifications to external HTTP endpoints via webhooks. This guide covers registering webhook endpoints, the event payload format, HMAC-SHA256 signature verification, and retry behavior.

Overview

Webhooks provide a push-based mechanism for receiving ARX events in real time. When a subscribed event occurs, ARX sends an HTTP POST request to your registered endpoint with a JSON payload describing the event.

Webhooks are useful for: - Triggering downstream workflows in response to ARX events - Feeding events into custom analytics or monitoring systems - Integrating with platforms not directly supported by the built-in SIEM or notification integrations

Registering a Webhook Endpoint

Webhooks are configured as SIEM integrations with integration_type set to webhook:

POST /v1/settings/siem
{
  "integration_type": "webhook",
  "name": "Custom Event Webhook",
  "config": {
    "endpoint": "https://your-service.example.com/webhooks/arx",
    "secret": "whsec_your-signing-secret-here",
    "headers": {
      "X-Custom-Header": "optional-custom-value"
    }
  },
  "enabled": true
}
Field Required Description
endpoint Yes The HTTPS URL where ARX will POST events
secret Recommended A shared secret used to compute the HMAC-SHA256 signature
headers No Additional HTTP headers included in every delivery

Use HTTPS endpoints exclusively. HTTP endpoints transmit event data and signatures in the clear, which compromises security.

Event Types

ARX delivers the following event types via webhooks:

Event Type Description
agent.deployed An agent was deployed
agent.stopped An agent was stopped
agent.error An agent encountered an error
approval.requested A new approval request was created
approval.reviewed An approval request was approved or denied
approval.expired An approval request expired without review
drift.detected Configuration drift was detected
user.created A new user was provisioned
user.deactivated A user was deactivated
ip_allowlist.entry_added An IP allowlist entry was added
ip_allowlist.entry_removed An IP allowlist entry was removed
siem.integration.created A SIEM integration was configured
encryption.config.updated Encryption settings were changed

Payload Format

Each webhook delivery is an HTTP POST with a JSON body:

{
  "id": "evt_a1b2c3d4e5f6",
  "type": "agent.deployed",
  "timestamp": "2026-04-11T14:30:00Z",
  "org_id": "a1b2c3d4-...",
  "data": {
    "agent_id": "d0e8a7b2-...",
    "agent_name": "production-scanner",
    "deployed_by": "jane@example.com",
    "environment": "production"
  }
}
Field Type Description
id string Unique event identifier (for deduplication)
type string The event type
timestamp string ISO 8601 timestamp of when the event occurred
org_id string Organization ID
data object Event-specific payload (varies by event type)

HMAC-SHA256 Signature Verification

When a secret is configured on the webhook, every delivery includes an X-ARX-Signature header:

X-ARX-Signature: sha256=a4f8c29b1d3e5f7a09b2c4d6e8f0a1b3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5

The signature is computed as the HMAC-SHA256 of the raw request body using the secret as the key.

Verification Example (Python)

import hashlib
import hmac

def verify_arx_signature(
    payload_body: bytes,
    signature_header: str,
    secret: str,
) -> bool:
    """Verify the X-ARX-Signature header from an ARX webhook delivery."""
    if not signature_header.startswith("sha256="):
        return False

    expected_signature = "sha256=" + hmac.new(
        secret.encode("utf-8"),
        payload_body,
        hashlib.sha256,
    ).hexdigest()

    return hmac.compare_digest(expected_signature, signature_header)

Verification Example (Node.js)

const crypto = require('crypto');

function verifyArxSignature(payloadBody, signatureHeader, secret) {
  const expectedSignature = 'sha256=' +
    crypto.createHmac('sha256', secret)
      .update(payloadBody, 'utf-8')
      .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature),
    Buffer.from(signatureHeader)
  );
}

Verification Example (Go)

package main

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "fmt"
    "strings"
)

func verifyARXSignature(payloadBody []byte, signatureHeader, secret string) bool {
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write(payloadBody)
    expectedSignature := "sha256=" + hex.EncodeToString(mac.Sum(nil))
    return hmac.Equal([]byte(expectedSignature), []byte(signatureHeader))
}

Important: Always use constant-time comparison (hmac.compare_digest, crypto.timingSafeEqual, hmac.Equal) to prevent timing attacks.

Signing Secret

The signing secret should be a cryptographically random string of at least 32 characters. Generate one with:

openssl rand -hex 32

Store the secret securely. If compromised, update the webhook configuration with a new secret immediately.

Retry Behavior

When a webhook delivery fails (non-2xx response or network error), ARX retries with exponential backoff:

Attempt Delay
1st retry 10 seconds
2nd retry 30 seconds
3rd retry 60 seconds
4th retry 5 minutes
5th retry 15 minutes

After all retries are exhausted, the delivery is marked as failed. The error_count on the integration record is incremented and the last_error field is updated with the failure details.

Your endpoint should return a 2xx status code within 10 seconds to indicate successful receipt. If your processing takes longer, accept the webhook and process it asynchronously.

Deduplication

Each event includes a unique id field. If your endpoint receives the same event ID more than once (due to retries or redelivery), treat the duplicate as a no-op. Implement idempotency on the consumer side.

Error Monitoring

Monitor webhook health through the SIEM integration response:

GET /v1/settings/siem

Each integration record includes:

Field Description
error_count Consecutive delivery failures (resets to 0 on success)
last_error Error message from the most recent failure
last_event_at Timestamp of the last successful delivery

Use the test endpoint to verify connectivity:

POST /v1/settings/siem/{integration_id}/test

Best Practices

  1. Always verify signatures. Reject any request where the X-ARX-Signature header is missing or invalid.
  2. Use HTTPS. Never register an HTTP endpoint for webhook delivery.
  3. Respond quickly. Return 200 OK immediately and process the event asynchronously.
  4. Implement idempotency. Use the event id to detect and skip duplicate deliveries.
  5. Monitor error counts. Set up alerting when error_count exceeds a threshold.
  6. Rotate secrets periodically. Update the webhook secret on a regular schedule.