Voice-call: fix Twilio status callbacks

This commit is contained in:
Ghost
2026-01-18 20:20:53 -08:00
parent b04b51d2c4
commit 60b87826bb
2 changed files with 21 additions and 5 deletions

View File

@@ -389,12 +389,12 @@ export class TwilioProvider implements VoiceCallProvider {
// Build request params - always use URL-based TwiML.
// Twilio silently ignores `StatusCallback` when using the inline `Twiml` parameter.
const params: Record<string, string> = {
const params: Record<string, string | string[]> = {
To: input.to,
From: input.from,
Url: url.toString(), // TwiML serving endpoint
StatusCallback: statusUrl.toString(), // Separate status callback endpoint
StatusCallbackEvent: "initiated ringing answered completed",
StatusCallbackEvent: ["initiated", "ringing", "answered", "completed"],
Timeout: "30",
};

View File

@@ -3,16 +3,33 @@ export async function twilioApiRequest<T = unknown>(params: {
accountSid: string;
authToken: string;
endpoint: string;
body: Record<string, string>;
body: URLSearchParams | Record<string, string | string[]>;
allowNotFound?: boolean;
}): Promise<T> {
const bodyParams =
params.body instanceof URLSearchParams
? params.body
: Object.entries(params.body).reduce<URLSearchParams>(
(acc, [key, value]) => {
if (Array.isArray(value)) {
for (const entry of value) {
acc.append(key, entry);
}
} else if (typeof value === "string") {
acc.append(key, value);
}
return acc;
},
new URLSearchParams(),
);
const response = await fetch(`${params.baseUrl}${params.endpoint}`, {
method: "POST",
headers: {
Authorization: `Basic ${Buffer.from(`${params.accountSid}:${params.authToken}`).toString("base64")}`,
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams(params.body),
body: bodyParams,
});
if (!response.ok) {
@@ -26,4 +43,3 @@ export async function twilioApiRequest<T = unknown>(params: {
const text = await response.text();
return text ? (JSON.parse(text) as T) : (undefined as T);
}