> For the complete documentation index, see [llms.txt](https://docs.amigo.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.amigo.ai/developer-guide/classic-api/webhooks.md).

# Webhooks

Receive real-time notifications about events during client interactions with Amigo. Webhooks let your application react immediately to conversation events, post-processing completions, and other system activities. This page covers configuring destinations, delivery and retry behavior, and signature verification; the per-event payload reference lives on [Webhook Event Types](/developer-guide/classic-api/webhooks/webhook-events.md).

{% hint style="info" %}
**Classic API.** These webhook endpoints are organization-scoped under the Classic API at `api.amigo.ai`.
{% endhint %}

## Webhook Destinations

{% tabs %}
{% tab title="Configuration" %}

| Feature                  | Details                                        |
| ------------------------ | ---------------------------------------------- |
| **Maximum destinations** | 10 per organization                            |
| **Event filtering**      | Specify which event types to receive           |
| **Retry configuration**  | Customize retry attempts for failed deliveries |
| **Secret management**    | Unique secret per destination for security     |
| {% endtab %}             |                                                |

{% tab title="Capabilities" %}

* Real-time event notifications
* Selective event subscription
* Automatic retry with exponential backoff
* Signature verification for security
* Zero-downtime secret rotation
  {% endtab %}
  {% endtabs %}

### Managing webhook destinations

Use these endpoints to manage your webhook destinations.

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/webhook\_destination/" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/webhook\_destination/{webhook\_destination\_id}" method="delete" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/webhook\_destination/" method="get" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/webhook\_destination/{webhook\_destination\_id}" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% hint style="info" %}
**URL cannot be changed.** The URL of a webhook destination cannot be updated. To change the URL, create a new webhook destination and delete the old one.
{% endhint %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/webhook\_destination/{webhook\_destination\_id}/rotate-secret" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% hint style="info" %}
**Rate limit.** Secret rotation can occur at most once per hour for each webhook destination.
{% endhint %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/webhook\_destination/{webhook\_destination\_id}/delivery" method="get" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

### Delivery and Retries

{% hint style="warning" %}
**Automatic retry logic.** Failed webhook deliveries are retried automatically with exponential backoff to keep event delivery reliable.
{% endhint %}

Default schedule (`retry_attempts` = 3, meaning 3 total delivery attempts):

| Attempt | Delay | Total Time |
| ------- | ----- | ---------- |
| Initial | 0s    | Immediate  |
| Retry 1 | 5s    | 5s         |
| Retry 2 | 5s    | 10s        |

* `retry_attempts` bounds the total number of delivery attempts, including the initial one. Configure it on the destination with a value from 1 to 5 (default 3).
* Backoff between attempts is exponential, clamped between 5 and 20 seconds. At the maximum setting of 5 total attempts, the waits are 5s, 5s, 5s, and 8s (about 23s total).
* View delivery history for the past 30 days via API.

### Delivery sequence

```mermaid
%%{init: {"theme": "base", "themeVariables": {"actorBkg": "#083241", "actorTextColor": "#FFFFFF", "actorBorder": "#083241", "signalColor": "#575452", "signalTextColor": "#100F0F", "labelBoxBkgColor": "#F1EAE7", "labelBoxBorderColor": "#D7D2D0", "labelTextColor": "#100F0F", "loopTextColor": "#100F0F", "noteBkgColor": "#F1EAE7", "noteBorderColor": "#D7D2D0", "noteTextColor": "#100F0F", "activationBkgColor": "#E8E2EB", "activationBorderColor": "#083241", "altSectionBkgColor": "#F1EAE7", "altSectionColor": "#100F0F"}}}%%
sequenceDiagram
  autonumber
  participant A as Amigo Events
  participant W as Webhook Destination (Your Endpoint)

  A->>W: POST /webhook<br/>{ event, headers, signature }
  alt 2xx ack
    W-->>A: 2xx Accepted/OK
  else Non-2xx / timeout
    W-->>A: 5xx/timeout
    A->>W: Retry 1 (5s backoff)
    W-->>A: 5xx/timeout
    A->>W: Retry 2 (5s backoff)
  end

  Note over A,W: `x-amigo-idempotent-key` stays constant<br/>across retries for deduplication
```

## Security

### Webhook signatures

Every webhook request is cryptographically signed so you can verify authenticity.

{% hint style="danger" %}
**Secret storage.** Store webhook secrets securely. Never commit them to version control or expose them in client-side code.
{% endhint %}

**Signature process:**

1. Receive the secret when creating a webhook destination.
2. Amigo signs all requests with HMAC-SHA256.
3. Validate the signature on receipt to verify authenticity.

### Request headers

| Header                      | Description                                                    |
| --------------------------- | -------------------------------------------------------------- |
| `x-amigo-idempotent-key`    | Unique identifier persisting through retries for deduplication |
| `x-amigo-request-timestamp` | UNIX timestamp (microseconds) of the delivery attempt          |
| `x-amigo-request-signature` | HMAC-SHA256 signature of `v1:{timestamp}:{body}`               |

### Signature verification

{% tabs %}
{% tab title="Node.js Example" %}

```javascript
const crypto = require('crypto');

function verifyWebhookSignature(body, timestamp, signature, secret) {
  // 1. Concatenate version, timestamp, and body
  const payload = `v1:${timestamp}:${body}`;
  
  // 2. Compute HMAC-SHA256
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  // 3. Compare signatures
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}
```

{% endtab %}

{% tab title="Python Example" %}

```python
import hmac
import hashlib

def verify_webhook_signature(body, timestamp, signature, secret):
    # 1. Concatenate version, timestamp, and body
    payload = f"v1:{timestamp}:{body}"
    
    # 2. Compute HMAC-SHA256
    expected_signature = hmac.new(
        secret.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()
    
    # 3. Compare signatures
    return hmac.compare_digest(signature, expected_signature)
```

{% endtab %}
{% endtabs %}

### Secret rotation

{% hint style="success" %}
**Zero-downtime rotation.** A dual-signing period lets you rotate secrets smoothly without missing events.
{% endhint %}

**Rotation process:**

| Step | Action                     | Duration                      |
| ---- | -------------------------- | ----------------------------- |
| 1    | Call the rotation endpoint | Immediate                     |
| 2    | Receive the new secret     | Immediate                     |
| 3    | Dual-signing begins        | 30 minutes                    |
| 4    | Update verification logic  | During dual-signing           |
| 5    | Old secret expires         | After `dual_signing_stops_at` |

**During the dual-signing period:**

* Amigo sends two signatures per request.
* Accept either the old or the new signature.
* No webhook deliveries are lost.

#### Rotation states

```mermaid
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#D4E2E7", "primaryTextColor": "#100F0F", "primaryBorderColor": "#083241", "lineColor": "#575452", "textColor": "#100F0F"}}}%%
stateDiagram-v2
  direction LR
  OldActive: Old secret active
  DualSigning: Dual-signing window
  NewActive: New secret active

  [*] --> OldActive
  OldActive --> DualSigning: rotate secret
  DualSigning --> NewActive: dual_signing_stops_at
  NewActive --> [*]

  note right of DualSigning
    Both old and new signatures<br/>are accepted during this window
  end note
```

## Webhook Event Types

Destinations can subscribe to API key expiration warnings, conversation post-processing completions, and agent framework resource updates. The full payload reference for each event lives on its own page.

{% content-ref url="/pages/UMICZ6oT4PVmKgeaJEow" %}
[Webhook Event Types](/developer-guide/classic-api/webhooks/webhook-events.md)
{% endcontent-ref %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.amigo.ai/developer-guide/classic-api/webhooks.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
