Webhook Notifications - Archyl Docs

Receive real-time HTTP notifications when architecture changes happen in your projects

Webhook Notifications

Webhooks let you receive real-time HTTP POST notifications whenever something changes in your Archyl workspace. Create a webhook, point it at your URL, pick the events you care about, and Archyl will notify your endpoint every time those events fire.

Overview

When an event occurs — a system is created, a release is deployed, an ADR is updated — Archyl sends an HTTP POST request to every webhook subscribed to that event. Your endpoint receives a JSON payload describing what happened, who did it, and which project it belongs to.

Typical use cases:

  • Slack or Teams notifications when architecture changes are made
  • CI/CD triggers when a new release is created
  • Audit logging to an external system
  • Custom dashboards that react to architecture events
  • Automation pipelines that run when discoveries complete

Supported Events

Architecture Elements

Category Events
Systems system.created, system.updated, system.deleted
Containers container.created, container.updated, container.deleted
Components component.created, component.updated, component.deleted
Code code.created, code.updated, code.deleted
Relationships relationship.created, relationship.updated, relationship.deleted
Overlays overlay.created, overlay.updated, overlay.deleted

Project Management

Category Events
Projects project.created, project.updated, project.deleted
Releases release.created, release.updated, release.deployed
Requests request.created, request.merged, request.closed

Documentation

Category Events
ADRs adr.created, adr.updated, adr.deleted
Documentation documentation.created, documentation.updated, documentation.deleted
Flows flow.created, flow.updated, flow.deleted
API Contracts api_contract.created, api_contract.updated

Collaboration & Analysis

Category Events
Comments comment.created
Whiteboards whiteboard.created
Event Channels event_channel.created
Discovery discovery.completed
Insights insight.generated

Creating a Webhook

  1. Go to Organization Settings and select the Webhooks tab
  2. Click New Webhook
  3. Fill in the configuration:
Field Required Description
Name Yes A descriptive label (e.g., "Slack — Architecture Changes")
URL Yes The HTTPS endpoint that will receive POST requests
Secret Token No A shared secret used to sign payloads for verification
Events Yes Select which events trigger this webhook
Projects No Optionally restrict to specific projects
  1. Click Create

The webhook starts receiving events immediately.

Payload Format

Every webhook delivery sends a JSON payload with this structure:

{
  "event": "system.created",
  "timestamp": "2026-03-10T14:30:00Z",
  "data": {
    "entityType": "system",
    "entityName": "Payment Service",
    "action": "created",
    "userName": "vincent",
    "projectId": "a1b2c3d4-...",
    "projectName": "My Project"
  }
}
Field Description
event The event type string (e.g., container.updated, release.deployed)
timestamp ISO 8601 timestamp of when the event occurred
data.entityType The type of entity that changed
data.entityName The name of the affected entity
data.action The action that was performed
data.userName The user who triggered the event
data.projectId UUID of the project where the event occurred
data.projectName Human-readable project name

The Content-Type header is always application/json.

Security

Request Headers

Every webhook delivery includes these headers:

Header Example Description
Content-Type application/json Always JSON
User-Agent Archyl-Webhook/1.0 Identifies the request as coming from Archyl
X-Archyl-Event system.created The event type that triggered this delivery
X-Archyl-Signature sha256=a1b2c3... HMAC-SHA256 signature (only if a secret token is set)

HMAC-SHA256 Signature Verification

If you set a secret token when creating the webhook, Archyl signs every payload using HMAC-SHA256. The signature is sent in the X-Archyl-Signature header with the format:

sha256=<hex-encoded HMAC-SHA256 digest>

To verify a delivery:

  1. Read the raw request body (the exact bytes, before any JSON parsing)
  2. Read the X-Archyl-Signature header and strip the sha256= prefix to get the hex signature
  3. Compute an HMAC-SHA256 hash of the raw body using your secret token as the key
  4. Hex-encode the result and compare it to the signature from step 2 using a constant-time comparison
  5. Reject the request if they don't match

Go example:

