Call recordings are useful until they become a privacy problem.
Support teams use them for QA. Sales teams use them for coaching. Compliance teams use them for audits. Product teams use transcripts to understand what customers are asking for.
But real calls contain real customer data.
Names, phone numbers, email addresses, account IDs, credit card numbers, street addresses, dates of birth, and sometimes even national IDs can show up in the middle of a completely normal conversation. Once that data lands in a transcript, every downstream system that touches the transcript becomes part of your privacy surface area.
That is the problem this example explores: how do you make call transcripts useful without spreading raw PII everywhere?
Code: github.com/team-telnyx/telnyx-code-examples/tree/main/call-recording-redactor-python
What the app does
The app is a small Flask service with two paths:
POST /redact
POST /redact/audio
If you already have a transcript, send it directly to /redact.
If you have a recording, upload the audio file to /redact/audio. The app transcribes the recording with Telnyx Speech-to-Text, then sends the transcript to Telnyx AI Inference for PII detection and redaction.
The output is not just a rewritten transcript. It is structured JSON:
{
"redacted_transcript": "Hi, this is [NAME] calling. My card number is [CREDIT_CARD].",
"redactions": [
{
"type": "name",
"original": "John Smith",
"redacted": "[NAME]",
"count": 1
}
],
"items_redacted": 2,
"pii_types_found": ["name", "credit_card"]
}
That structure is the important part.
A human can read the redacted transcript. An application can use the redaction map for review, audit logs, analytics, or approval workflows.
The call recording pipeline
Conceptually, the flow is simple:
Call recording or transcript
|
v
Flask app
|
|-- audio file -> Telnyx Speech-to-Text
|
|-- transcript -> Telnyx AI Inference
v
Redacted transcript + redaction map
For audio uploads, the app calls:
POST /v2/ai/audio/transcriptions
using:
distil-whisper/distil-large-v2
Then it calls:
POST /v2/ai/chat/completions
The default model in the sample is:
meta-llama/Llama-3.3-70B-Instruct
You can change the model in .env:
TELNYX_API_KEY=your_telnyx_api_key
AI_MODEL=meta-llama/Llama-3.3-70B-Instruct
HOST=127.0.0.1
Redacting a pasted transcript
The fastest way to try the example is with a text transcript:
curl -X POST http://localhost:5000/redact \
-H "Content-Type: application/json" \
-d '{
"transcript": "Hi, this is John Smith calling. My card number is 4532-1234-5678-9012 and my SSN is 123-45-6789. You can reach me at john.smith@email.com."
}'
The app asks Telnyx AI Inference to return JSON only. It replaces sensitive values with tagged placeholders like:
[NAME][CREDIT_CARD][SSN][PHONE][EMAIL][ADDRESS][DOB][ACCOUNT_NUMBER]
That makes the transcript safer to hand to QA, analytics, training, or internal tooling.
Redacting an audio recording
If you have an audio file, the app can run the full flow:
curl -X POST http://localhost:5000/redact/audio \
-F "file=@recording.wav"
The server reads the file, sends it to Telnyx STT, gets back text, and then runs the same redaction flow as /redact.
This is the version I would build on for real call workflows. For example, a production app could listen for a recording webhook, pull the recording, transcribe it, redact the transcript, and store the sanitized version for downstream use.
Why structured redaction matters
There are a few ways to redact sensitive data.
Regex works for obvious patterns like email addresses or credit card-like strings. But call transcripts are messy. People interrupt themselves. They spell things out. They say account numbers in chunks. Names and addresses do not always follow a clean pattern.
An LLM-based redaction layer gives you more flexibility because it can use context. The point is not to abandon deterministic rules entirely. The better production pattern is usually layered:
- use deterministic checks for high-confidence patterns
- use AI for context-aware detection
- return structured output
- review and audit what changed
This sample focuses on the AI layer and the application shape around it.
Production considerations
The example keeps recent redactions in memory so the core flow stays easy to follow.
For production, I would add:
- authentication around every endpoint
- durable storage for redaction jobs
- object storage for original and redacted artifacts
- async queues for longer recordings
- call recording webhook ingestion
- stronger JSON schema validation
- audit logs for every redaction
- role-based access for original transcripts
- custom PII types for your industry
- audio masking if the original recording also needs redaction
That last point matters. This example redacts transcripts. If your compliance requirement says the audio itself must be sanitized, you would also need timestamp-aware audio masking or bleeping.
Where this pattern fits
This is useful anywhere recorded conversations turn into operational data:
- contact center QA
- support coaching
- sales call review
- healthcare intake workflows
- insurance claims
- financial services support
- legal intake
- customer research
The broader idea is simple: keep the useful parts of call recordings while reducing the amount of sensitive data that spreads through the rest of the system.
That is a practical AI workflow. Not a chatbot, not a demo prompt, but a small piece of infrastructure that helps teams work with communications data more responsibly.