Handle webhook

Updated

Use webhooks to collect agent lifecycle, error, history, and metrics events on your backend.

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.

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.

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

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

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

To enable Agora notifications for Conversational AI:

  1. Sign in to the Agora Console.
  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.
  • Use HTTPS only.
  • Enable HTTP keep-alive if possible.
  • Make sure your server responds within 10 seconds.

Request header

The header of notification callbacks contains the following fields:

Field nameValue
Content-Typeapplication/json
Agora-SignatureSignature generated with the secret using HMAC/SHA1
Agora-Signature-V2Signature generated with the secret using HMAC/SHA256

Request body

The request body of notification callbacks contains the following fields:

Field nameTypeDescription
noticeIdStringNotification ID that uniquely identifies this callback
productIdNumberProduct ID of the notification source
eventTypeNumberType of event being notified
notifyMsNumberUnix timestamp in milliseconds when Agora sends the callback
payloadJSON objectEvent-specific data

The following example shows a sample request body:

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

Conversational AI event types

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

eventTypeDescription
101Agent joined a channel
102Agent left a channel
103Dialogue history notification
110Agent error
111Agent performance metrics
201Incoming call status change
202Outgoing call status change

For payload details, see Notification event types.

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:

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:

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

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.