BeyondCalls Documentation
The AI Revenue Operating System for autonomous outbound sales. Multi-channel sequences, AI voice dialing, real-time call coaching, and intelligent email automation.
Architecture
BeyondCalls is built on a modern stack designed for real-time sales operations:
- Frontend — Next.js 16, React, TypeScript, Tailwind CSS, shadcn/ui
- Backend — Next.js API Routes (App Router), Prisma ORM
- Database — PostgreSQL with multi-schema architecture (public, revenue_os, communications)
- Voice — Telnyx TeXML Voice, Telnyx WebRTC SDK, Retell AI
- Transfer Architecture (v6.2.1) — Zero-Delay Pre-Connect with AMD Gating: agent joins conference simultaneously with prospect call (0s dead air). AMD confirmation gates disposition screen.
endConferenceOnExit="true"ensures prospect hangup ends both calls. LHU auto-submits in 1.5s. - Real-time — Pusher for live event streaming to SDR desktops
- Email — Resend API for transactional email, with SMTP fallback
- AI — OpenAI GPT-4o for email generation, Retell AI for voice conversations
- Auth — Clerk for authentication and team management
- Hosting — Google Cloud Run (GCP) with Cloud SQL PostgreSQL
Quick Start
After signing in to the dashboard, the typical SDR workflow is:
- Import Leads — Upload a CSV or connect Apollo/ZoomInfo/Explorium in Lead Gen settings
- Create a Campaign — Set up a power-dial campaign with your script, talking points, and DID selection
- Build Sequences — Create multi-step email sequences with AI-generated content and collateral
- Start Dialing — Launch the power dialer from the SDR Desktop. The AI handles initial conversations.
- Take Transfers — When the AI confirms a human prospect, you're seamlessly connected via direct dial (sub-2 second latency)
- Review & Coach — Use the AI Coaching Dashboard to review calls, analyze performance, and replay Retell conversations
Power Dialer
The power dialer calls multiple prospects simultaneously, dramatically increasing connect rates. When a human answers, the system bridges them to you instantly.
How It Works
- Select a campaign and click Start Power Dial on the SDR Desktop
- The system dials 3-5 leads from your campaign simultaneously
- Each call runs through AMD (Answering Machine Detection) or Retell AI
- Voicemails and machines are automatically disconnected
- The first human to answer wins — all other calls are cancelled
- You're connected via direct
<Dial><Client>bridge with sub-2 second latency — no conference overhead
Hot-Bridge Transfers
Hot-Bridge is the premium transfer mode using Retell AI. Instead of silent AMD, an AI agent has a natural conversation with the prospect first.
v6.0.0 Direct-Dial Transfer Flow
- AI calls prospect — Retell AI dials the prospect and has a natural conversation
- Human verification — The AI confirms the answerer is a real human (not voicemail)
- Instant response — Webhook returns to Retell in <200ms via
after(), AI speaks "Transferring you now" immediately - Direct dial redirect — Prospect's existing call is redirected with
<Dial><Client>agent-xxx</Client></Dial>— just 2 media hops - Seamless handoff — SDR hears the prospect within 1-2 seconds. No conference overhead, no audio crackling.
Direct Dial Architecture
The v6.0.0 Hybrid Transfer Architecture fundamentally changes how calls are connected:
Before (Conference-Based — v5.x)
Prospect PSTN → Conference → SDR WebRTC
↑
3 media hops, ~5-8s latency
Audio crackling from triple relayAfter (Direct-Dial — v6.0.0)
Prospect PSTN → Provider Bridge → SDR WebRTC
↑
2 media hops, <2s latency
Zero audio cracklingKey Components
- Nuclear Path — Retrieves the underlying Call SID from Retell and redirects it with
calls(sid).update(twiml). The prospect never disconnects. - Fallback Path — If we can't retrieve the Call SID, we create a new outbound call with
<Dial><Client>TwiML. - Dial Complete Webhook —
/api/webhooks/warm-transfer/dial-completestores the SDR's child Call SID for potential conference escalation. - On-Demand Escalation —
/api/webhooks/warm-transfer/escalate-conferenceupgrades any direct-dial call to a conference when a supervisor needs access. - SDR LHU Auto-Detect — If the prospect disconnects, the SDR Desktop automatically pre-selects "Lead Hung Up" disposition.
Latency Benchmarks
| Parameter | Type | Required | Description |
|---|---|---|---|
Hot-Bridge webhook response | 153-207ms | No | Time for Retell to receive tool result (AI speaks instantly) |
AMD Callback (2x-5x power dial) | 240-337ms | No | Time to return AMD result and trigger agent call |
dial-complete webhook | 134-182ms | No | SDR call SID storage, call lifecycle management |
escalate-conference | 134-194ms | No | On-demand conference creation for supervisor |
AI Context Summarization
Paste any sales document (pitch decks, competitive analysis, product specs) into the Campaign Context Editor, and GPT-4o instantly extracts curated talking points for live calls.
How It Works
- Open the Sales Context tab in any campaign or the SDR Desktop
- Paste your raw document text (min. 20 characters)
- Click the AI Summarize button
- GPT-4o extracts: 5 icebreakers, 5 pain points, and an elevator pitch
- Results appear in the new AI Insights tab and are saved to the campaign
- During live calls, the Sales Copilot automatically injects these as priority icebreakers
API
/api/warm-transfer/campaigns/[id]/summarize-contextExtract icebreakers & pain points from raw context| Parameter | Type | Required | Description |
|---|---|---|---|
text | string | Yes | Raw sales context text (min 20 chars, max ~8000 chars processed) |
AI Call Coaching
The Coaching Dashboard analyzes your calls and provides actionable feedback:
- Call Recordings — Review all recorded calls with playback controls
- AI Analysis — Get automated feedback on talk-to-listen ratio, objection handling, and closing techniques
- Retell Replay — Review what the AI said to the prospect before the transfer
- Performance Metrics — Track connect rates, call durations, and conversion trends over time
iPhone VM Guard
iPhone VM Guard prevents transfers to voicemail by running a secondary AMD check before completing the hot-bridge transfer. If the prospect's phone goes to voicemail after initial pickup (common with iPhone's "Silence Unknown Callers"), the transfer is blocked and the call is ended gracefully.
Retell AI Replay
Replay AI-prospect conversations directly from the SDR Desktop or Coaching Dashboard:
- Structured Transcript — Turn-by-turn chat bubbles showing what the AI and prospect said
- Audio Playback — Play, pause, and seek through the call recording
- Call Metadata — Duration, sentiment analysis, call outcome, disconnect reason
- Multi-Call View — See all AI calls for a specific lead
Email Sequences
Build multi-step outreach sequences that combine email, phone, SMS, LinkedIn, and conditional logic.
Supported Step Types
- EMAIL — Automated email with personalization variables and tracking
- PHONE_CALL — Reminder to make a phone call (integrates with power dialer)
- SMS — Text message step (via SMS)
- LINKEDIN — LinkedIn outreach reminder or automation
- CONDITION — Branch logic based on email opens, clicks, replies, or bounces
Writing Styles
Each sequence can be configured with a writing style that affects all AI-generated content:
| Parameter | Type | Required | Description |
|---|---|---|---|
formal | style | No | Professional, business-appropriate language. No slang or contractions. |
casual | style | No | Friendly and conversational. Uses contractions naturally. |
assertive | style | No | Direct and confident. Leads with strong value propositions. |
consultative | style | No | Helpful and advisory. Asks insightful questions. Positions as trusted advisor. |
educational | style | No | Informative and teaching-oriented. Shares data and insights. |
Sales Collateral
Attach sales materials to sequence steps. Collateral is automatically referenced in AI-generated emails.
- Types — Whitepapers, Case Studies, ROI Calculators, Product Demos, Pricing Sheets, Battle Cards
- AI Targeting — Each piece has metadata: target industries, personas, pain points, buying stages
- Performance Tracking — Track times used, opens, and reply rates per collateral piece
AI Email Generation
Generate personalized email content using GPT-4o. The AI considers lead context, sequence configuration, previous emails, and attached collateral.
curl -X POST /api/v2/sequences/generate-email \
-H "Content-Type: application/json" \
-d '{
"firstName": "Sarah",
"lastName": "Chen",
"title": "VP of Sales",
"company": "Acme Corp",
"industry": "SaaS",
"writingStyle": "consultative",
"stepType": "initial_outreach",
"customInstructions": "Mention our recent Series B funding"
}'Open & Click Tracking
Every email sent through the sequence engine includes automatic tracking:
Open Tracking
A 1x1 transparent pixel is injected at the bottom of every HTML email. When the recipient's email client loads the image, an OPENED event is recorded with timestamp and user agent.
Click Tracking
All links in outbound emails are automatically wrapped with tracking redirects. When a recipient clicks a link, a CLICKED event is recorded before redirecting to the original URL.
API Reference
All API endpoints require authentication via Clerk. Include the session token in the request headers.
Sequences
/api/v2/sequencesList all sequences/api/v2/sequencesCreate a new sequence/api/v2/sequences/[id]Get sequence details/api/v2/sequences/[id]Update a sequence/api/v2/sequences/[id]Delete a sequence/api/v2/sequences/[id]/stepsList steps for a sequence/api/v2/sequences/[id]/stepsAdd a step to a sequence/api/v2/sequences/[id]/enrollEnroll leads in a sequence/api/v2/sequences/processProcess due enrollments (trigger engine)Collateral
/api/v2/collateralList all sales collateral/api/v2/collateralCreate collateral/api/v2/collateralUpdate collateral/api/v2/collateralDelete collateralEmail Accounts
/api/v2/email-accountsList connected email accounts/api/v2/email-accountsConnect a new email account/api/v2/email-accounts/[id]Update account settings/api/v2/email-accounts/[id]Disconnect an account/api/v2/email-accounts/[id]/testTest email account connectionAI Email Generation
/api/v2/sequences/generate-emailGenerate personalized email content| Parameter | Type | Required | Description |
|---|---|---|---|
leadId | string | No | Auto-enrich from lead data (name, company, industry) |
sequenceId | string | No | Auto-enrich from sequence config (writing style, brand voice) |
firstName | string | No | Prospect's first name |
company | string | No | Prospect's company name |
title | string | No | Prospect's job title |
industry | string | No | Prospect's industry |
writingStyle | string | No | formal, casual, assertive, consultative, educational |
stepType | string | No | initial_outreach, follow_up, breakup, nurture, re_engagement |
customInstructions | string | No | Additional prompt instructions for the AI |
collateralSummary | string | No | Summary of attached collateral to reference |
previousEmails | string[] | No | Previous email subjects for context continuity |
Response:
{
"subject": "Quick question about Acme's Q4 pipeline",
"body": "Hi Sarah, ...",
"bodyHtml": "<div>...</div>",
"preheader": "I noticed Acme recently...",
"cta": "Would a 15-minute call this week work?",
"personalizationNotes": "Referenced VP title, SaaS industry",
"model": "gpt-4o",
"tokensUsed": 347
}Email Tracking
/api/v2/emails/track/open?id={eventId}Tracking pixel (returns 1x1 GIF)Returns a transparent 1x1 GIF image. Records an OPENED event for the given email event ID. No authentication required — this is embedded in emails.
/api/v2/emails/track/click?id={eventId}&url={destinationUrl}Click redirect (302)Records a CLICKED event and redirects (302) to the destination URL. No authentication required — this wraps links in emails.
/api/v2/emails/eventsList email events (sent, opened, clicked, etc.)Retell Replay
/api/v2/retell/replay?callId={retellCallId}Get call transcript, recording, and analysis/api/v2/retell/replay?leadId={leadId}Get all Retell calls for a leadResponse:
{
"call": {
"callId": "call_abc123",
"callStatus": "ended",
"durationMs": 45000,
"recordingUrl": "https://...",
"callAnalysis": {
"userSentiment": "Positive",
"callSuccessful": true
},
"segments": [
{ "role": "agent", "content": "Hi, this is Joe from..." },
{ "role": "user", "content": "Oh hi Joe, how are you?" }
]
}
}Analytics
/api/v2/sequences/analyticsSequence performance analyticsReturns conversion funnel metrics: enrolled, sent, opened, clicked, replied, meetings booked. Supports per-sequence filtering and time period selection.
Webhooks
Webhook endpoints that receive callbacks from Telnyx, Retell AI, and Resend.
Warm Transfer Webhooks
/api/webhooks/warm-transferMain call status webhook/api/webhooks/warm-transfer/amd-callbackAMD detection results/api/webhooks/warm-transfer/conferenceConference events (join, leave)/api/webhooks/warm-transfer/inbound-callInbound call routing/api/webhooks/warm-transfer/recording-statusRecording completion/api/webhooks/warm-transfer/call-statusCall lifecycle eventsDial Complete (v6.0.0)
/api/webhooks/warm-transfer/dial-completeDirect-dial action callback — called when <Dial> completesCalled by the provider when the <Dial><Client> action completes (either party hangs up, or the dial fails). Handles call lifecycle management for direct-dial transfers:
| Parameter | Type | Required | Description |
|---|---|---|---|
CallSid | string | Yes | Prospect's parent call SID |
DialCallSid | string | Yes | SDR's child call SID (stored for conference escalation) |
DialCallStatus | string | Yes | completed, busy, no-answer, failed, canceled |
CallDuration | string | No | Call duration in seconds |
leadId | string | Yes | Lead ID (query param) |
campaignId | string | No | Campaign ID (query param) |
Escalate Conference (v6.0.0)
/api/webhooks/warm-transfer/escalate-conferenceOn-demand conference upgrade for supervisor listen/whisper/bargeUpgrades a direct 2-party call to a Conference when a supervisor needs to listen, whisper, or barge in. Gets both call SIDs from the lead record and redirects both legs into a new conference.
| Parameter | Type | Required | Description |
|---|---|---|---|
leadId | string | Yes | Lead ID — used to look up both prospect and SDR call SIDs |
Response:
{
"success": true,
"conferenceName": "escalate-abc123def-1711523456789",
"message": "Direct-dial call escalated to conference. Supervisor can now join."
}Retell AI Webhooks
/api/webhooks/retell/statusRetell call status updates/api/webhooks/retell/toolsRetell tool execution (hot_bridge_transfer, etc.)The tools webhook handles custom tool calls from the Retell AI agent, including hot_bridge_transfer (direct-dial bridge, v6.0.0), schedule_callback, and end_call. Uses Next.js after() to return the tool result in <200ms while executing all telephony/Pusher bridging in the background.
Resend Email Webhooks
/api/v2/webhooks/resendEmail delivery events (delivered, bounced, complained)Configuration
Setup guides for all third-party integrations.
Telephony Setup
Required environment variables:
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_PHONE_NUMBER=+15551234567
TWILIO_PHONE_NUMBERS=+15551234567,+15559876543
TWILIO_TWIML_APP_SID=APxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxThe TwiML App routes Device SDK calls to the /api/webhooks/warm-transfer/inbound-call webhook. All phone numbers must be configured with this same Voice URL for inbound call handling.
edge on the WebRTC SDK or region on Conference TwiML. Let the provider auto-select the closest edge server for optimal audio quality.Retell AI Setup
RETELL_API_KEY=key_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
RETELL_AGENT_ID=agent_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
RETELL_CONVERSATION_FLOW_ID=conversation_flow_xxxxxxxxxxxx
RETELL_FROM_NUMBER=+15551234567Configure your Retell agent with a conversation flow that includes the hot_bridge_transfer custom tool. The tool webhook URL should point to /api/webhooks/retell/tools.
Phone Numbers
| Parameter | Type | Required | Description |
|---|---|---|---|
Telnyx Numbers | PSTN | No | Primary outbound DIDs. Used for power dialing and AMD path via TeXML. |
Retell-Telnyx Numbers | SIP | No | Managed by Retell. Good for AI inbound/outbound. Cannot be redirected from your provider account. |
Custom (Imported) | SIP | No | Your Telnyx numbers imported into Retell. Best of both worlds — AI + redirect control. |
Email Accounts
Connect email accounts for sequence sending in Dashboard > Email Config:
- Resend API — Fastest setup. Add your Resend API key and verified sending domain.
- SMTP — Any SMTP server (Gmail, Outlook, custom). Requires host, port, username, password.
- Gmail OAuth — Connect via Google OAuth for Gmail sending without app passwords.
Email Campaigns (v7.0)
Complete email automation: from lead discovery to personalized campaign launch in 8 steps.
8-Step Campaign Wizard
Navigate to /dashboard/email-wizard to launch the campaign builder:
- Campaign Setup — Name, ICP profile, Campaign Brief selection for AI grounding
- Lead Generation — Apollo search OR CSV upload with enrichment
- Email Template — Tone selection (5 styles), template skeleton, sender info. Load from existing sequences.
- Sales Collateral — Attach whitepapers, case studies, ROI calculators
- Bulk Generation — GPT-4o generates unique personalized email per lead (up to 50/batch)
- Review & Edit — Inline edit each email before sending
- Mailbox Selection — Choose connected email account
- Launch — Campaign summary, go live, track in analytics
AI Intelligence Engine
The Intelligence Engine v2 generates personalized emails at scale using GPT-4o:
/api/email/bulk-generateBulk generate personalized emails- 5 Writing Tones: Formal, Casual, Assertive, Consultative, Educational
- Template Injection: Provide a skeleton with
{{name}},{{company}}placeholders - Campaign Brief Context: AI references uploaded PRDs and product docs for zero-hallucination emails
- Batch Processing: 5 leads per API call, up to 50 leads per run with progress tracking
AI Sequence Optimizer
Navigate to /dashboard/sequence-optimizer for AI-powered sequence analysis:
/api/v2/sequences/optimizeAnalyze sequence with GPT-4o and get recommendations- Performance Analysis: Evaluates subject lines, body content, timing, and follow-up cadence
- Prioritized Recommendations: HIGH / MEDIUM / LOW impact suggestions
- Predicted Improvement: Estimated uplift percentages for each recommendation
- One-Click Apply: Apply recommendations directly to your sequence
Email Account Setup
Configure sending accounts in Dashboard > Email Config. Four providers supported:
| Parameter | Type | Required | Description |
|---|---|---|---|
Resend | API Key | No | Fastest setup. Add API key + verified domain. Best deliverability. |
SendGrid | API Key | No | Enterprise-grade. API key + verified sender identity. |
Gmail OAuth | OAuth 2.0 | No | Google OAuth flow with refresh token. No app password needed. |
SMTP | Credentials | No | Any provider: host, port (587 STARTTLS / 465 SSL), username, password. |
Lead Generation
Multi-provider lead sourcing with inline API key management.
Apollo.io Integration
Connect your Apollo API key in Dashboard > Lead Gen > Providers to access:
- People Search: Filter by job title, industry, location, company size, seniority
- People Enrich: Batch enrichment of up to 25 leads per request with verified emails and phone numbers
- Campaign Wizard Integration: Search and enrich leads directly in Step 2 of the wizard
Provider Management
Manage API keys for multiple data providers:
/api/lead-gen/providersList connected providers/api/lead-gen/providersConnect a new provider (Apollo, ZoomInfo, Explorium)/api/lead-gen/providers/[id]Disconnect a providerCSV Upload
Upload leads via CSV in the Campaign Wizard (Step 2) or the Lead Gen page:
- Smart Column Parsing: Automatically maps
email,name/first_name+last_name,company,title,industry - Deduplication: Detects and skips existing leads by email address
- Enrichment: Optionally enrich imported leads via Apollo after upload
Production & Scaling
Ops tools for production readiness and SDR scaling.
System Health Check
/api/healthComprehensive system diagnosticsReturns granular status for all subsystems. Use as a daily pre-flight check before SDRs log in:
{
"status": "green", // green | yellow | red
"version": "7.3.8",
"services": {
"database": { "status": "ok", "latencyMs": 12 },
"telephony": { "status": "ok", "details": "Telnyx active. 12 DIDs, SIP connected, A-attestation." },
"retell": { "status": "ok", "details": "Agent: agent_xxx" },
"pusher": { "status": "ok", "details": "Cluster: mt1" },
"email": { "status": "ok", "details": "Providers: Gmail OAuth" },
"ai": { "status": "ok", "details": "OpenAI configured" }
},
"agents": { "total": 5, "available": 3, "busy": 2, "stale": 0 },
"scale": { "currentCPS": 5, "recommendedRatio": 3, "maxSDRs": 10 }
}Scaling to 10-50 SDRs
10 SDR Configuration (Phase 1)
| Parameter | Type | Required | Description |
|---|---|---|---|
Power Dial Ratio | 3x | No | 3 concurrent calls per SDR. 10 SDRs x 3 = 30 calls, spread over 6s at CPS=5. |
Provider CPS | 5 | No | Calls Per Second limit. Do not exceed. Staggered naturally by 3x ratio. |
DB Connection Pool | 15 | No | Append ?connection_limit=15&pool_timeout=30 to DATABASE_URL |
DID Pool | 40-60 | No | Phone numbers for rotation. Prevents spam flagging. |
Pusher Plan | Free/Starter | No | Free plan supports 200 concurrent connections (fine for 10 SDRs). |
Agent Heartbeat | 5s / 45s stale | No | SDR sends heartbeat every 5s. Stale after 45s missed. |
50 SDR Configuration (Phase 2)
| Parameter | Type | Required | Description |
|---|---|---|---|
Telnyx SIP | SIP | No | Direct Telnyx SIP routing. 50% PSTN cost reduction. |
DB Pool | 25 | No | Increase connection_limit to 25. |
Pusher Plan | Growth | No | Upgrade for 500+ concurrent connections. |
Cloud Run | min 2 instances | No | Prevent cold starts. Set min-instances=2 in GCP. |
Phase 1 Audit Results (v7.0.2)
Passed Checks
- API Key Token generation (SK-prefix) verified
- AMD async detection (DetectMessageEnd) active on all dial paths
- endConferenceOnExit=true on all conference legs
- No record:true on any calls.create()
- DNC check before every dial
- Stale lead auto-release before batch
- Agent heartbeat (5s) with 45s stale threshold
- Pusher fully configured (cluster mt1)
- Cross-campaign SDR routing isolation verified
Required Ops Actions
- DB Connection Pooling: Append
&connection_limit=15&pool_timeout=30to DATABASE_URL in GCP - Recording Strategy: Verify account-level recording or re-enable Conference recording
Changelog
The complete per-version breakdown lives in memory/CHANGELOG.md. The most recent v8.x releases are summarized below; deeper 7.x history follows further down.
v8.48.0 — August 2026 — DID reputation forecasts, rest lifecycle, bulk provisioning & org isolation
- Reputation & rotation forecasts. Every caller ID now shows its age, no-audio/gateway-strike signals, dials-per-day and a projected rotation date from a score-burn model — plus a floor-wide Non-Spam % KPI so the fleet's health is one glance.
- Rest lifecycle (cooldown, not release). Flagged numbers can be rested for 30 days — they stay owned (callbacks keep routing), leave rotation instantly, and return clean automatically once carriers age out the spam label. Auto-rest/auto-revive runs on a floor-guarded cron sweep.
- Bulk Purchase & Distribute. One admin action buys up to 200 numbers with an area-code spread matched to your lead geography, gives every SDR without a dedicated DID one, pools the rest, registers Voice Integrity, and puts everything through the 14-day warmup guard. Dry-run plan and explicit cost confirmation before any money moves.
- Workspace DID isolation. A workspace can only dial from numbers it owns or pooled ones — new orgs get a clear "buy numbers first" path (and a default pool at signup) instead of silently borrowing another org's caller IDs.
v8.47.0 — August 2026 — Network resilience for congested offices (low-bandwidth voice + dial protection + quality forensics)
- Low-Bandwidth Voice Mode. The browser softphone now negotiates Opus at 16 kbps (PCMU fallback) and pins media to the Singapore edge with roaming fallback — about a third of the wire bandwidth of G.711 with far better packet-loss concealment, sized for an India floor running ~20 SDRs × 3 lines on shared Wi-Fi.
- Network-aware dial protection. When the live network probe classifies the office connection as POOR, new Power Dial batches hard-pause (in-flight calls untouched) behind a red banner with live RTT/jitter metrics, and dialing auto-resumes the moment the connection recovers — no more burning leads on silent or dropping calls.
- In-call quality forensics. The Twilio SDK's live quality warnings (packet loss, jitter, high RTT, low MOS, ICE drops) are now logged per call to the forensics store — warnings clustering on one SDR point at their machine/Wi-Fi; floor-wide warnings point at the office uplink.
- Office IT Runbook. A one-page checklist for the office IT team (bandwidth math, wired-over-Wi-Fi, QoS for Twilio UDP media, SIP ALG off, dual-ISP failover) ships in the repo as
OFFICE_IT_RUNBOOK.md.
v8.44.0 – v8.46.1 — August 2026 — Floor-stability rollup
- Deterministic identity resolution (fixed silent calls / wrong-VM routing caused by duplicate roster rows), team-management authority fix for platform owners, DID reconciliation + gateway-failure auto-retry on manual dial, a no-audio detector with a per-DID 24h forensics card, the DID warmup guard (14-day window + daily cap for fresh numbers), and the SDR header Network Health pill.
v8.42.0 — June 2026 — Marketing site: expanded Platform & dedicated How-it-works + auth data-loss guard
- Public /features rebuilt and expanded (impact metrics, a "replaces your stack" before→after, a capability comparison checklist, and a go-live onboarding timeline) and a new dedicated /how-it-works page (anatomy-of-a-call timeline, non-human handling, a live-ops floor mockup and an FAQ). /resources and these Docs rebranded to the navy/red BeyondCalls theme.
- Auth data-loss guard. Returning users are now matched against ALL of their verified Clerk emails (not just the primary), so a Google / magic-link sign-in can never drop an existing user into a new empty workspace and hide their historical call logs and campaigns.
v8.41.0 — June 2026 — Landing redesign (light + dark editions)
- The landing page was rewritten around the AI-workforce positioning with a fully theme-responsive dark (near-black navy) and light edition, a live-ops hero mockup, and the "Dial → Detect → Verify → Bridge" narrative.
v8.40.0 — June 2026 — Public auth + isolated tenants
- Trusted email domains join the main organization; every other authenticated email is provisioned an isolated workspace (their own Organization, scoped reads only) instead of hitting a request-access dead-end. Kill-switch via
PUBLIC_ISOLATED_SIGNUP=false.
v8.39.0 — June 2026 — AMD dead-air hang-up fix
- Tightened AMD end-of-speech thresholds so a verified human is bridged ~0.4–0.8s faster — closing the trailing dead-air gap that made prospects hang up right after "hello".
v8.37.0 — June 2026 — Power-dial race fix + global outbound dialing
- Fixed a call-status race that stranded leads at
completed+attemptNumber=0(dropping them from every dial pool), enabled outbound dialing to 21+ countries, and added country flags + local-time calling windows for international prospects.
v8.34.0 — 2026 — Multi-country dialing foundation
- Additive groundwork so a mixed-country list (India + UK + US + AU) can be uploaded, previewed and safely dialed: phone-country detection, per-campaign coverage checker, and country-matched DID selection.
v8.33.0 — 2026 — SDR profile: campaign roster + inbox deep-links
- SDRs can now see every campaign they've touched (including cancelled/archived), with per-SDR stats and deep-links from a voicemail disposition straight to playback in My Inbox.
v8.32.3 — July 17, 2026 — Power Dial session stats + pop-up never freeze (React batching fix)
- The recurring "dashboard stats are frozen" SDR bug is fully fixed. v8.32.1 keyed the dedupe correctly by
callSidand passed its unit test, but the pop-up and top-strip still froze in production. Real root cause: React 18 automatic batching. Three call sites replace the power-dial feed with a filter that drops terminal legs (batch response, Pusherpower-dial-started, and the implicit intermediate step when a terminal Pusher update lands in the same tick). React merges multiplesetPowerDialFeedcalls in one event-loop tick into ONE commit — so the intermediate render (leg = voicemail) never happens and the feed useEffect that counts terminals never sees the transition. The dial IS placed and the DB records it, but the client-side totals sit frozen because the very legs that would have incremented them were filtered out one microtask before the effect could count them. - Fix (defence-in-depth): the two feed-replacement filters now KEEP a terminal leg unless
countedCallSidsRefalready accounts for it — the useEffect gets a guaranteed render tick to count it before it's dropped on the next batch. Filters stay pure (ref reads only) so React concurrent rendering can never double-count. The Pusherpower-dial-lead-updatehandler also refreshes the leg'scallSidwhen the payload carries a new one (retell / carrier retries) so the callSid dedupe stays correct on redials.sessionStartAtand the effect body itself (v8.32.1) are untouched. tests/test_v8323_stats_never_freeze.ts 13/13.
v8.32.2 — July 16, 2026 — New SDR disposition "No Longer Works" (NLWH)
- Wires NLWH end-to-end as a terminal / wrong-person disposition (semantically identical to NTRP/WN — a human answered but the target has moved on from the company we're dialing). Aliases
no_longer_works/no_longer_works_here/no-longer-worksnormalize to NLWH. Classifies ashuman_connected, never re-dialed (terminal + restart-terminal + human-disposition membership).
v8.32.1 — July 16, 2026 — Power Dial banner stopped freezing after cool-off (v1)
- Two independent bugs made the persistent banner look frozen once a session survived a cool-off: session counters keyed by
leadId(a re-dialed lead was already in the set → skipped) and the elapsed timer resetting on every batch (feed-min derivation). Fixed by dedupe-by-callSid and a persistentsessionStartAt. See v8.32.3 for the React-batching follow-up that closes the residual production freeze.
v8.32.0 — July 16, 2026 — Analytics: VMs demoted from "Human Connects — Proof"
- When AMD confirmed a machine AND the classifier's raw code is the ambiguous
CONNECTED(no SDR-set disposition), the row is now demoted to voicemail in the drill-down, the reconciliation summary and the CSV. Explicit SDR dispositions (MF/QUAL/CB/FUP/NI/…) are never touched — the SDR was the human on the call, AMD was wrong. Overview stat cards, SDR leaderboard and recordings unchanged.
v8.31.0 — July 15, 2026 — Meetings drill-down
- Click the "Meetings Booked" stat card on Analytics → Overview to open an audit table of every meeting booked in the period: SDR, prospect (name/phone/company), campaign or "Manual dial", when the meeting is scheduled, the SDR's notes, and the call recording played inline. Manual-dial meetings matched via the same-agent nearest-in-time recording.
v8.30.1 — July 15, 2026 — Meetings-booked undercount fixed
- Meetings are now counted from the disposition EVENT log (the same source of truth the SDR dashboard uses), deduped per lead/call. Manual/direct dials (no
leadId) are counted, and an MF set today on a lead dialed days earlier is attributed to today — not the dial date.
v8.30.0 — July 15, 2026 — Recording reconciliation sweep + Drop Analysis
- Recording reconciliation. New hourly cron treats Twilio as the source of truth: missing rows are created, misattributed rows are re-attributed (dialed-number match), untouchable rows are left alone. Conservative by design — nothing is guessed.
- Drop Analysis page (Operations → Drop Analysis): per-SDR drop rate, Twilio error-code breakdown, recent-drops feed. Built on the new
CallDisconnecttelemetry captured on every SDR softphone call end.
v8.29.0 — July 15, 2026 — On-screen disconnect reasons + manual-dial recording attribution
- The telephony device now classifies every call end (network/media ERROR with Twilio error code translated to plain English, LOCAL, or REMOTE) and the reason renders on the wrap-up screen. Abnormal drops also fire an immediate toast so "my call randomly disconnected" tickets become self-explanatory.
- Manual-dial recording attribution: the voice webhook now resolves the dialing SDR from the client identity and passes org + agent + dialed phone to the recording callback → correct lead in the SDR's org (blind "most recent lead" fallback disabled for direct dials).
v8.28.0–v8.28.2 — July 15, 2026 — Continuous-pipeline power dialer overhaul
- Pipeline refill — resolved legs are topped up immediately while siblings still ring (no more "whole batch pinned to the slowest leg").
- DB polling fallback —
GET /api/warm-transfer/power-dial/statusresolves legs even when Pusher events are dropped (previously stalled every such batch to the 40-45s watchdog). - Pause-aware watchdog — the 5s watchdog now respects the server-directed cool-off window instead of hammering the API and re-firing the "cooling off" toast every 10s.
- Stuck-lead reaper — leads whose terminal webhook was lost are auto-recycled after 10 minutes so first-pass coverage is complete.
- Persistent SDR banner with engine state (DIALING/PAUSED with a countdown/QUEUEING), first-pass coverage progress bar ("X/Y leads dialed at least once"), live dials/min and session totals.
- Stale-claim arbitration (v8.28.2) — an
AgentPresencerow pinned to a dead Twilio CallSid is healed with an atomic conditional update so batches can never 409 forever.
v8.26.0 — July 13, 2026 — Per-SDR atomic bridge lock
- The AMD winner path now claims the SDR presence conditionally (only if not on another live call); a colliding bridge INVITE is ended, the lead requeued (+30 min cool-off), and the SDR presence released. Root cause of the "VM greeting playing mid-conversation" + "wrap-up at 0:02 mid-call" + wrong-prospect identity reports.
Historical v7.x release notes follow below.
v7.6.8 — June 1, 2026 — Inbound-calls voicemail playback ("Missing recording SID") fix
- "Missing recording SID" on the Inbound Calls page. The
/api/inbound-callsAPI built the player URL with the wrong query param (?recordingSid=instead of?sid=), so the recording SID never reached the stream route. The recording itself was fine — only the URL was malformed. Surfaced (not caused) by the v7.6.6 inline error surfacing. Guard test added so the wrong param can't return.
v7.6.7 — June 1, 2026 — Recording Health (admin drift detector)
- Recording Health card on
/dashboard/admin/dial-errors— a read-only, per-provider (Twilio/Telnyx) check that pings the most-recent recording to verify it's actually fetchable with this environment's credentials, catching deployed-env credential drift before an SDR hits a dead player. Per-provider badges (Playable / Failing / Not configured / No recordings) with sample SID, HTTP status, latency, and the exact error. - New
GET /api/admin/telephony/recording-health. Deliberately separate from the playback path —/api/v2/recordings/streamand the calling path are untouched. 11/11 invariants + a live probe of the real Twilio voicemail returned ok.
v7.6.6 — June 1, 2026 — Recording/Voicemail Playback Permanent Fix
- Recordings/voicemails wouldn't play (greyed out at 0:00 / 0:00) in the deployed app. The v7.6.5 HTTP-Range fix targeted the wrong layer. A native
<audio src>doesn't carry the Clerk bearer token through the Cloud Run proxy →401→ silent grey-out. - Fix: a shared authenticated loader attaches the bearer token and plays from an in-memory Blob, and a reusable
<RecordingPlayer>now surfaces the exact error inline + Retry so it can never silently fail again. Rolled out to My Inbox voicemails, inbound-calls, the recordings library, warm-transfer recordings, and coaching. 10/10 + regression 8/8.
v7.6.5 — June 1, 2026 — Wrong-Prospect Fix (permanent) + Voicemail Playback Fix
- Wrong prospect on connected power-dial calls (permanent fix). During a live call the desktop + CRM panel could show a different prospect than the one on the line. The confirmed-winner guard now covers every
activeLeadwrite path (a centralised gated setter), the winner is reset when a new batch dials (so back-to-back batches never show the previous prospect), and the bridged call's ownleadIdis treated as authoritative. - Voicemail playback. Voicemails in My Inbox (and the missed-callbacks player) now play correctly — the recording stream proxy implements HTTP Range / 206 Partial Content (Chrome's
<audio>requires it) for both Twilio and Telnyx.
v7.6.4 — May 31, 2026 — My Inbox: SDR Voicemail Box + Unified Activity Dashboard
- Every SDR gets a personal inbox. New
/dashboard/my-inboxworkspace with two tabs — Voicemails and My Activity. Voicemail boxes are now fully active for dedicated DIDs. - Voicemails — voicemails left on the DIDs you own (lead/company/title, caller, DID, time, duration) with an inline recording player + transcript, an editable Notes field, a Mark resolved toggle, and a Schedule callback action that books a meeting for the prospect and resolves the voicemail.
- My Activity — a single, filterable disposition log of meetings booked, voicemails received, and dispositions set — each row carries the CRM customer details (name, company, phone, email, campaign). Filter by type / campaign / date-range / meeting-status with one-click CSV export.
- New
GET/PATCH /api/me/voicemails,POST /api/me/voicemails/schedule-callback,GET /api/me/activity.InboundCallLoggained anownerNotescolumn. 11/11 invariants.
v7.6.3 — May 29, 2026 — My Missed Callbacks (SDR surface + badge + toast)
- SDRs never lose a missed callback. New "My Missed Callbacks" section on the Inbound Calls page, scoped to DIDs you own — shows prospects who rang back while you were offline, with lead/company, caller, DID, time, an inline recording player, and a one-tap Call back button.
- Sidebar badge on "Inbound Calls" showing a live count of your unresolved missed callbacks, plus an on-login toast nudge the next time you come online.
- A missed callback auto-clears once you call back and log a disposition. 100% additive + read-only — no telephony or schema changes. 7/7 invariants.
v7.6.2 — May 29, 2026 — Callback Won-Back Attribution & ROI Leaderboard
- Prove the ROI of warm callbacks. When a rep dispositions a lead, the outcome is auto-attributed to a recent inbound dedicated-DID callback (within 3h). Positive outcomes (meeting booked / qualified) flag the callback as won back.
- Callback ROI card on the Admin SDR-DIDs page — total callbacks, won-back count, conversion %, and an estimated pipeline figure (won-backs ×
CALLBACK_MEETING_VALUE_USD, default $1,500), plus a "Callbacks Converted" leaderboard. - New
GET /api/admin/sdr-did-assignments/attribution.InboundCallLoggained disposition + won-back attribution columns. 10/10 invariants.
v7.6.1 — May 29, 2026 — Callback SLA + Auto-Assignment & DID Webhook Auto-Config
- Never drop a callback. When a prospect rings back a dedicated DID and the owning rep is offline, the callback is auto-assigned to the next available rep on the same campaign (with the same Warm Callback context) instead of going to voicemail.
- Voicemail is the last resort — only when no campaign-mate is online — and now raises a
callback_missedSystemAlert for supervisors. SLA target is configurable viaCALLBACK_SLA_SECONDS(default 60s). - Supervisor "Dedicated-DID Callbacks" badge on Live Ops shows how callbacks were handled (owner / fallback / voicemail) in the last hour and flags SLA breaches (
GET /api/admin/diagnostics/callbacks-waiting). The Warm Callback banner shows a "Covering — originally the owner's prospect" note on fallback calls. - Auto-configure on assignment — assigning a DID (manual or auto-distribute) now points its Twilio Voice webhook at the inbound handler automatically; no manual "Configure for Warm Transfer" step. 11/11 E2E invariants.
v7.6.0 — May 29, 2026 — SDR Dedicated DIDs (Phases 1–3)
- Every rep gets their own callback number. Map Twilio DIDs 1:1 to SDRs so a prospect calling back lands on the exact rep who dialed them, with full CRM context.
- Phase 1 — assignment engine — new
SdrDidAssignmentmodel (partial unique index enforces one active assignment per number); assign / unassign / list APIs +auto-distribute(sticky round-robin, lead-weighted, geographic) with dry-run preview and a "need more DIDs"SystemAlert. Fixed the P0 compile blocker (query referenced 4 fields that don't exist in the schema). 13/13 invariants. - Phase 2 — Admin console — new
/dashboard/admin/sdr-didspage (stats, DID-shortage banner, Auto-Distribute preview → apply, assignments table, SDR roster, Assign dialog) +overviewAPI + Sync Twilio Numbers importer to pull your existing Twilio inventory into the assignable pool. - Phase 3 — Inbound recognition + Warm Callback — the inbound webhook routes a callback on a dedicated DID to the assigned rep's browser (conference) when online, else voicemail + a missed-callback ping. The SDR Desktop shows a Warm Callback banner — "calling back X · last dialed by Y on Z" + prior disposition/notes — with one-tap "Resume — use last notes." Usage tracked per assignment. 9/9 E2E HTTP invariants.
- Did not touch the tuned WebRTC /
TWILIO_ONLY_MODE/ power-dial race logic — Phase 3 adds an inbound branch + an additive SDR banner only.
v7.5.31 — May 19, 2026 — Docs Sync & Version Bump (Consolidates v7.5.25 → v7.5.30)
- Pure documentation release — no source-code changes. All 7 release surfaces (version.ts, docs/CHANGELOG.md, memory/CHANGELOG.md, memory/PRD.md, memory/ROADMAP.md, README.md, public/user-guide.html) brought back into lockstep on v7.5.31.
yarn release --check✅ GREEN. - README "What's New" body had stuck at v7.5.24; PRD title at v7.5.25; in-app
/docsheader at v7.5.25 — all fixed.
v7.5.30 — May 19, 2026 — "Best Ratio?" Data-Backed Hint + Provider-Agnostic Connect Toast
- NEW UI —
RatioInsightHint.tsxsurfaces a tiny analytics pill under the SDR ratio picker with a one-click APPLY when a clear historical winner exists. Renders 4 states: brand-new campaigns (nothing), <100 dials (progress bar), no clear winner (muted text), clear winner (amber pill + click-to-expand bar chart). - NEW BACKEND —
GET /api/warm-transfer/campaigns/[id]/ratio-analytics: CTE-backed SQL joiningPOWER_DIAL_STARTEDevents withWarmTransferLead.powerDialGroupId, grouped by ratio. Recommendation gated on total ≥100 dialed, ≥2 ratios with ≥20 samples each, winner > next-best by ≥3 pp. Tie-break: lower ratio wins. - UX — Telephony connect toast made provider-agnostic. "Phone connected via Telnyx" → "Your phone is now connected, you can make and receive calls".
v7.5.29 — May 19, 2026 — Sticky preferredDialRatio per Campaign
- NEW — Reps lock a default 1x–5x ratio per campaign (Enterprise discovery = 1x, SMB outbound = 3x). Auto-applies on campaign select; debounced (800ms) save on ratio change. Dot indicator on the ratio button matching the saved default.
- SCHEMA —
WarmTransferCampaign.preferredDialRatio Int?(nullable 1–5). Migration applied additively to live DB. - BACKEND —
PATCH /api/warm-transfer/campaigns/[id]acceptspreferredDialRatioin body. 400 on invalid (outside 1–5).
v7.5.28 — May 19, 2026 — Power Dial 2-Row Layout + BC Clerk Reskin
- FIX (UX) — 3x / 4x / 5x ratio buttons were unclickable because the Power Dial control row overflowed the 300–340px campaigns column. Redesigned into 2 rows: ROW 1 = primary action (Power Dial / Stop / icon-only Force Hangup), ROW 2 = labeled "RATIO"
grid-cols-5grid that always fits the column. Every ratio button now clickable at any panel width. - NEW —
aria-pressed+aria-labelon every ratio button; primary action truncates with ellipsis on collapse. - BC BRANDING — Full beyondcalls.ai reskin of Clerk via
<ClerkProvider appearance={...}>. BC logo, brand red (#B31942) primary, dark navy surface, Open Sans typography across sign-in / sign-up / UserButton / UserProfile.
v7.5.27 — May 19, 2026 — Recent Disconnects Pill (SDR Self-Diagnostic)
- NEW UI — "Recent disconnects" pill in the SDR header surfaces the last 3 phone-bridge drops in 24h. Reps self-diagnose flaky wifi vs. browser tab-throttling without raising a ticket. Click opens popover with reason, hint, device state, and call state at the time of the drop. Escalating advisories: 2+ drops → "switch network", 3+ → "restart browser before next shift".
- NEW BACKEND —
POST/GET /api/warm-transfer/agent/device-disconnectlogs structured events with a reason whitelist. Piggybacks on existingWarmTransferEventtable — zero new schema.
v7.5.26 — May 18, 2026 — Silent Power Dialer Stall Fix (P0, Reported by Live SDR)
- FIX (critical) — "Power dialing automatically stopped" with no clear reason. Root cause: silent Twilio WebRTC device disconnect → power-dial churned through 10 "No agents" retries (~70s exponential backoff) before stopping with an easily-missed toast. Twilio account, Telnyx account, and 60/40 load balancer were all verified healthy at the time — purely a UX/state-coordination bug.
- INSTANT HALT — Auto-dial stops the moment
isAvailableflips false. No more 70-second silent retry storm. - VISIBLE OFFLINE BANNER — Persistent in-UI banner above the SDR Desktop main pane fires whenever
isAvailable=falsewhile a campaign is selected and dialer is IDLE. One-click Go Available button restores availability. - CLEARER STOP TOASTS — All terminal Power Dialer stop toasts now persistent (
duration: Infinity) with manual Dismiss action and explicit root-cause language.
v7.5.25 — Feb 14, 2026 — Multi-Phone Per Lead + CSV Upload Validation
- NEW — Each lead can carry up to 3 phone numbers (primary + 2 alts). On non-success dispositions (NA / BUSY / VM / WN / NTRP / NLW / NI / LHU) the disposition route promotes the next alt to
phoneand queues it for the next batch. Success / callback / DNC stop the chain. DNC propagates across ALL known numbers per lead. - CSV UPLOAD — Accepts
Phone / Phone 2 / Phone 3ANDMobile / Office / Home / Directconventions. E.164 + NANP validation per phone. Inline failures editor lets the SDR fix bad rows and re-upload as JSON. - SCHEMA —
WarmTransferLead.alternatePhones String?(JSON array, capped at 2 alts) +WarmTransferLead.triedPhones String?(audit trail). Both nullable, additive.
v7.5.24 — May 13, 2026 — Channel Limits Aligned with Actual 5 CPS Carrier Plans
- INFRA SAFETY — Channel limits in
cloudbuild.yamlreduced (Twilio 15→5, Telnyx 10→5) to match the actual 5 CPS carrier plans. Prevents 30443 / D1 90041 / 429 rate-limit errors. - AUDIT — DID inventory, Programmable Voice, AMD, Strategy-tab gap analysis delivered alongside (see PRD v7.5.24).
v7.5.23 — May 13, 2026 — Telephony Load Balancer: 60/40 Twilio/Telnyx Target-Split (Production-Enabled)
- NEW —
TELEPHONY_TARGET_SPLITenv var (e.g.twilio=60,telnyx=40) gives a stable, predictable carrier mix regardless of momentary in-flight counts. 10,000-dial simulation: 60.5% Twilio / 39.5% Telnyx, 0.47% drift from target. - ENABLED IN PRODUCTION —
_TELEPHONY_LOAD_BALANCEflippedfalse → trueincloudbuild.yaml. Backward-compatible: whenTELEPHONY_TARGET_SPLITis unset, behavior falls back to legacy free-slot weighting (v7.5.8). - SAFETY — AMD & latency untouched (per-call provider config). Capacity-safe (0-free-slots excluded, both-saturated → least-loaded). Sticky retry + US-only
DIAL_ALLOWED_REGIONSintact. Fully reversible via_TELEPHONY_LOAD_BALANCE='false'. - DID RECOMMENDATION — At 4 Twilio DIDs vs 12 Telnyx, the 60% Twilio share concentrates frequency. ≤5 SDRs: fine. 5-10 SDRs: purchase 6-8 more Twilio DIDs. 20+ SDRs: scale to 20+ Twilio DIDs and renegotiate CPS limit.
v7.5.22 — May 13, 2026 — "Find a Recording by Phone" Diagnostic Tool
- NEW —
/dashboard/admin/dial-errorsnow has a "Find a recording by phone" tool. Paste any phone format → get a definitive answer to "does this recording exist anywhere?" - ENDPOINT —
POST /api/admin/recordings/find-by-phone { phone, sinceDays? }. Queries Twilio Calls API, Telnyx Recordings + Call APIs, and the local DB independently. - VERDICT —
FOUND/CALLS_EXIST_NO_RECORDING/NO_CALLSwith per-provider breakdown and a Play button on every recording (via the existing/api/v2/recordings/streamproxy). - SAFETY — Telnyx call-leg lookups concurrency-pooled at 5 to stay under rate limits. Reuses
phoneMatchVariants,getOrCreateTeamMember, Clerkauth(). No new deps.
v7.5.21 — May 13, 2026 — Telnyx Recordings Were Invisible (Three Compounding Bugs)
- P0 SYMPTOM — Telnyx recordings (the now-default carrier for many leads after sticky-carrier v7.5.10) never appeared on
/dashboard/recordingsvia any search. - RCA — three compounding bugs in
src/app/api/v2/recordings/route.ts:- Single-provider gate — auto-sync + Sync Now pulled from only ONE carrier via
getActiveProvider(). Sticky-carrier-per-lead routes through both → half the recordings invisible. - Denorm missing —
syncTelnyxRecordingsset only FKs, never the display columns the list UI reads (leadName/leadPhone/company/agentName/campaignName/disposition). - No phone fallback — when
warmTransferEvent.callSidlookup missed, orphans stayed orphan withleadPhone=null→ v7.5.20 re-linker couldn't help.
- Single-provider gate — auto-sync + Sync Now pulled from only ONE carrier via
- FIX — (1) Both sync paths pull from BOTH providers in parallel (
Promise.allSettled). (2)syncTelnyxRecordingsjoins to lead + agent and denormalizes the full display columns. (3) Strategy-2 fallback queries Telnyx Call API forto/fromand matches viaphoneMatchVariantswhen Strategy 1 misses. PersistsleadPhoneeven when no match so the v7.5.20 re-linker can pick it up later. - RECOVERY — Deploy →
/dashboard/recordings→ Sync Now → search by name / company / any phone format. Optional: re-link orphans on/dashboard/admin/dial-errors.
v7.5.20 — May 13, 2026 — One-Click Orphan Recording Re-linker (Admin Tool)
- NEW —
/dashboard/admin/dial-errorsnow has an Admin Tools card with Preview (dry run) + Re-link orphan recordings buttons. BackfillsCallRecordingrows that were persisted withleadId=nullby the pre-v7.5.19 strict-equality phone match. - ENDPOINT —
POST /api/admin/recordings/relink-orphans?dryRun={true|false}&limit=N. - SAFETY — Org-scoped · idempotent (only scans
leadId IS NULL) · conservative (skips ambiguous multi-lead phones — never guesses) · atomic batches viaprisma.$transaction· disposition-safe (manual dispositions never overwritten) · bounded (5k rows/run, max 20k via?limit=). - TECH-DEBT AVOIDANCE — Reuses
phoneMatchVariants,getOrCreateTeamMember, Prisma, Clerkauth(), existingCard/Badge/toastprimitives. No new helpers, no new dependencies.
v7.5.19 — May 13, 2026 — Recordings Lost to Phone-Format Mismatch
- P0 — Real human-conversation recordings were syncing into the DB but surfacing as unknown lead on
/dashboard/recordings, unfindable by name / company / phone search. Reported example: meeting booked with Stephen Silveira / Aptus Court Reporting /(619) 546-9151. - RCA —
src/app/api/v2/recordings/route.tsmatched the Twiliocall.toE.164 (+16195469151) againstWarmTransferLead.phonewith strict string equality. CSV leads stored as(619) 546-9151failed to join → row persisted withleadId/leadName/company = null. Search by name "Silveira" or company "Aptus" then never hit it. The search filter onleadPhoneusedcontains:, which also didn't bridge raw-digit ↔ formatted forms. - FIX — All three lookups (
syncTwilioRecordings,syncCallRecordings'sphoneToLeadindex, and the?search=filter) now usephoneMatchVariants(). Any of6195469151/(619) 546-9151/+16195469151/+1 619 546 9151hits the same row. - RECOVERY —
/dashboard/recordings→ Sync Now → search by name, company, or any phone format. Or open the lead in/dashboard/sdr→ 360 Report → recordings tab (lookup byleadIddirectly).
v7.5.18 — May 13, 2026 — Disposition Window Auto-Skip Fix (Power Dialer Was Racing the SDR)
- P0 — Power-dial call ends →
DispositionFormopens → SDR starts typing notes / opens Schedule Meeting → 30s later the form vanishes and the Power Dialer fires the next batch. No disposition saved, no meeting logged. - ROOT CAUSE — Hard-coded 30s
setTimeoutin the WRAP_UPuseEffect(src/app/dashboard/sdr/page.tsx) calledresetCall()unconditionally →callState=IDLE →usePowerDialer[callState]resume effect fired the next batch 1500ms later. - FIX #1 — WRAP_UP idle window bumped 30s → 5min.
- FIX #2 — Idle timer now resets on every SDR interaction with the form: disposition click, notes keystroke, callback date, meeting form toggle, every meeting field, action item add/toggle. Implemented via a
wrapUpActivityTokenstate + anonActivityprop wired into every interactive control. - FIX #3 — DispositionForm shows a "Power Dialer paused — take your time to set disposition & schedule a meeting" pill when Power Dial is active.
- NOTE — Meeting scheduling (title / datetime / attendee / duration / notes →
POST /api/warm-transfer/disposition→Meetingmodel +.icsdownload) was already wired end-to-end. This fix simply makes sure the SDR has time to use it.
v7.5.17 — May 12, 2026 — Inbound Visibility + CRM Self-Heal + Clickable Version
- NEW PAGE —
/dashboard/inbound-callshub. Every incoming call with caller phone, DID it landed on, matched lead, handler (SDR/AI), status, duration, inline recording playback, AI summary, full transcript, and a "Callback Requested" badge. Stats cards and filters. Linked from sidebar under Telephony → Inbound Calls. - NEW UI — Direction-aware INCOMING screen. Inbound = PURPLE-themed pulsing hero with
↓ Inbound Callbanner,Calling from: <phone>label, "Landed on: your DID" tag. Outbound = green-themed↑ Outbound TransferwithConnecting to: <phone>. Unmatched callers show amber "Unknown Caller" + "No matching lead". - NEW UI — Sidebar version (
v7.5.17 ↗) is now a clickable link to/docs#changelog— review the issues fixed in your build with one click. - P0 — Phone-normalized lead lookup. "Unknown caller" was firing for leads that EXIST in the DB because phone formats didn't match exactly. New
phoneMatchVariants()generates 4-6 plausible formats (E.164, 10-digit, formatted) and OR-matches them. - P0 — SDR self-heal effect. Whenever
activeLeadis in the "unknown-<phone>" fallback state, frontend auto-calls/api/leads/lookup-by-phoneand upgrades within ~200ms. - NEW —
GET /api/leads/lookup-by-phone,GET /api/inbound-calls. AMDhuman-confirmedPusher events enriched with leadPhone/Email/Title.
v7.5.16 — May 12, 2026 — CRM Persistence + Inbound/Outbound Badge + Audio Diag
- P0 — Power Dial sibling voicemail events no longer kill the WINNER call. v7.5.7 guard required
callState === CONNECTED, but sibling Pusher events arrive during the 200-800ms INCOMING window before SDR auto-accept. New guard usespowerDialFeedRefto identify any in-batch sibling and ignore its events while state is non-IDLE. - P0 — CRM panel ALWAYS populated when a call connects. Previously
setActiveLeadwas gated byif (transferData.leadId). Inbound-to-DID + outbound transfers without enriched leadId left CRM blank. Now falls back to{ id: 'unknown-<phone>', name: 'Unknown caller', phone: from }. - P0 — "SDR not connected" mid-batch — heartbeat staleness check raised from 45s to 120s. Chrome throttles
setIntervalduring heavy WebRTC, letting the 5s heartbeat drift. Frontend now also fires a pre-batch heartbeat right before each power-dial trigger. - P0 — Telnyx double-recording — every call produced 2 rows in
/dashboard/recordings. Account-level "Record All Calls" on Telnyx + Conference TwiMLrecord="record-from-start"both fired the recording-status webhook with different recordingSids. Fix: gated conference recording behindTELNYX_USE_CONFERENCE_RECORDINGenv (default OFF). Defense-in-depth: recording-status webhook detects same-(leadId,callSid) duplicates within 5min and keeps only the longer one. - NEW UI — INBOUND vs OUTBOUND badge in Active Call header (purple ↓ vs emerald ↑).
- NEW UI — LEAD PREVIEW fallback panel showing caller phone + direction + "no matching lead" hint when no DB match.
- NEW — Outbound WebRTC audio-track diagnostic at
call.on('accept')→/api/diagnostics/audio-state→WarmTransferEvent. RCA-able offline. - NEW PAGE —
/dashboard/admin/dial-errors. Twilio code badges, time/provider filters, expandable rows. - IMPROVED — Power-dial backoff (2s → 30s) on ALL batch failures + auto-stop after 5 consecutive fails. Telnyx HTTP 403 detection broadened.
DIAL_ALLOWED_REGIONSenv filter (default1= US/Canada).
v7.5.15 — May 11, 2026 — US-Only Region Filter + Dial Error RCA Page
- NEW —
DIAL_ALLOWED_REGIONSenv var (default1= US/Canada/NANP only). Non-allowed leads are pre-filtered at lead-selection and bulk-marked CONFIG_ERROR so they stop cycling back every batch. Use*to disable, or1,44,61for US+UK+AU. - NEW PAGE —
/dashboard/admin/dial-errorsfor telephony RCA. ReadsLOG_ERROR_*rows fromWarmTransferEventwith Twilio-code badges (D1=red, auth=red, TwiML=amber). - IMPROVED — Power-dial frontend exponential backoff on ANY dial failure (not just "No agents"). 5 consecutive fails → auto-stop with hint to admin/dial-errors.
- IMPROVED — Telnyx 403 detection broadened. Any 403 / "country not allowed" / "outbound voice profile" marks lead CONFIG_ERROR and clears
lastDialedProvidersticky-pref.
v7.5.14 — May 11, 2026 — Documentation Backfill + Version Sync
- Pure docs release — zero source code changes. Resolves drift across 3 documentation surfaces.
docs/CHANGELOG.md— Renamed the mislabeledv7.5.2block (its body actually described the AMD False-Positive fix) →v7.5.3. Inserted 8 missing 7.x entries: v7.5.7, v7.5.1, v7.0.6, v7.0.5, v7.0.4, v7.0.3, v7.0.2. Now continuous from v7.5.13 → v7.0.0. Count: 47 → 55.src/app/docs/page.tsx(this page) — Was stuck at v7.3.8. Added 17<h3>blocks (v7.5.13 → v7.5.0, v7.4.1, v7.4.0, v7.3.9, v7.0.6, v7.0.5) plus this v7.5.14 entry.README.md— Title and version badge bumped (were stuck at 7.5.2 while "What's New" body had been updated to v7.5.13).- Audit —
node scripts/release.js --checknow validates 7 surfaces and confirms entry-count parity. All GREEN. - Verified —
yarn type-checkGREEN, regression 16/16 (no source changes).
v7.5.13 — April 21, 2026 — Duplicate Recording Fix (CRITICAL)
- CRITICAL: Duplicate Recording Fix — Every call was producing TWO recording entries playing back as overlapped audio. Both dial routes set
conferenceRecord: 'record-from-start'on participant create AND immediately calledconferences(sid).update({ record: true })— Twilio happily started a SECOND recording. Removed the redundant trigger indial/route.ts,power-dial/route.ts, and neuteredstartConferenceRecording()in the AMD callback. - LOGGING — Added
[AMD/AgentDial] conf=X agent=Y provider=Zline on every agent-into-conference dial. Grep Cloud Run logs for[AMD/AgentDial]to diagnose any future audio mismatch in seconds.
v7.5.12 — April 21, 2026 — One-Way Audio + Missing Recordings (P0 CRITICAL)
- Symptom — SDR saw "call connected", REC indicator and timer running, but NO voice from the prospect's end. Recordings later showed the call but audio was empty.
- Root cause —
amd-callback/route.tsused the GLOBALgetActiveProvider()when adding the agent to the conference and controlling recording. After v7.5.8 (load balancer) + v7.5.10 (sticky carrier) introduced per-lead provider variance, the prospect could be in a Telnyx conference while the agent was added to a Twilio conference of the same name — two separate conferences on two different switches. - Fix —
dialAgentIntoConference()andstartConferenceRecording()now accept an explicitproviderparameter. AMD callback readslead.lastDialedProvider(v7.5.10 column) at all 5 call sites. Three-layer fallback:lastDialedProvider→customData.dialProvider→ global. Agent ALWAYS joins the SAME provider conference the prospect is in. - iPhone VM redirect —
calls(callSid).update({ twiml })now also uses the per-lead provider so the SDK targets the correct switch.
v7.5.11 — April 21, 2026 — Permanent Build-Failure Prevention
- CRITICAL BUILD FIX — Cloud Build
bd6ecd2d-...failed with TS7016 "Could not find a declaration file for module 'uuid'". Root cause:uuidwas being imported but neitheruuidnor@types/uuidwas inpackage.json— resolving transitively at runtime but with no type declarations. - FIX — Replaced
import { v4 as uuidv4 } from 'uuid'withimport { randomUUID } from 'crypto'(Node 20 native). Removes the dep entirely — no future@typesbreakage possible. - PERMANENT GUARD — New
scripts/check-untyped-imports.jswalks every staticimportinsrc/, verifies each module is either a Node built-in, declared inpackage.jsonwith type declarations, or has its own.d.ts. Runs in ~0.3s. - PIPELINE — Added
prebuildscript —yarn buildnow runscheck-imports && type-checkBEFOREnext build. Cloud Build fails fast at the import-check stage (~0.3s) instead of 30+s into Turbopack. Husky pre-push hook updated to run both checks.
v7.5.10 — April 21, 2026 — Sticky Carrier per Lead
- NEW: Per-Lead Sticky Carrier — Added
lastDialedProvidercolumn toWarmTransferLead. Every successful dial stamps the carrier that placed it; retries reuse it viapreferProvider, preserving per-destination answer-rate reputation each carrier has built. - WIRED — Single dial reads
lead.lastDialedProviderand passes it as sticky-pref toselectProviderForCall. Power Dial computes majoritylastDialedProvideracross the batch and passes it as sticky-pref. - WRITE-SIDE — All 4 success paths (Retell, native Twilio/Telnyx, Twilio failover for D1) stamp
lastDialedProvideron success. - MIGRATION —
prisma/migrations/20260421000001_add_last_dialed_provider/— nullable column + optional index. Zero-downtime (NULL = no sticky preference).
v7.5.9 — April 21, 2026 — SDR Refactor: Dead Code Out, Shared Constants In
- REFACTOR (P2) — Deleted 4 stale SDR component shells (
CampaignPanel,CallControlBar,LeadPanel,DispositionPanel) that were never wired into production. Documented as safe indocs/SDR_COMPONENT_STATUS.md. - SHARED CONSTANTS —
DISPOSITION_OPTIONS+DispositionOptiontype promoted tosrc/lib/dispositions.tsx— survives future UI cleanups, now consumable by analytics / coaching surfaces. - NEW EXTRACTION —
SMSInboxcomponent extracted fromsdr/page.tsx(88 LOC, pure presentational, props-driven, no Pusher closure traps). - HEALTH —
/api/health/regressionreturns 16/16 GREEN.
v7.5.8 — April 21, 2026 — Twilio/Telnyx Load Balancer + Husky Pre-Push Gate
- NEW: Telephony Load Balancer — Weighted-random Twilio ↔ Telnyx split based on live free-slot capacity. Default OFF for safety (
TELEPHONY_LOAD_BALANCE=false). Flip totrueto enable. - API —
selectProviderForCall(options?)picks weighted by(limit - active). OptionalpreferProviderfor sticky retries. 5s in-memory snapshot cache. Falls back to least-loaded when both are at capacity. - TELEMETRY —
GET /api/telephony/load-balancerreturns live capacity, enabled flag, and a 100-pick sample distribution. - BUILD SAFETY — Installed
husky+cross-env. Newyarn type-checkrunstsc --noEmit --skipLibCheck..husky/pre-pushblocks pushes that don't type-check.
v7.5.7 — April 21, 2026 — CRM Panel Persistence in Power Dial 3x (P0 CRITICAL)
- Recurring across forks — SDRs reported the CRM/Lead-Intel panel going blank the moment a Power Dial 3x lead became human and connected. Bug had been "fixed" twice before and kept returning.
- Root cause — In Power Dial 3x, when one lead becomes human and the SDR connects, the OTHER 2 leads fire
voicemail-detectedPusher events. The handler was unconditionally runningsetActiveLead(null),callManager.resetCall(), andwarmTransfer.clearTransfer()on the WINNER lead. Compounded by stale closures — useEffect deps were[teamMemberId, isAvailable], so handler captured staleactiveLead+callStateat bind time. - Fix — Added
activeLeadRef+callStateRefto mirror current state. Handler bails out ifdata.leadId !== activeLeadRef.current?.idwhilecallStateRef.current === 'CONNECTED'.clearActiveLead()rewired to read from refs.handleStopPowerDialuses the safe setter.
v7.5.6 — April 21, 2026 — Cloud Build Unblocked (power-dial Syntax Fix)
- CRITICAL BUILD FIX — Cloud Build
6638d078-...failed with TurbopackExpression expectedatpower-dial/route.ts:684. Root cause: an unclosedelse { ... }block in the D13 country-whitelist handler tried to close two scopes with a single}. Brace-depth instrumentation confirmed depth went3 → 2on one brace where two were required. - Fix — Rewrote D13 handler as early-return pattern (push to
failedLeads,return null, no else). Brace/paren counts now balanced (218/218, 224/224).
v7.5.5 — April 21, 2026 — Telnyx Recording Playback / Download Fix (CRITICAL)
- Symptom — Every recording in
/dashboard/recordingsshowed "Recording unavailable". Audio playeronErrorfired; downloads produced HTML/JSON error bodies. 772+ Telnyx recordings affected. - Root cause —
recordings/stream/route.tswas attachingAuthorization: Bearer ${TELNYX_API_KEY}when fetching audio. Telnyx returnsdownload_urls.mp3as an AWS S3 presigned URL, and S3 rejects any extra auth header withHTTP 400 InvalidRequest: Only one auth mechanism allowed. - Fix — Drop the Bearer header on the S3 fetch. Telnyx metadata fetch still uses Bearer. Verified end-to-end: HTTP 200, 25,388 bytes, first 4 bytes
ID3(valid MP3).
v7.5.4 — April 20, 2026 — Critical Production Fixes: AMD, Recordings, Telnyx D13
- AMD False-Positive "Rings Twice" — Power Dial 3x calls would ring twice then disconnect. ZERO-DELAY logic connected agent on carrier "in-progress" (early media) instead of waiting for AMD human confirmation. Disabled premature agent connection — agent now connects EXCLUSIVELY after AMD confirms human. 1-3s connection delay (acceptable tradeoff).
- Recording Download Fix — Download button was returning CSV/HTML instead of
.mp3. AddedgetToken()Clerk auth + credentials on all recording requests + blob type validation. - Telnyx D13 Country Whitelist Handling — Cryptic "Dial error 403" now auto-detected; leads marked
CONFIG_ERROR, system alert created with actionable admin instructions. - Recording System Nuclear Fix — Retry with exponential backoff (2 retries), extended timeout (60s), provider-specific error messages, blob validation. New
GET /api/v2/recordings/health. - Follow-ups — Admin/Manager default to "All" scope.
lastDIDUsedin API. Banner when viewing "Mine" with 0 results.
v7.5.3 — April 19, 2026 — AMD False-Positive + Ops Escape Hatches + Capacity
- AI Call-Analysis Persistent Cache — Added
aiAnalysis Json?,aiAnalyzedAt,aiAnalyzedBytoCallRecording. Restored cache inGET/POST /api/call-analysis. - ProblematicNumber Tracking — New model tracks phones whose carriers trigger AMD false positives via misleading early-media. Auto-flagged after 3 incidents.
- AMD False-Positive Auto-Correct —
completedwebhook withduration<5son a "connected" lead andansweredBy != 'human'overrides tono_answerinstead of preserving staleconnected. - Force Hangup + Reconcile Stuck Leads —
POST /api/warm-transfer/force-hangup(per-lead emergency hangup) +POST /api/warm-transfer/reconcile-stuck-leads(org-scoped bulk reset of leads stuck >2min). - Telnyx→Twilio Per-Lead Failover — Power Dial detects Telnyx
D1/90041channel-limit errors mid-batch and transparently retries via Twilio. - Provider Capacity Widget —
GET /api/telephony/capacity+ newProviderCapacityWidgetUI with live utilization %. - Cloud Build Regression Gate — Post-deploy step hits
/api/health/regression; build fails if not green.
v7.5.2 — April 19, 2026 — Regression Audit + Failover + Regression API
- Regression Audit (Issues #2–#14) — Full regression sweep of all 13+ user-reported issues across v7.0.7 → v7.3.9. Each fix verified via grep + source inspection. ALL CONFIRMED RESOLVED.
- NEW:
GET /api/health/regression— 16 source-level checks against the 13 resolved issues + 3 UX regressions + 1 audio-regression guard. Returns JSON with pass/fail per check. - NEW: Admin → Regression Health Page —
/dashboard/admin/regressionone-click audit with badges, file:line evidence, re-run button. - NEW: Automatic Provider Failover (Telnyx ↔ Twilio) — Dial route wraps attempts in a failover loop. If primary fails (e.g., 20003 auth, network), fallback is tried after
TELEPHONY_FAILOVER_DELAY_MS. - Build-Breaking Bugs Fixed —
call-analysisroute Python-only import,CallRecording.customDatareference,prisma.callEventnonexistent model,providerSid→providerId, supervisor pagec.id→c.campaignId, regression API Turbopack over-bundling.
v7.5.1 — April 19, 2026 — Supervisor Call History + SDR Page Decomposition
- Supervisor Call History Tab — Full call log with filters by agent / campaign / disposition / date range, pagination, color-coded disposition badges.
- Export to CSV — Download call history for reporting and external analysis.
- SDR Page Decomposition — Extracted
CampaignPanel,CallControlBar,LeadPanel,DispositionPanelintosrc/app/dashboard/sdr/components/*.
v7.5.0 — April 19, 2026 — Per-Campaign Provider + DID Purchase UI + Automatic Failover
- Per-Campaign Provider Selection — Choose Twilio or Telnyx per campaign. Provider badge (orange / green) on campaign cards.
- DID Purchase UI — Search and buy phone numbers from both Twilio and Telnyx in one place.
POST /api/phone-numbers/search,POST /api/phone-numbers/buy. - Automatic Failover Infrastructure —
dialWithFailover()function added for provider redundancy. - Schema — Added
telephonyProviderfield toWarmTransferCampaign.
v7.4.1 — April 19, 2026 — Dual-Provider Restoration (Twilio + Telnyx)
- DUAL-PROVIDER — Restored full Twilio + Telnyx side-by-side support. Provider selection respects explicit
TELEPHONY_PROVIDERenv var even when both are configured. - Phone Numbers API — Returns DIDs from BOTH Twilio and Telnyx with provider labels.
- Telephony Status API — Tests connectivity to both providers, reports active / available.
- Recordings UI — Provider badges (orange / green) on each recording row.
- Helpers —
isProviderAvailable(),getAvailableProviders()for multi-provider support.
v7.4.0 — April 18, 2026 — Recording Availability Fix for Twilio Suspension
- Twilio Account Suspension Handling — Twilio recordings now show clear "Twilio (Suspended)" status instead of cryptic errors.
- Recordings Banner — Explains Twilio suspension and shows count of unavailable vs. available recordings.
- Provider Detection — AudioPlayer visually distinguishes Twilio (red/disabled) from Telnyx (green/playable).
- Stream API — Returns clear error for suspended Twilio recordings with provider info. Download button disabled with tooltip.
v7.3.9 — February 21, 2026 — Critical Call + DID Dropdown + SDR Visibility Fixes
- CRITICAL: One-Way Audio for Telnyx WebRTC — Added a remote audio element so prospect audio now plays.
- CRITICAL: Phone Numbers Dropdown — Now fetches Telnyx DIDs from the API (was showing stale Twilio numbers).
- FIX: Disposition-in-2-seconds — Deferred
activeCalluntil the call genuinely reaches active state. - FIX: Outbound call failure — Returns to IDLE instead of showing disposition.
- FIX: SDR Campaign Visibility — All org campaigns now visible to all SDRs.
v7.3.8 — February 20, 2026 — Production Deployment Fixes + DID Analytics
- CRITICAL: Cloud Run Telnyx Env Vars — Added all 10 Telnyx env vars to
cloudbuild.yaml. Previously Cloud Run had zero Telnyx credentials, routing all calls to suspended Twilio. - CRITICAL: Provider Detection —
getActiveProvider()now unconditionally prefers Telnyx when any Telnyx credential exists. Prevents accidental Twilio routing. - FIX: Build Error — Resolved
Cannot find name getProviderClientin recordings enrich route. - FIX: SDR Dial — Guarded
call.on()for Telnyx (Call objects don't support .on). Provider-aware call ID extraction. - FIX: WebRTC Stability — Socket close debounced 6s. Auto-reconnect with 30s cooldown. Old client cleanup before reconnect.
- NEW: Phone Numbers Telnyx Support — API fetches from Telnyx API with env var fallback. UI shows Telnyx tab with green badges and A-attestation.
- NEW: Health Monitor v7.3.8 —
checkTelephony()replacescheckTwilio(). Shows Telnyx DID count and SIP status. - NEW: DID Analytics — Disposition events store DID used. SDR dashboard shows per-DID call counts. DID column in dispositions tab.
- IMPROVED: Token Route — Telnyx fallback when Twilio creds missing. Diagnostic logging for Cloud Run debugging.
v7.3.0 — April 16, 2026 — Full Telnyx Migration + Telephony Abstraction
- NEW: Full Telnyx Migration — 30+ files converted from Twilio. All dial, power-dial, DID, recording, AMD, WebRTC paths now route through Telnyx.
- NEW: Provider Abstraction —
IVoiceProviderinterface with Twilio + Telnyx implementations. Switch viaTELEPHONY_PROVIDERenv var. - NEW: Telnyx TeXML Dial — Prospect + agent calls via TeXML API. Conference join, recording, AMD all via TwiML-compatible markup.
- NEW: AMD Parity — Aggressive AMD params preserved: speechThreshold=1200, speechEndThreshold=500, silenceTimeout=2000, timeout=30s.
- NEW: useTelephonyDevice — Provider-agnostic WebRTC hook. Supports
@twilio/voice-sdkand@telnyx/webrtc. - NEW: 12 Telnyx DIDs — All assigned to TeXML App "ASOC Mission Control" with production webhook.
- NEW: Complete DID Management — Search, bulk purchase, recording sync all via Telnyx API.
- NEW: Status API —
/api/telephony/statusshows active provider, health, balance, number count. - IMPROVED: Dial + Power-Dial — Both routes support Telnyx and Twilio paths. Zero-delay pre-connect preserved.
- PRESERVED — Conference recording, Smart DID rotation, STIR/SHAKEN A-attestation (native on Telnyx).
v7.2.1 — April 15, 2026 — Legal/Compliance Pages + GDPR Cookie Consent
- NEW: 7 Legal Pages — Privacy Policy (
/privacy), Terms & Conditions (/terms), EULA (/eula), Cookie Policy (/cookies), Opt-Out & Data Deletion (/opt-out), AI & Automation Policy (/ai-policy), Compliance Center (/compliance). - NEW: GDPR Cookie Consent Banner — Accept All, Essential Only, Customize (Functional/Analytics toggles). localStorage persistence with version tracking.
- NEW: Opt-Out Form — Interactive request form for DNC, data access, data deletion, recording deletion, AI opt-out.
- NEW: Compliance Center — 6 regulation cards (TCPA, GDPR, CCPA, STIR/SHAKEN, CAN-SPAM, TSR) + regional compliance table (US, EU, UK, Canada, Australia, India).
- IMPROVED: Footer — "Legal & Compliance" section with links to all 7 legal pages.
v7.2.0 — April 13, 2026 — Production Hardening + DID Infrastructure + CRM
- NEW: DID Purchase UI — Buy DIDs by city ($1.15/number/month) with cost confirmation.
POST /api/twilio/dids/purchase. - NEW: Smart DID Rotation — Region-based caller ID (same state → neighbor → lowest volume). 50-call daily limit per DID.
- NEW: SDR Dedicated DID — 1:1 DID per SDR for inbound/outbound. Admin assignment via Team page.
- NEW: CRM Lead 360 Report — Full prospect view with call history, recordings, meetings, CSV export.
GET /api/crm/lead-report. - NEW: SDR Personal Dashboard —
/dashboard/sdr-analyticswith stats, dispositions, recordings, meetings, date filters, CSV. - NEW: System Alerts Module — 9 health checks, sidebar badge, cron API.
GET /api/cron?task=health-check. - INFRA: AMD Validation Guard —
validateAMDParams()clamps to safe min/max. Prevents outages. - INFRA: Disposition Refactor — Shared
telephony-utils.tsfor status mapping, error codes. - INFRA: SDR Page Decomposition — 3,041 → 2,830 lines (6 extracted components).
- FIX: 1x Dial Recording — Re-enabled
record-from-answer-dualfor manual outbound calls. - FIX: 1x Dial Disposition — WRAP_UP transition now reliable.
v7.1.2 — April 13, 2026 — CRITICAL: AMD Parameter Fix + Recording Fix
- CRITICAL: AMD speechEndThreshold — 400→500ms (below 500ms minimum blocked ALL dials).
- NEW: System Alerts Dashboard —
/dashboard/alertswith 6 health checks, ack/resolve, severity filtering. - NEW: Lead Edit/Delete — Inline editing and deletion in campaign lead list.
- NEW: Campaign Soft Delete — Preserves all data. Restore via modal.
- NEW: In-Call DTMF Dialpad — Keypad for IVR navigation during active calls.
- FIX: Triple-Redundancy Recording — conferenceRecord + REST API + webhook.
- FIX: Dashboard Counters — callsHandledToday incremented, Connected excludes VM/DNC/DND.
v7.1.0 — April 13, 2026 — Scale Readiness + DID Reputation + AMD Tuning
- NEW: Scale Dashboard —
/dashboard/twilio-scalewith real-time STIR/SHAKEN attestation, CPS monitoring, concurrent call tracking, DID pool health, agent capacity, and automated scale recommendations. - NEW: DID Reputation Scoring — Per-DID scores (0-100), grades A-F, trend detection (improving/declining/stable), auto-flagging below threshold, configurable time ranges (7d/14d/30d).
- NEW: Auto-Rotate DIDs — Bulk deactivation of flagged DIDs from active pool. Safety guard keeps min 2 active. Manual per-DID deactivation available.
- NEW: Scale Readiness API —
GET /api/twilio/scale-readinessreturns account CPS, Trust Hub, concurrent calls, dial stats, recommendations. - NEW: DID Reputation API —
GET /api/twilio/did-reputation+POSTfor auto-rotate/deactivate. - FIX: DNC Disposition Bug — SDR can now hang up and see disposition form without dialer auto-advancing. Root cause: WRAP_UP race condition in disconnect useEffect.
- FIX: AMD Voicemail Detection — Tightened parameters: speechThreshold 2400→2000ms, speechEndThreshold 1200→800ms, silenceTimeout 5000→3500ms.
v7.0.8 — April 10, 2026 — Deployment Fix + Recording Enrichment
- FIX: Cloud Build CLERK_SECRET_KEY — Combined bash step clears stale secret bindings before deploy.
- NEW: Recording Enrichment —
POST /api/v2/recordings/enrichmaps orphaned recordings to leads. - NEW: Real-time Recording Webhook — DB insertion on recording-status callback.
v7.0.7 — April 9, 2026 — Call Recordings + CSV Export
- NEW: Call Recordings System — Auto-sync from provider, full pagination (10K), 3-strategy lead matching, CSV export.
- NEW: CSV Export on Call Logs — Export up to 10K events.
- IMPROVED: Campaign Analytics — Restart archives historical counters.
v7.0.6 — April 10, 2026 — Audio Fix + Disposition + Follow-ups + Dedicated DIDs
- FIX: Manual Dial "All Agents Busy" — TwiML App Voice URL was misconfigured to the inbound webhook. Repointed to
/api/twilio/voicevia Twilio REST API. - FIX: One-Way Audio (Prospect Cannot Hear SDR) — Switched ALL conference joins to
client.conferences(name).participants.create(). Eliminates TwiML parent→child call bridge that was losing browser audio. - FIX: Recording Audio Dropout — Removed
record: 'record-from-ringing-dual'from voice and inbound-call routes. - FIX: Disposition Popup — Always appears post-call (auto-LHU-submit removed).
- FIX: Callback Date — Now persisted via dedicated picker on CB/FUP dispositions (
WarmTransferLead.callbackDate). - FIX: Notes Auto-Bleeding —
callNotes+callbackDatecleared on every new call. - FIX: CB/FUP Leads — Status set to
callback_scheduled(excluded from auto-dialer). - NEW: Follow-ups & Meetings Page (
/dashboard/followups) — list, calendar, analytics views. - NEW: Dedicated Inbound DID per SDR — Assignable from profile page. Rings the SDR's browser directly when online; AI receptionist + miss notification when offline.
v7.0.5 — April 9, 2026 — Nuclear Telephony Fix: Persistent Ringing + Recording
- CRITICAL: Persistent Ringing — Root cause: Pusher
incoming-transferarrived 200-800ms before the Twilio WebRTC call reached the browser. The old 100ms auto-accept timer fired whentwilio.incomingCallwas still null, falling through tomakeCall()which created a SECOND outbound call while the original kept ringing forever. - Fix — Auto-accept now triggers from the
twilio.incomingCalluseEffect (when the call ACTUALLY arrives).makeCallfallback removed. Polling (10 × 200ms) replaces the blind 1000ms wait. Three-layer auto-accept (Pusher confirm + INCOMING state safety net +handleAnswerpolling). - CRITICAL: Recording Not Working —
record="record-from-start"had been silently removed from Conference TwiML in v6.2.5. Restored on the PROSPECT's Conference TwiML in both single and power-dial routes (NOT on agent TwiML — prevents dual-stream audio).
v7.0.4 — April 9, 2026 — Campaign-Aware DID Pools + SDR Launch Guide
- FIX: SDR Desktop DID Dropdown — Previously showed only global/env numbers (4 DIDs). Now dynamically loads DIDs from the campaign's assigned phone pool when an SDR selects a campaign. Falls back to global numbers when no pool is assigned.
- FIX: Single Dial Pool Routing —
POST /api/warm-transfer/dialnow checks the campaign'sdidPoolIdsand uses pool numbers (matching power-dial behavior). Previously only used global active DIDs. - IMPROVED: DID Count Badge — SDR Desktop header shows the number of available DIDs and indicates when using a campaign pool.
- NEW: Campaign Launch Guide — Step-by-step guide in User Guide covering the full workflow: Create Pool → Create Campaign → Upload Leads → Context → Assign SDR → Activate → Dial.
- DOCS: Phone Pools Section — New comprehensive section in User Guide covering pool creation, campaign assignment, and DID rotation behavior.
v7.0.3 — April 9, 2026 — AI Context Summarization + Docs Update
- NEW: AI Context Summarization — Paste sales docs, GPT-4o extracts top 5 icebreakers + pain points. New
POST /api/warm-transfer/campaigns/[id]/summarize-contextendpoint. - NEW: AI Insights Tab — Third tab in Campaign Context Editor shows elevator pitch, numbered icebreakers, and pain point cards.
- IMPROVED: Copilot Icebreakers — AI-extracted talking points now prioritized over collateral-based icebreakers during live calls. Cap expanded from 6 to 8.
- NEW: contextSummary Field — Persisted on campaign schema. AI summary survives refresh and auto-feeds into copilot.
- DOCS: Global Update — Version bump across README,
/docs, user guide, release notes, roadmap, and changelog.
v7.0.2 — April 8, 2026 — Phase 1 Production Readiness Audit
- CRITICAL FIX: Clerk Auth Middleware —
proxy.tshad broken export pattern causingauth()to return null on all API routes. Fixed with standardexport default clerkMiddleware(). This resolved the "Unauthorized" error when saving Apollo/ZoomInfo API keys. - CRITICAL FIX: Recording Bug Prevention — Removed
record: options.recordingEnabledfromtwilio-client.ts:createOutboundCall()to prevent v6.2.4 one-way audio regression. - NEW: Comprehensive Health Endpoint —
GET /api/healthreturns granular status for Telnyx, Retell AI, Pusher, DB, Email, AI, Active Agents + scale configuration. - FIX: Hardcoded GCP URLs — Removed stale fallback URLs from power-dial and amd-callback routes. Now fails fast on missing
NEXT_PUBLIC_APP_URL. - Phase 1 Audit — Full 7-point production readiness verification for 10 SDRs / 1,000 calls per day. All checks passed.
v7.0.0 — April 2, 2026 — Email Outbound System + Campaign Wizard
- NEW: 8-Step Email Campaign Wizard — Setup → Leads → Template → Collateral → Generate → Review → Mailbox → Launch
- NEW: AI Intelligence Engine v2 — GPT-4o bulk email generation with 5 tones, template injection, campaign brief context
- NEW: AI Sequence Optimizer — GPT-4o analysis with prioritized recommendations and predicted uplift
- NEW: Sequence Template Loader — Load existing sequences in wizard Step 3
- NEW: Campaign Briefs — Upload PRDs, whitepapers for AI grounding at
/dashboard/campaign-briefs - NEW: Apollo Lead Enrichment — Batch enrichment up to 25 leads per request
- NEW: CSV Lead Upload — Smart column parsing with deduplication
- NEW: Email Analytics Dashboard — Open/Click/Reply/Bounce rates, campaign comparison
- NEW: 4-Provider Email Config — Resend, SendGrid, Gmail OAuth, SMTP
- FIXED: SMTP SSL detection — Port 587 → STARTTLS, Port 465 → SSL
- FIXED: Gmail OAuth redirect URI — Properly validated after server restart
v6.2.5 — March 29, 2026 — Prod Logging + Scale Readiness
- FIX: Voicemail disposition screen — Voicemails no longer show the disposition screen to SDRs. Root cause:
incoming-transfersenthumanDetected: truebefore AMD ran. Fix: addedamdPendingflag andhuman-confirmedPusher event to gate WRAP_UP behind AMD confirmation. - FIX: Prospect hangup didn't end agent call — Prospect conference leg had
endConferenceOnExit="false". Changed to"true"in bothdial/route.tsandpower-dial/route.ts. Hangup now ends both calls. - FIX: Slow return to dialing — LHU (Lead Hung Up) auto-submits disposition in 1.5s and returns SDR to IDLE immediately. No more 30s WRAP_UP timeout blocking the dialer.
- AMD callback — All 4 human-detected paths (single + power, pre-connect + fallback) now send
human-confirmedPusher event - SDR page —
amdConfirmedRefgates disconnect → WRAP_UP.autoDispositionRefauto-submits LHU.
v6.2.0 — March 29, 2026 — Zero-Delay Conference Pre-Connect (Nuclear Audio Fix)
- NUCLEAR FIX — Eliminated 8-10s dead air on warm transfers. Prospect was saying "Hello?" into an empty conference because agent call was deferred to AMD callback (3-8s after pickup).
- Single Dial — Agent + prospect calls fire simultaneously via
Promise.allSettled()— 0s dead air - Power Dial — Agent call created on first
in-progressevent (fires before AMD) with atomic group claiming - Omnichannel placeholders — WhatsApp, Email, SMS "Coming Soon" cards on Warm Transfer page
- Disposition display fixes — Color mapping, human-readable names, badges on lead cards and activity feed
v6.1.0 — March 28, 2026 — Live Agent Testing: Browser WebRTC + Phone
- NEW: Browser Mic Test — Talk to AI agents via WebRTC in your browser. Real-time transcript with agent/user bubbles, mute, duration timer.
- NEW: Phone Call Test — AI agent calls your phone number for production-accurate testing.
- NEW: Live Test Panel — Expand/collapse panel with call status indicators, accessible from Agents page and Flow Builder.
- Power Dial 1x — Sequential one-at-a-time dialing through the power dial engine for high-value prospects.
v6.0.0 — March 27, 2026 — Hybrid Transfer Architecture
- ARCHITECTURE REWRITE — Replaced Conference-based transfers with direct
<Dial><Client>for sub-2s latency and zero audio crackling (2 media hops instead of 3) - NEW: dial-complete webhook —
/api/webhooks/warm-transfer/dial-completefor direct-dial call lifecycle management - NEW: escalate-conference webhook —
/api/webhooks/warm-transfer/escalate-conferencefor on-demand supervisor access - Supervisor auto-escalation — Monitor API auto-creates conference when supervisor clicks listen/barge on a direct-dial call
- SDR LHU auto-detect — Prospect hangup is auto-detected for Lead Hung Up disposition
- Persistent ringing fix — Ringtone properly stops on disconnect and WRAP_UP timeout
- Zero-latency webhooks — Next.js
after()returns responses in <250ms across all transfer webhooks - Version lock —
.version-lockfile prevents future forks from regressing below v6.0.0
v5.20.0 — March 24, 2026
- AI-Powered Email Content Generation — GPT-4o generates personalized emails from lead context, writing style, and sequence config
- Email Open Tracking — Invisible 1x1 pixel, real-time OPENED events, auto-updates step/enrollment counters
- Email Click Tracking — All links wrapped with tracking redirects, CLICKED events with URL attribution
- Retell AI Conversation Replay — Transcript + audio playback + sentiment analysis modal
- Centralized Event Logger — Unified error logging across all v2 APIs
- Critical Audio Fix — Removed forced
edge:ashburnfrom Device SDK, removed destructiveendCall()after redirect, parallelized transfer for sub-2s handoff - AMD Fix —
unknownnow treated as human (was incorrectly classified as voicemail) - +229 SIP Trunk Fixed — Proper SIP Domain and trunk configuration for Retell custom numbers
v5.19.0 — March 23, 2026
- Nuclear Audio Fix — Removed
region="us1"andrecord="record-from-start"from all 13 Conference TwiML points
v5.18.0 — March 23, 2026
- Email Sequence Engine — Multi-channel sequence builder with 5 step types
- Sales Collateral Library — CRUD with AI-targeting metadata and performance tracking
- Email Account Configuration — SMTP, Resend, Gmail OAuth with testing
- Sequence Processor Engine — Automated enrollment processing with personalization
- Sequence Analytics Dashboard — Conversion funnel and per-step metrics