func verifyArchylWebhook(r *http.Request, secret string) ([]byte, error) {
    body, err := io.ReadAll(r.Body)
    if err != nil {
        return nil, err
    }

    header := r.Header.Get("X-Archyl-Signature")
    if !strings.HasPrefix(header, "sha256=") {
        return nil, fmt.Errorf("missing or invalid signature header")
    }
    signature := strings.TrimPrefix(header, "sha256=")

    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write(body)
    expected := hex.EncodeToString(mac.Sum(nil))

    if !hmac.Equal([]byte(expected), []byte(signature)) {
        return nil, fmt.Errorf("signature mismatch")
    }
    return body, nil
}

Node.js example:

const crypto = require("crypto");

function verifyArchylWebhook(req, secret) {
  const header = req.headers["x-archyl-signature"] || "";
  if (!header.startsWith("sha256=")) {
    throw new Error("Missing or invalid signature header");
  }
  const signature = header.slice("sha256=".length);

  const body = req.rawBody; // use raw body, not parsed JSON
  const expected = crypto
    .createHmac("sha256", secret)
    .update(body)
    .digest("hex");

  if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
    throw new Error("Signature mismatch");
  }
  return JSON.parse(body);
}

Python example:

import hmac
import hashlib

def verify_archyl_webhook(body: bytes, header: str, secret: str) -> dict:
    if not header.startswith("sha256="):
        raise ValueError("Missing or invalid signature header")
    signature = header.removeprefix("sha256=")

    expected = hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(expected, signature):
        raise ValueError("Signature mismatch")
    return json.loads(body)

Always use constant-time comparison (hmac.Equal, crypto.timingSafeEqual, hmac.compare_digest) to prevent timing attacks. Always verify against the raw request body — parsing and re-serializing JSON may change the byte representation and break the signature.

Delivery History

Every webhook keeps a log of recent deliveries. To view it:

  1. Go to Organization Settings > Webhooks
  2. Click on the webhook name
  3. Open the Deliveries tab

Each delivery entry shows:

Field Description
Event The event type that triggered the delivery
Status Code The HTTP response code from your endpoint
Timestamp When the delivery was sent
Duration How long the request took
Request Payload The full JSON body that was sent
Response Body The response returned by your endpoint

Deliveries are retained for 7 days. After that, they are automatically purged.

A green badge indicates a successful delivery (2xx response). Red indicates a failure (non-2xx or timeout).

Testing

Before relying on a webhook in production, verify it works:

  1. Open the webhook detail page
  2. Click Send Test
  3. Archyl sends a test payload to your endpoint with event: "webhook.test"
  4. Check the Deliveries tab to confirm receipt and inspect the response

The test delivery uses the same signing mechanism as real events, so you can validate your signature verification logic at the same time.

Retry Policy

When a delivery fails (non-2xx response or network timeout), Archyl retries automatically:

Attempt Delay
1st retry 1 minute
2nd retry 5 minutes
3rd retry 30 minutes

After 3 failed retries, the delivery is marked as failed. You can manually re-trigger any failed delivery from the Deliveries tab by clicking Retry.

If a webhook consistently fails for 24 hours, Archyl disables it and sends a notification to the organization admins. Re-enable it from the webhook settings once the issue is resolved.

Filtering by Projects

By default, a webhook receives events from all projects in the organization. To narrow the scope:

  1. Edit the webhook
  2. Under Projects, select one or more projects
  3. Save

Only events originating from the selected projects will trigger deliveries. This is useful when different teams manage different projects and only need notifications for their own work.

You can update the project filter at any time without recreating the webhook.

Best Practices

Respond Quickly

Your endpoint should return a 2xx response within 10 seconds. If you need to do heavy processing, accept the webhook immediately and handle the work asynchronously in a background job.

Verify Signatures

Always set a secret token and verify the X-Archyl-Signature header. This ensures payloads genuinely come from Archyl and haven't been tampered with.

Use HTTPS

Always use an HTTPS endpoint. Archyl will not deliver webhooks to plain HTTP URLs.

Filter by Project

If your organization has many projects, scope webhooks to the projects you care about. This reduces noise and avoids unnecessary processing on your end.

Handle Duplicates

In rare cases (network retries, infrastructure failover), your endpoint may receive the same event more than once. Use the timestamp and event fields to detect and deduplicate.

Monitor Delivery Health

Check the Deliveries tab periodically. A pattern of failures may indicate endpoint issues, firewall rules, or expired credentials on your side.

Next Steps