Ir al contenido
Guía

Haz una campaña de calificación de leads con IA con Wixzel Voice

Al final habrás subido una lista de leads, un agente que tú escribiste habrá llamado a cada uno por tu propia troncal SIP con tus preguntas de calificación, y habrás leído el estado y la transcripción de cada llamada. La implementación lleva unos 30 minutos en Node.js con el SDK wixzel-voice, más lo que tarden las llamadas. Las llamadas cortas con guion son la carga más barata: con el motor classic, a $0.0867 por minuto conectado, 1000 llamadas de dos minutos suman unos $173 de tiempo de motor, facturados por segundo desde un saldo prepago, más la tarifa de tu operador. Una llamada que nadie contesta no cuesta nada.

Por · Publicado el · Actualizado el

Duración
Unos 30 minutos, más las llamadas
Motor
classic
Tiempo de motor
$0.0867 por minuto conectado

¿Qué necesitas antes de empezar?

  • Una troncal SIP y un número saliente registrado en ella. La guía de Twilio y la documentación de troncales SIP explican ambas cosas.
  • Una clave de API de Wixzel Voice con crédito, y Node.js 20 o posterior con npm install wixzel-voice.
  • El consentimiento para llamar a cada lead de la lista donde la ley lo exija. El paso de cumplimiento de abajo resume lo que pide la Política de uso aceptable.

