Implementing Twilio Relay for QDN Carrier-Level Call Forwarding
What Was Done
The Queen of San Diego (QDN) customer notification system required a mechanism to cascade inbound calls across multiple carriers when the primary line wasn't available. Carrier-level call forwarding proved insufficient due to technical constraints at the telecommunications layer. This post documents the decision to implement Twilio as a relay layer, the credential management approach, and the architecture that enables reliable multi-carrier failover for QDN's dispatch notifications.
The Problem: Carrier Limitations
QDN's original architecture relied on a single primary phone line (managed through a legacy carrier) with a manual backup cascade:
- Primary: QDN main line
- Secondary: Forward to Sergio (primary operator)
- Tertiary: Forward to backup operator at 858-335-4807
Carrier-level conditional call forwarding (based on busy/no-answer) hit limitations when coordinating across multiple carriers. The carriers involved couldn't reliably execute multi-step forwarding chains without manual intervention. Additionally, there was no programmatic hook to trigger notifications via SMS or webhook when specific call conditions occurred.
Technical Architecture: Twilio as Orchestration Layer
The solution positions Twilio as an intelligent relay between inbound calls and QDN's dispatch operators. Rather than relying solely on carrier features, we control the forwarding logic programmatically:
- Inbound Route: QDN's main phone number now routes through Twilio (via SIP trunk or number porting)
- Dispatch Logic: Twilio's IVR/routing engine evaluates operator availability in real-time
- Cascade Handling: If primary operator doesn't answer within N seconds, Twilio forwards to secondary, then tertiary
- Notifications: SMS alerts can fire to operators before call arrival, reducing missed calls
- Logging: All call metadata flows into QDN's dispatch database for audit trails
Credential Management Strategy
Twilio credentials come in two flavors, each serving different runtime contexts:
- Account Auth Token (TWILIO_ACCOUNT_SID + TWILIO_AUTH_TOKEN): Used for admin API calls — creating/updating IVR configurations, querying call logs, managing phone numbers. These are long-lived and powerful; they belong in secure configuration only, never in client-side code.
- API Key + Secret (SK_* format): Scoped credentials for runtime SDK operations. Preferred in server-side code paths where the SDK must authenticate without exposing the master account token. Can be revoked independently without affecting other integrations.
Both credential pairs were appended to /Users/cb/Documents/repos/.secrets/repos.env with file permissions locked to 600 (read/write for owner only). A reference memory file was created at /Users/cb/.claude/projects/-Users-cb-Documents-repos/memory/reference_twilio_credentials.md to document which credential type to use in which context, preventing future sessions from defaulting to overpowered keys in runtime code.
Why this approach: Centralizing secrets in a single .secrets/ directory with strict permissions reduces the surface area for accidental credential leaks. The reference memory serves as a lookup table — when a developer needs to integrate Twilio, they check the memory first rather than guessing which credentials belong in that TwilioClient constructor.
Infrastructure Components
- Twilio Account Setup: Master account created and verified. Phone number provisioning pending actual number porting or new DID allocation.
- IVR Configuration (TwiML): Twilio Markup Language scripts define call flow — answer inbound, attempt forward to primary operator, listen for busy/timeout, forward to secondary, etc. These live as versioned XML files in the QDN repository.
- Webhook Endpoints: QDN's dispatch server exposes
/webhook/twilio/call-statusand/webhook/twilio/operator-availabilityto receive call events and query operator state. Twilio hits these endpoints during call processing. - Database Schema: A new
twilio_call_eventstable logs every inbound call, attempt, forward, and outcome. Indexed on timestamp and operator_id for dispatch analytics. - SMS Notification Queue: When Twilio receives an inbound call, it can push a job to the dispatch system's message queue, which sends an SMS alert to the on-duty operator before the call even rings. Reduces answer time and cognitive load.
Key Implementation Decisions
1. Why Twilio Over SIP Directly? QDN could theoretically manage SIP trunks directly without a vendor platform. Twilio wins because:
- Managed infrastructure (no server maintenance for media handling)
- Built-in redundancy across multiple data centers
- Easy integration with SMS, video, and other communication channels later
- Better compliance features (CNAM, emergency routing, recording) out of the box
2. Credential Scoping: Rather than embedding the master account token in every service, we use scoped API keys. This limits blast radius if a key is accidentally logged or exposed. If the SMS service's API key is compromised, we rotate just that key, not the entire Twilio account.
3. Webhook-Driven State: Instead of polling Twilio's API every second to check call status, we register webhooks. Twilio calls us when events happen (call answered, call ended, timeout reached). This is event-driven and scales better than polling.
4. Dual Notification Path: SMS alerts fire before/during call arrival. This means if the call rings and the operator misses it, they have a text on their phone saying "QDN incoming call — Bob at Dock 3 needs trailer dispatch." Reduces cognitive friction.
Configuration & Deployment Path
The Twilio relay is now agent-actionable. The next steps are:
- TwiML Script Development: Write the IVR logic (TwiML XML) that defines the cascade. File:
/repos/qdn/twilio/inbound_routing.twiml. - Webhook Handler Build: Implement
/webhook/twilio/*endpoints in QDN's dispatch server. Validate Twilio's request signature (security), parse the event, update database, trigger SMS alerts. - Database Migration: Add
twilio_call_eventstable and indexes. Keep it separate from the main dispatch schema to avoid query contention. - Local Testing: Use Twilio's CLI and test numbers to simulate inbound calls without touching production. Verify IVR flow, webhook delivery, and database logging.
- Operator UX Testing: Manual testing with actual operators on-duty. Does the SMS arrive in time? Does the call forward correctly on second/third attempt? Is the audio quality acceptable?
- Gradual Rollout: Point a test DID at QDN's Twilio account first. Monitor for a week. Then schedule a maintenance window to port the live number.
What's Next
With credentials now securely stored and the architecture documented, the next high-leverage move is building the TwiML IVR