Skip to main content
Tavus sends JSON payloads to the callback_url you configure on each resource. On your server, read the body and branch on event_type (and message_type where noted). This page covers five callback areas: conversation events (below), guardrails, objectives, face training, and video generation - payload shapes differ, and most event-specific fields live under properties.

Conversation Callbacks

If a callback_url is provided when you call POST https://tavusapi.com/v2/conversations (Create Conversation), callbacks will provide insight into the conversation’s state. These can be system-related (e.g. PAL joins and room shutdowns) or application-related (e.g. final transcription parsing and recording-ready webhooks). Additional webhooks coming soon.

Structure

All Conversation callbacks share the following basic structure. Differences will occur in the properties object.

Types

Our callbacks are split into two main categories:

System Callbacks

These callbacks are to provide insight into system-related events in a conversation. They are:
  • system.pal_joined: Fired when the PAL is ready for a conversation. Use this in new integrations.
  • system.replica_joined: Legacy duplicate of system.pal_joined with an identical payload. Still sent so existing integrations keep working; prefer system.pal_joined for new code.
  • system.shutdown: This is fired when the room shuts down, for any of the following reasons:
    • max_call_duration reached
    • participant_left_timeout reached
    • participant_absent_timeout reached
    • bot_could_not_join_meeting_it_was_probably_ended
    • daily_room_has_been_deleted
    • exception_encountered_during_conversation_startup
    • end_conversation_endpoint_hit
    • internal error occurred at step x
Examples:

Application Callbacks

These callbacks are to inform developers about logical events that take place. They are:
  • application.transcription_ready: This is fired after ending a conversation, where the chat history is saved and returned. Each transcript entry includes role, content, timestamp (Unix epoch float, seconds, when the turn began - same field name as live interaction events), seconds_from_start, duration (seconds, float - same field name as the duration on conversation.stopped_speaking), and inference_id (on assistant turns). The same payload is also available on the verbose GET conversation response under events (look for the event with event_type: "application.transcription_ready").
  • application.recording_ready: This is fired once your recording is durably written to your storage destination. Includes storage_provider (s3 / gcs / azure_blob) and a fully-qualified storage_uri so the same handler works across providers. See Recording Storage to set up GCS, Azure, or S3-in-any-region destinations.
  • application.recording_copy_failed: This is fired only on the worker-copy path (GCS, Azure, or S3 in regions Daily doesn’t support natively) when Tavus is unable to deliver the recording into your bucket after retries. Daily’s default storage retains the recording for ~30 days as a manual recovery window. Common causes: customer IAM trust policy mismatch, federated credential drift, bucket region typo. Use this as the canary for misconfiguration in your end.
  • application.perception_analysis: This is fired after ending a conversation, when the PAL has finished summarizing the visual artifacts that were detected throughout the call. This is a feature that is only available when the PAL has raven-1 specified in the Perception Layer.
  • application.post_call_action_executed: This is fired once for each post-call action Tavus runs after the conversation ends, recording the outcome (tool_name, status, and the request / response). The same payload is also available on the verbose GET conversation response under events.
Examples:

Guardrail Callbacks

If a callback_url is provided on a guardrail, a callback is sent when that guardrail is triggered during a conversation.

Objective Callbacks

If a callback_url is provided on an objective, a callback is sent when that objective is completed during a conversation.

Face Training Callbacks

If a callback_url is provided in the POST /faces call, you will receive a callback on face training completion or on face training error.
Dual delivery during the replicaface rename. While the API transitions from replica to face, each training event triggers two POSTs to the same callback_url: first the legacy payload with replica_id (for backward compatibility), then a second payload with face_id. Both POSTs share the same UUID value, the same status, and, on error, the same error_message - only the id field name differs.To handle this cleanly:
  • Distinguish the two payloads by which id field is present (replica_id vs. face_id).
  • De-duplicate on your side by treating replica_id and face_id as the same identifier for a given training event.
  • New integrations should key off face_id; the replica_id twin will be removed once the legacy field is retired.
Legacy payload (replica_id)
New payload (face_id)

Video Generation Callbacks

If a callback_url is provided in the POST /videos call, you will receive callbacks on video generation completed and on video error.

Sample Webhook Setup

Create a sample webhook endpoint using Python Flask, and expose it publicly with ngrok.

Prerequisites

1

Step 1: Install Python Dependencies

Install the Python dependencies needed to create the server.
2

Step 2: Make a Webhook Server

Set up a webhook server and save it as server.py.
The server will receive and process webhook callbacks from Tavus, handle different event types, store transcripts in memory, and analyze conversation data for each session.
3

Step 3: Run the Server

Run the app using the following command in the terminal:
The server should run on port 5000.
4

Step 4: Forward the Port Using Ngrok

With ngrok installed and on your PATH, forward the port from a terminal (on Windows you can run ngrok.exe from the install folder instead).
The command will generate a forwarding link (e.g., https://1234567890.ngrok-free.app), which can be used as the callback URL.
5

Step 5: Use the Callback URL

Include the callback URL in your request to Tavus by appending /webhook to the forwarding link and setting it in the callback_url field.
Create conversation with callback_url
  • Replace <api-key> with your actual API key. You can generate one in the PAL Maker.
  • Replace <face_id> with the Face ID you want to use.
  • Replace <pal_id> with the PAL ID you want to use.