¿Cómo construyes esto en Wixzel Voice, paso a paso?

  1. 01Escribe el agente que llama

    El agente es el guion. Los campos de combinación personalizan cada llamada:

    agent.mjs
    import { WixzelVoice } from 'wixzel-voice';
    
    const client = new WixzelVoice({ apiKey: process.env.WIXZEL_API_KEY });
    
    const agent = await client.agents.create({
      name: 'Demo follow-up',
      outbound_phone_number_id: process.env.NUMBER_ID,
      system_prompt: [
        'You are calling {{name}} from {{company}}, who asked for a demo of Acme Scheduling.',
        'Ask three questions, one at a time: how many staff take bookings,',
        'what they use for bookings today, and when they would want to switch.',
        'Keep replies short. If they are not interested, thank them and end the call.',
        'If they ask not to be called again, confirm that you have noted it and end the call.',
        'Finish by thanking them and saying a person will follow up by email.',
      ].join('\n'),
      opening_message: 'Hi {{name}}, this is an automated assistant calling for Acme about the demo you requested. Is now a good time?',
      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);

    {{name}} se toma del lead, y cada clave de los fields de un lead también se convierte en campo de combinación, así que {{company}} sale de la subida de abajo. La frase de apertura dice que la llamada es automática, que es donde va ese aviso cuando la ley lo exige. outbound_phone_number_id es obligatorio para las campañas: es el identificador de llamada que muestra cada llamada.

  2. 02Sube los leads

    El resto de la implementación es un solo script, campaign.mjs. Empieza con la subida:

    campaign.mjs, part 1
    import { WixzelVoice } from 'wixzel-voice';
    
    const client = new WixzelVoice({ apiKey: process.env.WIXZEL_API_KEY });
    
    // From your CRM or a CSV: only people you have consent to call.
    const rows = [
      { name: 'Priya Nair', phone_number: '+14155550111', fields: { company: 'Northside Physio' } },
      { name: 'Sam Carter', phone_number: '+14155550112', fields: { company: 'Carter Auto' } },
    ];
    
    const upload = await client.leads.bulkCreate({ leads: rows });
    console.log('created', upload.created_count, 'failed', upload.failed_count);
    for (const e of upload.errors) console.log('row', e.index, e.phone_number, e.error);
    
    const leadIds = upload.data.map((lead) => lead.id);

    En una petición caben hasta 1000 leads. Las filas se validan una a una, así que revisa failed_count y errors en lugar de dar por hecho que llegó toda la lista. Una subida masiva no dispara webhooks.

  3. 03Ejecuta campañas ajustadas a tu límite de llamadas simultáneas

    Una campaña es un agente y una lista de leads. Crearla no llama a nadie; start sí, y gasta crédito a medida que se conecta cada llamada.

    Hoy, una campaña hace sus llamadas en rápida sucesión en lugar de ponerlas en cola, y cada llamada cuenta para el límite de llamadas simultáneas de la cuenta, cinco por defecto. Un lead que supera el límite se registra como llamada fallida en lugar de esperar su turno. Por eso, recorre la lista en lotes no mayores que tu límite, y empieza el siguiente lote cuando el anterior haya terminado:

    campaign.mjs, part 2
    const LIMIT = 5; // your account's concurrent-call limit, minus any calls you expect meanwhile
    const DONE = new Set(['completed', 'failed', 'busy', 'no-answer', 'canceled']);
    const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
    
    async function finishedCalls(campaignId) {
      let finished = 0;
      for await (const call of await client.calls.list({ campaign_id: campaignId, limit: 100 })) {
        if (DONE.has(call.status)) finished++;
      }
      return finished;
    }
    
    const campaignIds = [];
    for (let i = 0; i < leadIds.length; i += LIMIT) {
      const batch = leadIds.slice(i, i + LIMIT);
      const campaign = await client.campaigns.create({
        name: 'Demo follow-up ' + (i / LIMIT + 1),
        agent_id: process.env.AGENT_ID,
        lead_ids: batch,
      });
      await client.campaigns.start(campaign.id);
      campaignIds.push(campaign.id);
    
      const giveUpAt = Date.now() + 30 * 60 * 1000;
      while ((await finishedCalls(campaign.id)) < batch.length && Date.now() < giveUpAt) {
        await sleep(15000);
      }
    }

    start responde con la campaña en status: "running". Para detener un lote antes de tiempo, client.campaigns.pause(campaign.id) lo detiene y cuelga sus llamadas en curso; después la campaña muestra status: "stopped". Volver a iniciar una campaña detenida llama otra vez a todos sus leads, incluidos los que ya se llamaron, así que para continuar, crea una campaña nueva con los leads que aún no se han contactado. scheduled_at al crearla inicia la campaña a una hora fijada en lugar de con start.

  4. 04Consulta cada llamada

    Cada llamada es un registro con su estado, su costo y su transcripción, vinculado a su lead por lead_id:

    campaign.mjs, part 3
    for (const campaignId of campaignIds) {
      for await (const call of await client.calls.list({ campaign_id: campaignId, limit: 100 })) {
        const detail = await client.calls.retrieve(call.id);
        const answers = detail.transcript
          .filter((line) => line.role === 'user')
          .map((line) => line.content)
          .join(' / ');
        console.log(call.lead_id, call.status, call.duration_seconds, call.failure_code, answers);
      }
    }

    status indica si la llamada se conectó, failure_code por qué no (17 ocupado, 19 sin respuesta, 21 rechazada por el operador) y cost_micros cuánto costó. Un lead rechazado antes de marcar, por el límite de llamadas simultáneas o por falta de crédito, aparece como failed sin failure_code.

    La calificación en sí la decides tú. Wixzel Voice registra la conversación; la transcripción contiene las respuestas a tus tres preguntas, así que puntúala con tus propias reglas o tu propio modelo y escribe el resultado en tu CRM. El campo summary puede estar vacío, así que no dependas de él. Para reaccionar cuando terminan las llamadas en lugar de consultar periódicamente, suscríbete al webhook callCompleted, que incluye los ids del lead y de la campaña con el estado y la duración de la llamada.

  5. 05Cumple las normas sobre llamadas

    La Política de uso aceptable deja estas obligaciones a quien llama, es decir, a ti. Esto es un resumen de esa política, no asesoramiento legal.

    Llama solo a personas cuyo consentimiento tengas donde la ley lo exija. En Estados Unidos, eso suele significar consentimiento previo, expreso y por escrito para llamadas de marketing a móviles según la TCPA; en la India, las normas de preferencias del cliente de la TRAI; en el Reino Unido y la UE, la PECR y el RGPD.

    Consulta los registros nacionales y estatales de exclusión de llamadas y tu propia lista de exclusión antes de cada subida. Cuando alguien pida que no le vuelvan a llamar, elimínalo pronto y de forma permanente: el agente puede terminar la llamada con educación, pero eliminar el lead es tarea de tu código.

    Avisa de que la llamada es automática al inicio, donde la ley lo exija, como hace la frase de apertura de arriba; respeta las restricciones de horario de llamadas y conserva la prueba del consentimiento durante el tiempo que exija la ley.

¿Cuánto cuesta esto en Wixzel Voice?

Tiempo de motor para llamadas de 2 minutos con el motor classic a $0.0867 por minuto conectado: unos $0.17 por llamada. La telefonía es tu propia troncal con la tarifa de tu operador y no está incluida.

Costo mensual de motor de lo que construye esta guía
Llamadas al mesMinutos conectadosCosto de motor al mes
10002000$173
500010.000$867
20.00040.000$3,468

Solo se factura el tiempo conectado, por segundo. Una llamada ocupada, sin respuesta o rechazada antes de marcar no cuesta nada, porque el motor nunca arranca. Tu operador factura la línea por separado con sus propias tarifas, sin 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?

  • Una campaña llama a sus leads en rápida sucesión y no espera en cola por el límite de llamadas simultáneas, cinco por cuenta por defecto; los leads que lo superan se registran como fallidos. Divide la lista en lotes según tu límite, o pide uno más alto.
  • Volver a iniciar una campaña detenida llama otra vez a todos sus leads. Continúa con una campaña nueva formada por los leads que aún no se han contactado.
  • Cada campaña admite hasta 10 000 leads, y una cuenta admite hasta 500 campañas por defecto; el límite se amplía a petición.
  • Wixzel Voice registra la llamada y su transcripción. Decidir quién califica y mantener tu lista de exclusión es tarea de tu código.
  • Los cambios de comportamiento de Wixzel Voice se publican detrás de un encabezado Wixzel-Version con fecha.

Preguntas frecuentes

¿Cómo hago una campaña de llamadas salientes con IA en Wixzel Voice?

Sube leads con POST /v1/leads/bulk, crea una campaña con un agente y esos leads, y POST /v1/campaigns/{id}/start hace que el agente llame a cada uno por tu propia troncal SIP, uno tras otro. Mantén cada campaña dentro de tu límite de llamadas simultáneas, porque un lead que lo supera se marca como fallido en lugar de ponerse en cola. Cada llamada es un registro con su estado, su transcripción y su costo, vinculado al lead por lead_id. Las llamadas sueltas se hacen con POST /v1/calls.

¿Cuántas llamadas salientes pueden estar en curso a la vez?

Cinco por cuenta por defecto, contando cada llamada en curso y cada sesión web. El límite se amplía a petición: escribe a aqeel@wixzel.com con el volumen que esperas.

¿Uso campañas o llamadas sueltas?

Las campañas sirven para una lista que llamas de una vez. Si quieres tu propio ritmo y tus propios reintentos, POST /v1/calls por lead desde tu propia cola te da un control más fino: cada llamada lleva un lead_id y una clave de idempotencia, y tú decides cuándo empieza la siguiente.

¿Es legal hacer llamadas salientes con IA?

Depende de dónde estén las personas a las que llamas y de su consentimiento. La Política de uso aceptable exige consentimiento donde la ley lo exija, respetar los registros de exclusión de llamadas y las solicitudes de baja, y avisar de que la llamada es automática donde sea obligatorio. Wixzel Voice aporta las herramientas, no la base legal.

Dónde leer más

  • Inicio rápidodocumentación

    Una troncal, un número, un agente y una llamada.

  • Agentesdocumentación

    Instrucciones, frases de apertura e identificadores de llamada.

  • Webhooksdocumentación

    callCompleted, campaignCompleted y firmas.

  • Referencia de la APIdocumentación

    Leads, campañas y llamadas, campo por campo.

API para telefonía con agentes

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.

Dale a Claude una línea telefónica con el MCP de Wixzel Voice

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.

Recepcionista con IA para Twilio en Node.js con Wixzel Voice

Tu número actual de Twilio atendido por un recepcionista de IA que agenda citas en la API, hecho en Node.js.

Agente telefónico en hindi y malayalam con sarvam en Wixzel Voice

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.

Añade un agente de voz a Flutter por WebSocket con Wixzel Voice

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.

Gemini Live en una llamada real con la API de Wixzel Voice

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.

Añade una mascota de IA que habla a tu web con Wixzel Voice

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.

Muestra la mascota de tu agente en Flutter con Wixzel Voice

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.