> ## Documentation Index
> Fetch the complete documentation index at: https://moonshotfactory.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Receive real-time event notifications from AgentVista at your own HTTPS endpoint with signed payloads and automatic retries.

AgentVista webhooks push event notifications to an HTTPS endpoint you control. When an event occurs — such as an alert firing or an agent run completing — AgentVista sends a signed HTTP POST to your registered endpoint so your systems can react in real time.

## How it works

When an event matches one of the event types you subscribed to, AgentVista:

1. Builds a JSON payload and signs it using HMAC-SHA256.
2. Sends a `POST` request to your endpoint with the signature in the `X-Webhook-Signature` header.
3. Retries automatically on failure with exponential backoff (up to 7 attempts).
4. Disables the endpoint after repeated terminal failures and notifies your org admins by email.

## Register an endpoint

<Steps>
  <Step title="Open webhook settings">
    In the AgentVista dashboard, go to **Settings → Webhooks** and click **Add endpoint**.
  </Step>

  <Step title="Provide endpoint details">
    Fill in the following fields:

    | Field         | Description                                                                             |
    | ------------- | --------------------------------------------------------------------------------------- |
    | `url`         | The HTTPS URL AgentVista will POST to.                                                  |
    | `name`        | An optional human-readable label for the endpoint.                                      |
    | `event_types` | One or more event type strings to subscribe to (see [Event types](#event-types) below). |

    <Note>
      Webhook URLs must start with `https://`. HTTP endpoints are rejected at registration time.
    </Note>
  </Step>

  <Step title="Save your signing key immediately">
    After you click **Save**, AgentVista displays the endpoint's `signing_key` exactly once. Copy it and store it securely (for example, as an environment variable in your service).

    <Warning>
      The signing key is shown only at creation time and cannot be retrieved again. If you lose it, rotate the secret from the endpoint settings page to generate a new one. The old key is immediately invalidated when you rotate.
    </Warning>
  </Step>
</Steps>

## Event types

Subscribe to one or more of the following event type strings:

| Event type            | Triggered when                                         |
| --------------------- | ------------------------------------------------------ |
| `alert.fired`         | An alert rule threshold is crossed and an alert fires. |
| `agent_run.completed` | An agent run finishes (success or failure).            |

You must provide at least one event type when registering an endpoint.

## Webhook payload

Each delivery is a JSON object. The request body is a snapshot stored at delivery time and replayed on retries.

AgentVista sends the following headers with every delivery:

| Header                | Description                                         |
| --------------------- | --------------------------------------------------- |
| `Content-Type`        | `application/json`                                  |
| `X-Webhook-Id`        | The unique delivery ID (UUID).                      |
| `X-Webhook-Timestamp` | Unix timestamp (seconds) when the request was sent. |
| `X-Webhook-Signature` | HMAC-SHA256 signature of the payload (see below).   |

## Verify webhook signatures

Every delivery is signed so you can confirm it came from AgentVista and was not tampered with in transit. The signature format mirrors the Stripe/GitHub webhook convention.

**Signature construction:**

```
HMAC-SHA256(signing_key, "{timestamp}.{raw_body_bytes}")
```

The header value is prefixed with `sha256=`.

**Python verification example:**

```python theme={null}
import hashlib
import hmac
from flask import Flask, request, abort

app = Flask(__name__)

SIGNING_KEY = "your_signing_key_here"  # from env variable


def verify_signature(signing_key: str, timestamp: str, body: bytes, signature: str) -> bool:
    """Return True if the request signature is valid."""
    msg = f"{timestamp}.".encode() + body
    expected = "sha256=" + hmac.new(
        signing_key.encode(), msg, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)


@app.route("/webhooks/agentvista", methods=["POST"])
def handle_webhook():
    timestamp = request.headers.get("X-Webhook-Timestamp", "")
    signature = request.headers.get("X-Webhook-Signature", "")
    body = request.get_data()  # raw bytes — do not parse before verifying

    if not verify_signature(SIGNING_KEY, timestamp, body, signature):
        abort(403)

    payload = request.get_json()
    event_type = payload.get("event_type")

    if event_type == "alert.fired":
        # handle alert
        pass
    elif event_type == "agent_run.completed":
        # handle run completion
        pass

    return "", 200
```

<Tip>
  Use `hmac.compare_digest()` for the final comparison — it performs a constant-time comparison that prevents timing attacks.
</Tip>

## Delivery and retry behavior

Each event dispatch creates a `WebhookDelivery` record that tracks the overall status and every HTTP attempt made against your endpoint.

### Delivery status

| Status     | Meaning                                                                             |
| ---------- | ----------------------------------------------------------------------------------- |
| `pending`  | The delivery has been queued but not yet attempted.                                 |
| `retrying` | A previous attempt failed (non-2xx or network error); another attempt is scheduled. |
| `success`  | Your endpoint returned a 2xx response.                                              |
| `failed`   | All retry attempts were exhausted with no 2xx response.                             |

### Retry schedule

AgentVista retries failed deliveries up to **7 times** using exponential backoff with a maximum interval of 600 seconds (10 minutes). Each attempt is logged with its HTTP status code, response body (truncated at 10 KB), response headers, duration, and any network error message.

Your endpoint must return a `2xx` status code for the delivery to be considered successful. Any other status code or network error triggers a retry.

### Circuit breaker

AgentVista tracks `consecutive_failures` on each endpoint. After a configurable number of consecutive terminal failures (deliveries that exhaust all retries), the endpoint is automatically disabled (`is_active` set to `false`) and your org admins are notified by email.

To re-enable a disabled endpoint, go to **Settings → Webhooks**, select the endpoint, and toggle it back on. Re-enabling resets the consecutive failure counter to zero.

## Manage endpoints

### View delivery history

Navigate to **Settings → Webhooks → \[your endpoint] → Deliveries** to see a paginated list of recent deliveries with status and attempt count.

Click any delivery to view the full detail, including the request body that was sent and the response from each HTTP attempt.

### Retry a delivery manually

From the delivery detail view, click **Retry** to immediately re-enqueue the delivery. You can do this for any delivery regardless of its current status.

### Rotate the signing key

Go to **Settings → Webhooks → \[your endpoint] → Rotate secret**. A new signing key is generated and displayed once. The old key is invalidated immediately — update your service's environment variable before rotating if you have active traffic.

<Warning>
  Rotating the secret immediately invalidates the old key. Any in-flight deliveries that were signed with the old key will fail HMAC verification on your endpoint until you deploy the new key.
</Warning>
