Retellai: Pre-Call Webhook Routing
Pay close attention to the following
This tutorial is based on using JavaScript based Container Applications. Make sure that you choose the correct runtime
for your container application.
In this tutorial, we'll explore how to use the Retellai API to call the pre-call webhook for routing incoming calls to your Retellai voice agent.
The Source Code
basic assumptions
- The provided script will handle any inbound call.
- The provided script will call the
/register-phone-callendpoint - The provided script will route the inbound call to returned call ID from Retell
- The provided script will log the call details to the console
- The provided script will provide the Retell agent with additional Cloudonix session data for future use
- The provided script will assumes the inbound call is received via an Inbound Voice Trunk
const httpClient = require('https');
/* ReTell API Config */
const retell_token = '{{ Your Retell API Token }}';
const retell_agent = '{{ Your Retell Agent ID }}';
async function httpsRequest(url, method = 'GET', headers = {}, body = null, requestTimeout = 5000) {
const start = Date.now();
let response;
if (method === 'POST') {
response = await httpClient.post(url, { headers, body });
} else if (method === 'PUT') {
response = await httpClient.put(url, { headers, body });
} else if (method === 'DELETE') {
response = await httpClient.delete(url, { headers });
} else if (method === 'GET') {
response = await httpClient.get(url, { headers });
} else {
throw new Error(`Unsupported method: ${method}`);
}
const elapsed = Date.now() - start;
if (elapsed > requestTimeout) {
console.log(`[httpsRequest] HTTP Request ${method} to ${url} timed out after ${elapsed} mSec`);
return false;
}
const status = response.status || response.statusCode || 0;
const ok = status >= 200 && status < 300;
const responseBody = typeof response.body === 'string'
? response.body
: JSON.stringify(response.body || {});
return {
status,
ok,
body: responseBody,
headers: response.headers || {}
};
}
async function getRetellCallId(ev) {
const url = 'https://api.retellai.com/v2/register-phone-call';
// SIP headers from Cloudonix
const inboundSipHeaders = JSON.parse(ev.body).SessionData.profile['trunk-sip-headers'];
const retellDynamicVariables = {
cloudonix_callerid: ev.parameters.From,
cloudonix_destination: ev.parameters.To,
cloudonix_token: ev.parameters.Session,
cloudonix_domain: ev.parameters.Domain
};
for (const key in inboundSipHeaders) {
retellDynamicVariables[key] = inboundSipHeaders[key];
}
const payload = {
agent_id: retell_agent,
from_number: ev.parameters.From,
to_number: ev.parameters.To,
retell_llm_dynamic_variables: retellDynamicVariables
};
console.log(`[getRetellCallId] Payload: ${JSON.stringify(payload)}`);
const headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + retell_token
};
try {
const response = await httpsRequest(url, 'POST', headers, JSON.stringify(payload));
if (!response.ok) {
throw new Error(`[getRetellCallId] ReTell call registration failed: ${response.status} - ${response.body}`);
}
const data = JSON.parse(response.body);
console.log(`[getRetellCallId] Success: ${data.call_id}`);
return data.call_id;
} catch (error) {
console.error(`[getRetellCallId] Error:`, error.message || error);
await deleteSession(ev.parameters.Domain, ev.parameters.Session);
return false;
}
}
function dialToRetell(ev, retellCallId) {
let result = `<Dial callerId="${ev.parameters.From}">\n`;
result += ` <Service provider="retell">${retellCallId}</Service>\n`;
result += `</Dial>`;
return result;
}
function response(content) {
let result = `<?xml version="1.0"?>`;
result += `<Response>${content}</Response>`;
return result;
}
exports.handler = async (ev) => {
const retellCallId = await getRetellCallId(ev);
if (!retellCallId) {
console.log(`[handler] ReTell call registration failed`);
return response("<Reject reason='rejected' />");
}
const retellRoutingCxml = dialToRetell(ev, retellCallId);
return response(retellRoutingCxml);
};
In-Depth Explanation
- Import the
httpsmodule to make HTTP requests. - Define the Retell API configuration variables, such as the API token and the Retell agent ID.
- Define a function
httpsRequestto make HTTP requests with custom timeout and error handling. - Define a function
getRetellCallIdto generate a Retell call using the provided Cloudonix session data. - Define a function
dialToRetellto construct the XML response for the Dial verb to route the call to the Retell agent. - Define the
handlerfunction that receives the Cloudonix event and uses the functions defined above to generate the appropriate response. - In the
handlerfunction, call thegetRetellCallIdfunction to generate the Retell call ID. - If the Retell call generation fails, reject the call.
- Otherwise, construct the XML response for the Dial verb to route the call to the Retell agent.
- Return the XML response to Cloudonix.
Remember to replace the placeholders ({{ Your Retell API Token }}, {{ Your Retell Agent ID }}) with your actual Retell API token and agent ID.