Files
DentalManagement09/apps/Backend/src/routes/twilio-webhooks.ts
T
GiteadandClaude Sonnet 5 79ac6aaa31 feat: migrate SMS/voice to Telnyx (TeXML), keep browser dial pad on Twilio
Twilio now handles only the in-browser dial pad (Access Token + browser-Device
outbound TwiML); Telnyx takes over SMS, inbound voicemail, the AI voice
conversation loop, and staff-triggered outbound calls via TeXML. Adds
TelnyxSettings model, Communication.provider discriminator, new comms/routes
modules, and a real Telnyx Settings page.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-03 15:39:43 -04:00

38 lines
1.6 KiB
TypeScript

// NOTE: Twilio is now used only for the in-browser dial pad. This webhook
// handles the browser-Device outbound-call leg only — everything else (SMS,
// inbound/AI voice) moved to Telnyx, see routes/telnyx-webhooks.ts.
import express, { Request, Response } from "express";
import { prisma as db } from "@repo/db/client";
const router = express.Router();
function escapeXml(text: string): string {
return text
.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
.replace(/"/g, "&quot;").replace(/'/g, "&apos;");
}
// POST /api/twilio/webhook/voice-browser
// Called by Twilio when a browser Device (Voice SDK) places an outbound call.
// Looks up the office's Twilio phone number by AccountSid and dials the patient.
router.post("/webhook/voice-browser", async (req: Request, res: Response): Promise<any> => {
try {
const { To, AccountSid } = req.body as { To?: string; AccountSid?: string };
if (!To || !AccountSid) {
res.set("Content-Type", "text/xml");
return res.send("<Response><Say>Missing call parameters.</Say></Response>");
}
const settings = await db.twilioSettings.findFirst({ where: { accountSid: AccountSid } });
const callerId = settings?.phoneNumber || "";
res.set("Content-Type", "text/xml");
return res.send(
`<Response><Dial callerId="${escapeXml(callerId)}"><Number>${escapeXml(To)}</Number></Dial></Response>`
);
} catch {
res.set("Content-Type", "text/xml");
return res.send("<Response><Say>An error occurred. Please try again.</Say></Response>");
}
});
export default router;