# Handle webhook (/en/ai/build/handle-runtime-events/webhooks)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

A webhook is a user-defined HTTPS callback that lets your backend receive notifications when Conversational AI events occur. Agora sends POST requests to your webhook endpoint so your system can react to agent lifecycle changes, history delivery, errors, and performance metrics in real time.

For the combined entry point that compares client toolkit and webhook delivery, see [Get runtime events](get-runtime-events).

Use this page when you need durable backend records for monitoring, alerting, or analytics. If you need live UI state inside the app, use [Client-side events](event-notifications).

## Understand the tech [#understand-the-tech]

Using Agora Console, you subscribe to specific events for your project and configure the URL of the webhook endpoint that receives them. Agora sends event notifications to that endpoint whenever the subscribed events occur. Your server verifies the request signature, processes the JSON payload, and returns `200 OK` to confirm receipt.

## Common uses [#common-uses]

Webhooks are typically used to:

* Track when an agent joins or leaves a channel
* Receive short-term memory history after an agent session ends
* Capture module-level errors for monitoring and debugging
* Collect performance metrics such as LLM and TTS latency

## Prerequisites [#prerequisites]

Before you begin, make sure you have:

* An Agora account
* An active Agora project with Conversational AI enabled
* A public HTTPS endpoint that can receive webhook callbacks
* Server-side access to store and validate the secret used for signature verification

## Enable notifications [#enable-notifications]

To enable Agora notifications for Conversational AI:

1. Sign in to the [Agora Console](https://console.agora.io).
2. Open **Projects** and locate the target project.
3. Open the **Notifications** configuration area for the project.
4. Select the Conversational AI event types you want to subscribe to.
5. Enter the HTTPS callback URL of your receiving server.
6. Save the generated **Secret**. You need it for signature verification.
7. Run the console-side health check and confirm your server responds with `200 OK`.

### Recommended webhook endpoint settings [#recommended-webhook-endpoint-settings]

* Use HTTPS only.
* Enable HTTP keep-alive if possible.
* Make sure your server responds within 10 seconds.

## Request header [#request-header]

The header of notification callbacks contains the following fields:

| Field name           | Value                                                 |
| -------------------- | ----------------------------------------------------- |
| `Content-Type`       | `application/json`                                    |
| `Agora-Signature`    | Signature generated with the secret using HMAC/SHA1   |
| `Agora-Signature-V2` | Signature generated with the secret using HMAC/SHA256 |

## Request body [#request-body]

The request body of notification callbacks contains the following fields:

| Field name  | Type        | Description                                                  |
| ----------- | ----------- | ------------------------------------------------------------ |
| `noticeId`  | String      | Notification ID that uniquely identifies this callback       |
| `productId` | Number      | Product ID of the notification source                        |
| `eventType` | Number      | Type of event being notified                                 |
| `notifyMs`  | Number      | Unix timestamp in milliseconds when Agora sends the callback |
| `payload`   | JSON object | Event-specific data                                          |

The following example shows a sample request body:

```json
{
  "noticeId": "2000001428:4330:107",
  "productId": 1,
  "eventType": 101,
  "notifyMs": 1611566412672,
  "payload": {}
}
```

## Conversational AI event types [#conversational-ai-event-types]

Agora can notify your server of the following Conversational AI events:

| eventType | Description                   |
| --------- | ----------------------------- |
| `101`     | Agent joined a channel        |
| `102`     | Agent left a channel          |
| `103`     | Dialogue history notification |
| `110`     | Agent error                   |
| `111`     | Agent performance metrics     |
| `201`     | Incoming call status change   |
| `202`     | Outgoing call status change   |

For payload details, see [Notification event types](../../reference/event-types).

## Signature verification [#signature-verification]

To communicate securely between Agora and your webhook, Agora uses signatures for identity verification:

1. When you configure notifications in Agora Console, Agora generates a secret for your project.
2. When sending a notification, Agora generates `Agora-Signature` and `Agora-Signature-V2` values using HMAC/SHA1 and HMAC/SHA256.
3. When your server receives the callback, verify one of those signatures against the raw request body.

The following Go example calculates a signature and compares it with the received value:

```go
import (
    "crypto/hmac"
    "crypto/sha1"
    "encoding/hex"
    "net/http"
)

const secret = "<replace-with-your-secret>"

func calcSignatureV1(secret, payload string) string {
    mac := hmac.New(sha1.New, []byte(secret))
    mac.Write([]byte(payload))
    return hex.EncodeToString(mac.Sum(nil))
}

func verify(requestBody, signature string) bool {
    calculatedSignature := calcSignatureV1(secret, requestBody)
    return calculatedSignature == signature
}
```

After reading the request body in your handler, verify the signature:

```go
if !verify(string(body), agoraSignature) {
    http.Error(w, "Invalid signature", http.StatusUnauthorized)
    return
}
```

## Best practices [#best-practices]

* Keep the webhook secret on the server side only.
* Store raw payloads for troubleshooting when useful.
* Design webhook processing to be idempotent, because retries can happen.
* Return `200 OK` quickly and move heavier processing to async workers if needed.

## Related resources [#related-resources]

* [Monitor agent status, errors, and performance](monitor-agent-runtime)
* [Debug agent failures with runtime events](debug-agent-failures)
* [Retrieve conversation history after a session ends](retrieve-session-history)
* [Client-side events](event-notifications)
* [Notification event types](../../reference/event-types)
* [Start a conversational AI agent](/en/api-reference/api-ref/conversational-ai/join)
* [Retrieve agent history](/en/api-reference/api-ref/conversational-ai/history)
