Skip to main content
Telnyx Deepfake Detection analyzes live call audio to determine whether the remote party’s voice is human or AI-generated. When enabled, audio is streamed in real time to a detection model that returns a classification result via webhook. Deepfake detection is available on both outbound calls (Dial) and inbound calls (Answer).

How it works

  1. You enable deepfake_detection when dialing or answering a call.
  2. Telnyx streams the remote party’s audio to the detection service.
  3. The service analyzes audio frames and returns a result within the configured timeout.
  4. You receive a call.deepfake_detection.result webhook with the classification, or a call.deepfake_detection.error webhook if something went wrong.
The call proceeds normally while detection runs in the background — there is no impact on call audio or latency.

Configuration parameters

ParameterTypeDefaultRangeDescription
enabledbooleanfalseWhether deepfake detection is enabled.
timeoutinteger155–60Maximum seconds to wait for a detection result before timing out.
rtp_timeoutinteger305–120Maximum seconds to wait for RTP audio. If no audio arrives within this window, detection stops with an error.

Enabling on an outbound call

Include the deepfake_detection object when creating an outbound call via the Dial command:
POST https://api.telnyx.com/v2/calls HTTP/1.1
Content-Type: application/json; charset=utf-8
Authorization: Bearer YOUR_API_KEY

{
  "connection_id": "uuid-of-your-connection",
  "to": "+18005551234",
  "from": "+18005554321",
  "deepfake_detection": {
    "enabled": true,
    "timeout": 15,
    "rtp_timeout": 30
  },
  "webhook_url": "https://www.example.com/webhooks"
}

Enabling on an inbound call

Add deepfake_detection to the Answer command when picking up an incoming call:
POST https://api.telnyx.com/v2/calls/{call_control_id}/actions/answer HTTP/1.1
Content-Type: application/json; charset=utf-8
Authorization: Bearer YOUR_API_KEY

{
  "deepfake_detection": {
    "enabled": true,
    "timeout": 20,
    "rtp_timeout": 30
  }
}

Handling the result webhook

When detection completes, you receive a call.deepfake_detection.result webhook:
{
  "record_type": "event",
  "event_type": "call.deepfake_detection.result",
  "id": "0ccc7b54-4df3-4bca-a65a-3da1ecc777f0",
  "occurred_at": "2025-06-15T14:30:27.521992Z",
  "payload": {
    "call_control_id": "v3:MdI91X4lWFEs7IgbBEOT9M4AigoY08M0WWZFISt1Yw2axZ_IiE4pqg",
    "connection_id": "7267xxxxxxxxxxxxxx",
    "call_leg_id": "428c31b6-7af4-4bcb-b7f5-5013ef9657c1",
    "call_session_id": "428c31b6-7af4-4bcb-b7f5-5013ef9657c1",
    "client_state": "aGF2ZSBhIG5pY2UgZGF5ID1d",
    "result": "fake",
    "score": 0.87,
    "consistency": 94.5
  }
}

Result fields

FieldTypeDescription
resultstringreal — human voice detected. fake — AI-generated voice detected. silence_timeout — no analyzable speech before timeout.
scorefloat | nullProbability the audio is AI-generated, from 0.0 (likely real) to 1.0 (likely deepfake). Null for silence_timeout.
consistencyfloat | nullPercentage (0–100) indicating how consistently the model classified the audio across frames. Values above 90% indicate high confidence. Null for silence_timeout.

Handling errors

If detection fails, you receive a call.deepfake_detection.error webhook:
{
  "record_type": "event",
  "event_type": "call.deepfake_detection.error",
  "id": "0ccc7b54-4df3-4bca-a65a-3da1ecc777f0",
  "occurred_at": "2025-06-15T14:30:27.521992Z",
  "payload": {
    "call_control_id": "v3:MdI91X4lWFEs7IgbBEOT9M4AigoY08M0WWZFISt1Yw2axZ_IiE4pqg",
    "connection_id": "7267xxxxxxxxxxxxxx",
    "call_leg_id": "428c31b6-7af4-4bcb-b7f5-5013ef9657c1",
    "call_session_id": "428c31b6-7af4-4bcb-b7f5-5013ef9657c1",
    "client_state": "aGF2ZSBhIG5pY2UgZGF5ID1d",
    "error_message": "detection_timeout"
  }
}

Error types

ErrorDescription
detection_timeoutNo detection result received within the configured timeout.
rtp_timeoutNo RTP audio received within the configured rtp_timeout.
dfd_connection_errorCould not connect to the detection service.
dfd_stream_errorAudio stream to the detection service failed.

Example: screening inbound calls

This example webhook server answers inbound calls with deepfake detection enabled and takes action based on the result.
const express = require("express");
const axios = require("axios");
const app = express();

app.use(express.json());

const TELNYX_API_KEY = process.env.TELNYX_API_KEY;
const telnyxApi = axios.create({
  baseURL: "https://api.telnyx.com/v2",
  headers: { Authorization: `Bearer ${TELNYX_API_KEY}` },
});

// Answer incoming calls with deepfake detection enabled
app.post("/webhooks/call-initiated", async (req, res) => {
  const { call_control_id } = req.body.payload;

  await telnyxApi.post(
    `/calls/${call_control_id}/actions/answer`,
    {
      deepfake_detection: {
        enabled: true,
        timeout: 15,
        rtp_timeout: 30,
      },
    }
  );

  res.sendStatus(200);
});

// Handle deepfake detection results
app.post("/webhooks/deepfake-result", async (req, res) => {
  const { call_control_id, result, score, consistency } =
    req.body.payload;

  console.log(
    `Detection result: ${result}, score: ${score}, consistency: ${consistency}%`
  );

  if (result === "fake" && score > 0.8) {
    // High-confidence deepfake — hang up or route to fraud queue
    await telnyxApi.post(
      `/calls/${call_control_id}/actions/hangup`,
      {}
    );
    console.log("Deepfake detected — call terminated.");
  } else if (result === "real") {
    // Human caller — proceed normally
    await telnyxApi.post(
      `/calls/${call_control_id}/actions/speak`,
      {
        payload: "Welcome! How can we help you today?",
        language: "en-US",
        voice: "female",
      }
    );
  }
  // silence_timeout — caller didn't speak; handle as needed

  res.sendStatus(200);
});

// Handle detection errors gracefully
app.post("/webhooks/deepfake-error", async (req, res) => {
  const { call_control_id, error_message } = req.body.payload;
  console.log(`Deepfake detection error: ${error_message}`);

  // Continue the call normally if detection fails
  await telnyxApi.post(
    `/calls/${call_control_id}/actions/speak`,
    {
      payload: "Welcome! How can we help you today?",
      language: "en-US",
      voice: "female",
    }
  );

  res.sendStatus(200);
});

app.listen(3000, () => console.log("Webhook server running on port 3000"));

Best practices

  • Set appropriate timeouts. The default 15-second detection timeout works well for most calls. Increase it if callers may take longer to start speaking (e.g., IVR prompts on the remote end).
  • Use score and consistency together. A high score with high consistency is a strong signal. A high score with low consistency may warrant additional verification rather than an immediate hangup.
  • Handle errors gracefully. Detection errors should not block the call. Design your application to fall through to normal call handling when detection is unavailable.