Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
twilio avatar

Twilio Call Recordings

  • 85 installs
  • 26 repo stars
  • Updated July 29, 2026
  • twilio/ai

twilio-call-recordings is an agent skill that implements correct Twilio voice recording using Dial record, dual-channel audio, Conference capture, and PCI pause patterns.

About

The twilio-call-recordings skill explains how to capture Twilio voice audio for compliance, QA, and analytics without the common mistake of using the Record verb for two-party calls. A comparison table contrasts Record for caller-only voicemail capture, Dial record for both parties, Start Recording for multi-verb flows such as ConversationRelay, Conference record for multi-party mixes, and REST API mid-call controls for PCI pause during payments. Quickstart Flask and Express examples use dial record-from-answer-dual with recording_status_callback webhooks, emphasizing jurisdiction-specific consent requirements via twilio-compliance-traffic. Recording status handlers should validate X-Twilio-Signature because unauthenticated callbacks can be spoofed. Advanced patterns cover dual-channel separation for agent QA, pausing and resuming recordings around card entry, and Conference recording with participant modes. Prerequisites include voice-capable numbers, TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, and a webhook endpoint. Use whenever developers need correct Twilio call recording architecture instead of voicemail-style Record behavior.

  • Contrasts Record verb voicemail capture vs Dial record for two-party calls.
  • Provides dual-channel record-from-answer-dual quickstart with status callbacks.
  • Documents mid-call pause and resume for PCI-sensitive payment flows.
  • Covers Conference recording and ConversationRelay Start Recording workaround.
  • Requires X-Twilio-Signature validation on recording callbacks.

Twilio Call Recordings by the numbers

  • 85 all-time installs (skills.sh)
  • +6 installs in the week ending Aug 5, 2026 (Skillselion tracking)
  • Ranked #3,036 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
At a glance

twilio-call-recordings capabilities & compatibility

Capabilities
record vs dial record decision guide · dual channel recording quickstart · recording status callback handling · mid call pci pause via rest api · conference and conversationrelay patterns
Use cases
api development
Pricing
Bring your own API key
npx skills add https://github.com/twilio/ai --skill twilio-call-recordings

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs85
repo stars26
Last updatedJuly 29, 2026
Repositorytwilio/ai

How do I record both sides of a Twilio call for QA without accidentally creating voicemail-style Record behavior?

Record two-party Twilio voice calls with Dial record, dual-channel QA audio, mid-call PCI pause, and secure recording callbacks.

Who is it for?

Developers building Twilio voice apps that need compliant two-party call recording and QA audio separation.

Skip if: Skip for SMS-only apps or simple caller voicemail capture where Record verb is intended.

When should I use this skill?

User needs Twilio call recording, dual-channel QA audio, PCI pause during payments, or recording webhooks.

What you get

Correct Dial or Conference recording with consent prompts, dual-channel options, and secured status callbacks.

Files

SKILL.mdMarkdownGitHub ↗

Overview

Twilio offers multiple recording methods. Choosing the wrong one is the #1 developer mistake in voice — using <Record> when you mean <Dial record> produces voicemail behavior instead of call recording.

MethodWhat it doesUse when
<Record> verbRecords the CALLER only (voicemail-style)Leaving a message, capturing input
<Dial record>Records BOTH parties on a callCall recording for two-party calls
<Start><Recording>Starts a recording alongside other verbsConversationRelay, multi-verb flows
Conference recordRecords the conference mixMulti-party calls
Recordings REST APIProgrammatic control mid-callPause during payment (PCI)

---

Prerequisites

  • Twilio account with a voice-capable phone number — see twilio-account-setup
  • TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN — see twilio-iam-auth-setup
  • SDK: pip install twilio / npm install twilio
  • A webhook endpoint for recording status callbacks
  • Compliance check: Recording consent requirements vary by jurisdiction — see twilio-compliance-traffic

---

Quickstart

Record a Two-Party Call (Most Common)

Use <Dial record> — NOT <Record>.

Python (Flask)

from flask import Flask, request
from twilio.twiml.voice_response import VoiceResponse

app = Flask(__name__)

