Agencias

Rotación de números en WhatsApp: cómo repartir la carga entre instancias

Cuando un cliente tiene varios números, la pregunta deja de ser cómo enviar y pasa a ser desde qué número enviar. Meter todo por el mismo chip concentra el riesgo y deja los otros parados. La rotación divide el volumen, respeta el tope de cada número y saca de la fila al que se cayó. Esta guía muestra la regla, un ejemplo en Node.js sobre los endpoints documentados y los límites del método. La API no trae un balanceador listo: la rotación es lógica tuya, sobre GET /instances y send/text. ZapZap es una solución no oficial, y WhatsApp puede limitar o bloquear cualquier número, aunque la carga esté bien repartida.

Publicado el · 4 min de lectura

Este artículo también está disponible en: Português · English

Cuándo vale la pena la rotación (y cuándo no)

Vale para operaciones en las que un único cliente conversa con mucha gente: un equipo comercial con varias líneas, una clínica con sedes, una tienda que responde leads de anuncios todo el día. Dividir el envío reduce el volumen por número y mantiene viva la operación cuando un chip se cae.

No vale para envío masivo a quien nunca habló contigo. Dividir una lista fría entre cinco números solo esparce el problema en cinco chips, y el consentimiento sigue siendo lo que más pesa. Si el número es nuevo, caliéntalo antes: mira el calentamiento de chip.

Las cuatro reglas de una rotación segura

Primera, rotar solo entre números conectados: lee la lista de instancias y filtra por estado. Segunda, tope diario por número, definido por ti según la fase de cada chip (la planilla de operación lo guarda). Tercera, el mismo contacto siempre por el mismo número: quien ya conversó con el número A no debe recibir el siguiente mensaje del número B, porque el cambio confunde al cliente y parece sospechoso para WhatsApp. Cuarta, pausa inmediata en el número que devuelve 429 o cae de estado.

La tercera regla pide una tabla simple en tu sistema: contacto, instancia de origen. La rotación vale solo para contactos nuevos. Los contactos que ya tienen dueño siguen con él.

Código: rotación con tope diario sobre la API

El ejemplo lee GET /instances, filtra las conectadas (el estado viene como CONNECTED en la respuesta de ejemplo de la referencia), gira un cursor y salta a quien ya alcanzó el tope. El contador está en memoria solo para el ejemplo: en producción guárdalo por día en una base de datos, o la rotación se reinicia con cada arranque. La llamada de envío es POST /{instanceId}/send/text con number y text. Mira la referencia para los demás campos.

Node.js: round-robin with a daily cap

// Round-robin sender: picks the next CONNECTED instance that is under its daily cap
const BASE = "https://api.zapzapapi.com/api/v1";
const H = {
  "Content-Type": "application/json",
  "x-api-key": process.env.ZAPZAP_API_KEY,
  "x-api-secret": process.env.ZAPZAP_API_SECRET,
};
const DAILY_CAP = 40;          // your own limit per number, from your operations sheet
const sentToday = new Map();   // instance id -> count (persist it in a database in production)
let cursor = 0;

async function connectedInstances() {
  const res = await fetch(BASE + "/instances", { headers: H });
  if (!res.ok) throw new Error("GET /instances failed: HTTP " + res.status);
  const list = await res.json();
  return list.filter((i) => i.status === "CONNECTED");
}

function pickInstance(pool) {
  for (let n = 0; n < pool.length; n++) {
    const inst = pool[(cursor + n) % pool.length];
    if ((sentToday.get(inst.id) || 0) < DAILY_CAP) {
      cursor = (cursor + n + 1) % pool.length;
      return inst;
    }
  }
  return null; // every number hit its cap: stop and try again tomorrow
}

export async function sendBalanced(number, text) {
  const pool = await connectedInstances();
  const inst = pickInstance(pool);
  if (!inst) throw new Error("no instance available under the daily cap");
  const res = await fetch(BASE + "/" + inst.id + "/send/text", {
    method: "POST",
    headers: H,
    body: JSON.stringify({ number, text }),
  });
  if (res.status === 429) throw new Error("rate limited, back off on " + inst.name);
  if (!res.ok) throw new Error("send failed on " + inst.name + ": HTTP " + res.status);
  sentToday.set(inst.id, (sentToday.get(inst.id) || 0) + 1);
  return { instance: inst.name, status: res.status };
}

Ritmo, 429 y caídas: lo que el código no resuelve solo

La referencia lista 429 como límite de solicitudes excedido. Trátalo como señal para retroceder en ese número y seguir por los otros, en vez de repetir la llamada en bucle. Si todos llegan al tope, la respuesta correcta es parar y retomar al día siguiente, no subir el tope.

No distribuyas ráfagas idénticas: varía el texto, espacia los envíos y prefiere conversaciones a disparos. La API tiene opciones de retraso por mensaje, y el envío por lista en /sender/simple acepta retrasos mínimo y máximo; úsalos en vez de dormir en tu código cuando sea una campaña programada.

Costo y seguimiento

Más números no cambian el precio unitario: R$15 por número activo al mes, prepago, sin cobro por mensaje, así que repartir la carga entre 4 números cuesta R$60 al mes, sea cual sea el volumen. Antes de crear más instancias, consulta el costo en GET /instances/cost, que muestra la tarifa de activación y el saldo necesario.

Registra, por número y por día: enviadas, respuestas y fallas. Un número con tasa de respuesta cayendo y fallas subiendo retrocede una fase. Para ver el precio a escala, mira costo por número y volumen y la página de precios. Para el perfil de quien opera así, mira agencias con IA y gestores de tráfico.

Resumen rápido

  • La API no trae un balanceador listo: la rotación es lógica tuya, sobre GET /instances y send/text.
  • Rotación solo entre números conectados, con tope diario por número y el mismo contacto siempre en el mismo número.
  • 429 y caída de estado sacan al número de la fila al instante; si todos se pasan, para, no subas el tope.
  • Repartir la carga no sustituye el consentimiento ni el calentamiento, y el riesgo del canal no oficial continúa.
  • El costo es lineal: R$15 por número activo al mes, sin cobro por mensaje.

Lee también

Preguntas frecuentes

¿ZapZap tiene rotación de números lista en la API?

No hay un endpoint de rotación en la referencia. La distribución se hace en tu sistema, eligiendo la instancia antes de llamar a send/text, como en el ejemplo de la guía.

¿Qué tope diario debo usar por número?

La API no publica un tope único. Define el tuyo por fase del chip: un número nuevo conversa solo con quien ya conoce al cliente, un número maduro recibe más volumen poco a poco. Mira la guía de calentamiento.

¿Puedo cambiar el número de quien ya conversó?

Evítalo. El contacto espera hablar con el mismo número, y el cambio se vuelve ruido y reportes. La rotación es para contactos nuevos.

¿Dividir entre varios números evita el bloqueo?

No. Reduce la concentración de riesgo, pero ZapZap es una solución no oficial y WhatsApp puede limitar o bloquear cualquier número.

¿Cuánto cuesta operar 5 números en rotación?

R$75 al mes (5 x R$15), prepago y sin cobro por mensaje, más la tarifa de activación única por instancia creada, que consultas en GET /instances/cost.

Prueba la rotación con dos números

Crea la cuenta, conecta dos números y ejecuta el ejemplo. R$15 por número activo al mes, sin cobro por mensaje. Al verificar el teléfono hay un crédito de bienvenida, sujeto a la campaña vigente.