Recepcionista con IA para Twilio en Node.js con Wixzel Voice
Al final, las llamadas a tu número actual de Twilio las atiende un recepcionista de IA que tú creaste: saluda a quien llama, responde según tus instrucciones y agenda citas que puedes consultar desde la API. Lleva unos 30 minutos en Node.js, con el SDK wixzel-voice para TypeScript y JavaScript y una troncal Elastic SIP de Twilio. El tiempo de motor con el motor classic cuesta $0.0867 por minuto conectado, unos $0.26 por una llamada de tres minutos, facturado por segundo desde un saldo prepago. Twilio te factura directamente los minutos de la troncal, sin margen.
Por Aqeel Shamsudheen · Publicado el · Actualizado el
- Duración
- Unos 30 minutos
- Motor
- classic
- Tiempo de motor
- $0.0867 por minuto conectado
¿Qué necesitas antes de empezar?
- Una cuenta de Twilio con Elastic SIP Trunking y un número de teléfono de Twilio.
- Una clave de API de Wixzel Voice (
wv_live_…) y crédito en la cuenta. La recarga mínima es de $5. - Node.js 20 o posterior.
¿Cómo construyes esto en Wixzel Voice, paso a paso?
01Crea la troncal Elastic SIP en Twilio
En la consola de Twilio, abre Elastic SIP Trunking y crea una troncal. En Termination, elige un Termination SIP URI, como
your-clinic.pstn.twilio.com. Ese nombre de host es elhostde la troncal que conectas en el siguiente paso.Deja abierta la consola de Twilio. Volverás a ella cuando la API te haya dado las dos direcciones que tienes que introducir.
02Instala el SDK y conecta la troncal
Instala el SDK y pon tu clave de API en el entorno:
shellnpm install wixzel-voice export WIXZEL_API_KEY="wv_live_..."trunk.mjsimport { WixzelVoice } from 'wixzel-voice'; const client = new WixzelVoice({ apiKey: process.env.WIXZEL_API_KEY }); const trunk = await client.sipTrunks.create({ name: 'Twilio', host: 'your-clinic.pstn.twilio.com', // your Termination SIP URI port: 5060, transport: 'udp', }); console.log('TRUNK_ID', trunk.id); console.log('Allowlist at Twilio:', trunk.platform_ip); console.log('Origination URI:', trunk.origination_uri);Aquí no hay usuario ni contraseña porque Twilio autoriza por IP de origen, que es el siguiente paso. Para usar una Credential List de Twilio, pasa su
usernamey supassword. La contraseña se guarda cifrada y la API no la vuelve a devolver nunca.03Apunta Twilio a Wixzel Voice, en ambas direcciones
Twilio configura las llamadas salientes y las entrantes por separado, y cada dirección falla sin avisar cuando falta su configuración.
En Termination, y luego en Authentication, añade la
platform_ipque se imprimió arriba a una IP Access Control List. Sin ella, Twilio rechaza las llamadas en un segundo aproximadamente con la causa de colgado 21.En Origination, añade un Origination SIP URI con el valor del
origination_urique se imprimió arriba. Sin él, tu número nunca llega al agente y no aparece nada en ninguno de los dos logs, porque la llamada nunca sale de Twilio.Por último, asocia tu número de Twilio a esta troncal en Numbers.
04Crea el recepcionista
Un agente se compone de unas instrucciones (prompt), una frase de apertura y un motor de voz.
appointment_booking_enabledle permite listar, agendar y cancelar citas durante la llamada; las instrucciones le dicen qué días, qué horario y qué duración de cita puede ofrecer.agent.mjsimport { WixzelVoice } from 'wixzel-voice'; const client = new WixzelVoice({ apiKey: process.env.WIXZEL_API_KEY }); const agent = await client.agents.create({ name: 'Reception', system_prompt: [ 'You are the receptionist for Riverside Dental, answering the phone.', 'Keep every reply to one or two short sentences, and never read out lists.', 'You can book, move and cancel check-ups and cleanings.', 'Offer appointments Monday to Friday, 09:00 to 17:00, 30 minutes each.', 'Before booking, ask for the full name of the caller and repeat the day and time back.', 'For a dental emergency, tell the caller to hang up and ring the emergency number.', 'If you cannot help, take a message and promise a callback.', ].join('\n'), opening_message: 'Riverside Dental, this is the automated assistant. How can I help?', appointment_booking_enabled: true, voice: { stt: { model: 'deepgram/nova-3', language: 'en-US' }, llm: { model: 'openrouter/gpt-4o-mini' }, tts: { model: 'elevenlabs/eleven_flash_v2_5' }, }, }); console.log('AGENT_ID', agent.id);Este es el motor classic: Deepgram Nova-3, GPT-4o-mini y ElevenLabs Flash v2.5, la combinación fiable más barata para inglés, a $0.0867 por minuto. Añade una
voiceal bloquettspara elegir la voz;client.engines.voices('classic')lista las que puede usar.La frase de apertura dice que quien llama está hablando con un asistente automático. Donde la ley lo exige, o exige avisar de que la llamada se graba, ese aviso va en la frase de apertura.
05Enruta tu número al recepcionista
Registra el número en la troncal, con el agente como el que lo atiende:
number.mjsimport { WixzelVoice } from 'wixzel-voice'; const client = new WixzelVoice({ apiKey: process.env.WIXZEL_API_KEY }); const number = await client.phoneNumbers.create({ phone_number: '+14155550100', // your Twilio number, in E.164 sip_trunk_id: process.env.TRUNK_ID, inbound_agent_id: process.env.AGENT_ID, }); console.log('NUMBER_ID', number.id);Sin un
inbound_agent_id, las llamadas entrantes a un número se rechazan. Para que el mismo agente también haga llamadas, para recordatorios o una llamada de prueba, haz que el número sea su identificador de llamada conclient.agents.update(agentId, { outbound_phone_number_id: number.id }).06Llama y luego consulta la llamada y la cita
Llama a tu número de Twilio desde un teléfono móvil y reserva un horario. Al colgar, la llamada y la cita ya están en la API:
results.mjsimport { WixzelVoice } from 'wixzel-voice'; const client = new WixzelVoice({ apiKey: process.env.WIXZEL_API_KEY }); // Lists are newest first. const calls = await client.calls.list({ direction: 'inbound', limit: 1 }); const latest = calls.data[0]; if (latest) { const call = await client.calls.retrieve(latest.id); console.log(call.status, call.duration_seconds + 's', (call.cost_micros ?? 0) / 1e6, 'USD'); for (const line of call.transcript) console.log(line.role + ': ' + line.content); } const appointments = await client.appointments.list({ limit: 5 }); for (const a of appointments.data) { console.log(a.date_time, a.client_name, a.phone_number, a.status); }date_timesiempre está en UTC. Cada reserva también dispara el webhookappointmentBooked, que es la forma de copiarla a tu propio calendario en el momento.
¿Cuánto cuesta esto en Wixzel Voice?
Tiempo de motor para llamadas de 3 minutos con el motor classic a $0.0867 por minuto conectado: unos $0.26 por llamada. La telefonía es tu propia troncal con la tarifa de tu operador y no está incluida.
| Llamadas al mes | Minutos conectados | Costo de motor al mes |
|---|---|---|
| 200 | 600 | $52.02 |
| 1000 | 3000 | $260 |
| 3000 | 9000 | $780 |
Wixzel Voice factura solo el tiempo de motor, por segundo de llamada, desde un saldo prepago. Twilio factura los minutos de Elastic SIP Trunking a tu cuenta de Twilio con tus tarifas de Twilio; Wixzel Voice nunca ve ese cargo ni le añade margen.
Prepago, sin suscripción y sin plan gratuito: agrega crédito desde $5 y el uso lo va consumiendo. Calcula tu propia combinación.
¿Qué límites de Wixzel Voice se aplican a esto?
- El recepcionista conoce tu horario por sus instrucciones. La API v1 no tiene un endpoint de disponibilidad, así que no puede ver tu calendario real: rechaza un horario ya reservado desde la API, pero no ve las citas que gestionas en otro sitio.
- Las reservas se interpretan en la zona horaria de la cuenta, que es UTC salvo que se haya cambiado, y la API v1 todavía no permite cambiarla. Revisa el
date_timede tus primeras reservas antes de confiar en ellas, y escribe a aqeel@wixzel.com si tu negocio no está en UTC. - Por defecto, cada cuenta puede tener cinco llamadas en curso a la vez. Las demás se rechazan hasta que termine una, y el límite se amplía a petición.
- Tu número sigue en Twilio. Wixzel Voice no vende, porta ni aloja números.
- Los cambios de comportamiento de Wixzel Voice se publican detrás de un encabezado
Wixzel-Versioncon fecha.
Preguntas frecuentes
¿Puedo crear un recepcionista de IA en Twilio?
inbound_agent_id. A partir de ahí, las llamadas al número las atiende tu agente, y Twilio sigue facturándote la troncal directamente.¿Tengo que sacar mi número de Twilio?
¿Por qué mi número de Twilio no llega al agente?
origination_uri de la troncal, y el número necesita un inbound_agent_id.¿Cuánto cuesta una llamada de un recepcionista de IA?
¿Hay SDK para lenguajes distintos de JavaScript?
wixzel-voice en npm para TypeScript y JavaScript, y wixzel_voice en pub.dev para Dart y Flutter. Otros lenguajes llaman directamente a la misma API HTTP, descrita por el documento OpenAPI en https://docs.voice.wixzel.com/api-reference.Dónde leer más
- Troncales SIPdocumentación
La sección de Twilio: IP ACL, Termination URI, identificador de llamada y Origination URI.
- Agentesdocumentación
Instrucciones, frases de apertura, de dónde sale el valor de cada campo y llamadas de prueba.
- Webhooksdocumentación
appointmentBooked, callCompleted, firmas y reintentos.
- SDKdocumentación
Los SDK de TypeScript y Dart.
Acerca de Wixzel Voice
Wixzel Voice es una API de IA de voz para crear agentes de IA que hacen y contestan llamadas telefónicas reales a través de tu propia troncal SIP, o que hablan con personas en tus apps web y móviles. Una clave de API y un saldo prepagado cubren todos los motores de voz, con cobro por segundo de uso real.
Más guías
Claude, en Claude Code o claude.ai, haciendo una llamada real por tu troncal SIP y leyéndote la transcripción, con una confirmación antes de marcar.
Dos agentes telefónicos, uno en hindi y otro en malayalam, con los modelos de Sarvam para idiomas de la India, que atienden o hacen llamadas por tu troncal SIP.
Una app Flutter en la que los usuarios hablan con tu agente de voz por WebSocket, con la clave de API guardada en tu servidor y sin ningún número de teléfono.
Un agente Gemini Live llamando a un teléfono real por tu troncal SIP a partir de cuatro peticiones cURL, y el registro de la llamada con su transcripción y su costo.
Una lista de leads llamados por tu agente a través de tu troncal SIP, en lotes ajustados a tu límite de llamadas simultáneas, con el estado y la transcripción de cada llamada.
Una mascota que habla en la esquina de tu sitio web, a la que los visitantes llaman desde el navegador, limitada a tus dominios y a tus límites diarios, con cada persona que llama registrada.
Una pantalla de Flutter con la mascota de tu agente, que mueve la boca con la voz del agente durante una llamada en tiempo real, con tu clave de API guardada en tu servidor.
Crea tu primer agente de voz