@app.route("/voice", methods=["POST"])
def incoming_call():
    response = VoiceResponse()
    response.say("This call may be recorded for quality assurance.")
    dial = response.dial(
        record="record-from-answer-dual",  # dual-channel: agent on one, caller on other
        recording_status_callback="https://yourapp.com/recording-status"
    )
    dial.number("+15558675310")  # agent's phone
    return str(response)

Node.js (Express)

app.post("/voice", (req, res) => {
    const response = new VoiceResponse();
    response.say("This call may be recorded for quality assurance.");
    const dial = response.dial({
        record: "record-from-answer-dual",
        recordingStatusCallback: "https://yourapp.com/recording-status",
    });
    dial.number("+15558675310");
    res.type("text/xml").send(response.toString());
});

Handle the Recording Status Callback

Security: Validate X-Twilio-Signature on recording callbacks in production. Without validation, attackers could POST fake recording URLs to your endpoint.

Python (Flask)

@app.route("/recording-status", methods=["POST"])
def recording_status():
    recording_sid = request.form["RecordingSid"]
    recording_url = request.form["RecordingUrl"]
    call_sid = request.form["CallSid"]
    status = request.form["RecordingStatus"]  # "completed", "failed"
    duration = request.form.get("RecordingDuration", 0)

    if status == "completed":
        # Store recording reference
        save_recording(call_sid, recording_sid, recording_url, duration)

    return "", 200

---

Key Patterns

Recording Modes for <Dial record>

ModeWhat's recordedUse case
record-from-answerSingle channel, both parties mixedSimple recording
record-from-answer-dualDual channel — caller on left, agent on rightQA (separate agent/caller audio)
record-from-ringingRecords from ring, not answerCapture ring time + full call
record-from-ringing-dualDual channel from ringQA with ring time

Always use `dual` for QA and analytics. Dual-channel lets speech analytics tools (like Conversation Intelligence) distinguish agent from caller.

Conference Recording

Record multi-party calls via the Conference:

Python

response = VoiceResponse()
dial = response.dial()
dial.conference(
    "support-room-123",
    record="record-from-start",  # Records from when conference starts
    recording_status_callback="https://yourapp.com/conf-recording-status"
)

Note: Conference recording captures the main audio mix. Coach/whisper audio is NOT included. See twilio-conference-calls.

ConversationRelay Recording

Critical: record:true on the REST API call is silently ignored with ConversationRelay. No error. No recording.

Correct approach: Use <Start><Recording> in TwiML before <Connect>:

Python

@app.route("/voice", methods=["POST"])
def voice():
    response = VoiceResponse()
    response.say("This call may be recorded.")
    
    # Start recording BEFORE connecting ConversationRelay
    start = Start()
    start.recording(
        recording_status_callback="https://yourapp.com/recording-status",
        recording_status_callback_event="completed"
    )
    response.append(start)
    
    # Now connect ConversationRelay
    connect = Connect()
    connect.conversation_relay(url="wss://yourapp.com/ws/voice")
    response.append(connect)
    
    return str(response)

Node.js

app.post("/voice", (req, res) => {
    const response = new VoiceResponse();
    response.say("This call may be recorded.");
    
    const start = response.start();
    start.recording({
        recordingStatusCallback: "https://yourapp.com/recording-status",
        recordingStatusCallbackEvent: "completed",
    });
    
    const connect = response.connect();
    connect.conversationRelay({ url: "wss://yourapp.com/ws/voice" });
    
    res.type("text/xml").send(response.toString());
});

Mid-Call Pause for PCI Compliance

Pause recording when a customer provides payment information:

Python

def pause_recording_for_payment(call_sid, recording_sid):
    """Pause recording during credit card capture."""
    client.calls(call_sid).recordings(recording_sid).update(
        status="paused"
    )

def resume_recording(call_sid, recording_sid):
    """Resume recording after payment processed."""
    client.calls(call_sid).recordings(recording_sid).update(
        status="in-progress"
    )

Node.js

async function pauseForPayment(callSid, recordingSid) {
    await client.calls(callSid).recordings(recordingSid).update({
        status: "paused",
    });
}

async function resumeRecording(callSid, recordingSid) {
    await client.calls(callSid).recordings(recordingSid).update({
        status: "in-progress",
    });
}

PCI DSS: Never record card numbers. Use Twilio's <Pay> verb when possible. If collecting verbally, pause recording for the duration. PCI Mode is IRREVERSIBLE and account-wide — use a sub-account if only some calls need PCI.

Accessing Recordings

Python

# List recordings for a specific call
recordings = client.recordings.list(call_sid=call_sid)

for recording in recordings:
    print(f"SID: {recording.sid}")
    print(f"Duration: {recording.duration}s")
    print(f"URL: https://api.twilio.com{recording.uri.replace('.json', '.mp3')}")

# Download a recording
import requests as req
audio = req.get(
    f"https://api.twilio.com/2010-04-01/Accounts/{account_sid}/Recordings/{recording_sid}.mp3",
    auth=(account_sid, auth_token)
)
with open("recording.mp3", "wb") as f:
    f.write(audio.content)

# Delete a recording (GDPR right to deletion)
client.recordings(recording_sid).delete()

Recording Storage & Retention

FeatureDefaultNotes
Storage locationTwilio cloudCan configure external storage (S3, GCS)
RetentionIndefiniteDelete manually via API or set auto-delete policy
FormatsWAV (default), MP3Request MP3 by appending .mp3 to URL
EncryptionAt restAdditional encryption with PCI Mode

---

Common Errors

SymptomCauseFix
Recording captures only caller (no agent)Used <Record> verb instead of <Dial record>Switch to <Dial record="record-from-answer">
No recording at allUsed REST API record:true with ConversationRelayUse <Start><Recording> in TwiML
Recording is empty / silentWebhook endpoint unreachable, recording never startedCheck StatusCallback URL reachability
Recording has both parties on same channelUsed record-from-answer (mono)Use record-from-answer-dual for separate channels
Coach audio missing from conference recordingExpected behavior — coach audio isn't in the mixRecord coach's call leg separately

---

CANNOT

  • `recordingTrack` has no observable effect via TwiML — The <Start><Recording> TwiML parameter recordingTrack does not isolate tracks. Use the Recordings REST API with recordingTrack for actual track isolation.
  • Cannot start API recordings on ConversationRelay calls — REST API record:true is silently ignored ("not eligible for recording"). Must use <Start><Recording> before <Connect> in TwiML.
  • Cannot pause/resume recordings via TwiML — Only available via the REST API (update with status="paused" or status="in-progress").
  • Cannot get dual-channel conference recordings — Conference recording is always mono (mixed).
  • Cannot get dual-channel from Calls API without explicit paramRecord=true defaults to mono. Must specify recordingChannels: 'dual'.
  • Cannot transcribe PCI-mode recordings — Recordings created while PCI mode was enabled cannot be transcribed, even after PCI is disabled.
  • Cannot use `<Record>` verb for call recording<Record> captures the caller only (voicemail-style). Use <Dial record> or <Start><Recording> for call recording.
  • Cannot capture coach/whisper audio in conference recordings — Supervisor whisper is excluded from the mix
  • Cannot reverse PCI Mode — PCI Mode is irreversible and account-wide. Once enabled, all recordings are encrypted.
  • Cannot auto-delete recordings without configuration — Recordings are retained indefinitely unless you configure auto-deletion
  • Cannot avoid larger file sizes with dual-channel — Dual-channel recordings are ~2x the size of mono. Factor into storage costs.

---

Next Steps

  • Conference calls: twilio-conference-calls
  • Agent routing: twilio-taskrouter-routing
  • Compliance: twilio-compliance-traffic
  • Debug recording issues: twilio-debugging-observability

Related skills

FAQ

What is the most common Twilio recording mistake?

Using the Record verb when Dial record is needed, which records only the caller like voicemail.

When should I use twilio-call-recordings?

When capturing two-party call audio, conference mixes, or mid-call PCI pauses on Twilio voice.

Is twilio-call-recordings safe to install?

Review the Security Audits panel on this page before installing in production.

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.