Dev

Cómo enviar un mensaje de WhatsApp por API (Node.js, Python y PHP)

Enviar un mensaje de WhatsApp desde código es una llamada HTTP. Apuntas a tu instancia, indicas la clave y el secreto de la API y envías el número con código de país y el texto. Abajo hay ejemplos que puedes copiar en cuatro lenguajes, más los cuidados que evitan dolores de cabeza cuando el envío pasa de la prueba a producción.

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

Qué necesitas antes de enviar

Son cuatro cosas: una cuenta en ZapZap, una instancia (el número de WhatsApp) conectada por código QR en el panel, la clave y el secreto de la API, y el ID de la instancia. La clave (x-api-key) y el secreto (x-api-secret) están en el panel, en Configuración y API, y el ID de la instancia aparece en la lista de instancias.

Toda solicitud lleva las dos cabeceras de autenticación. No hay OAuth ni sesión: la documentación de autenticación muestra el formato completo. El secreto es solo para tu servidor. Nunca lo pongas en código que se ejecuta en el navegador o en la aplicación del cliente.

Primera prueba con cURL

Antes de escribir código, confirma que todo funciona con una llamada directa. Cambia los valores en mayúsculas por los tuyos. El número va con código de país y solo dígitos (55 para Brasil, luego código de área y número).

cURL

curl -X POST https://api.zapzapapi.com/api/v1/SEU_INSTANCE_ID/send/text \
  -H "Content-Type: application/json" \
  -H "x-api-key: SUA_API_KEY" \
  -H "x-api-secret: SEU_API_SECRET" \
  -d '{"number":"5511999999999","text":"Olá! Teste de envio pela API."}'

Enviar un mensaje de WhatsApp con Node.js

En Node.js 18 o superior, fetch ya viene incluido, así que no hay que instalar nada. Guarda las credenciales en variables de entorno.

Node.js

const resposta = await fetch(
  `https://api.zapzapapi.com/api/v1/${process.env.ZAPZAP_INSTANCE_ID}/send/text`,
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": process.env.ZAPZAP_API_KEY,
      "x-api-secret": process.env.ZAPZAP_API_SECRET,
    },
    body: JSON.stringify({
      number: "5511999999999",
      text: "Olá! Seu pedido saiu para entrega.",
    }),
  },
);

if (!resposta.ok) {
  throw new Error(`Falha ${resposta.status}: ${await resposta.text()}`);
}
console.log(await resposta.json());

Enviar un mensaje de WhatsApp con Python

En Python, la biblioteca requests lo deja corto. Define siempre un timeout para que la llamada no se quede colgada.

Python

import os
import requests

url = f"https://api.zapzapapi.com/api/v1/{os.environ['ZAPZAP_INSTANCE_ID']}/send/text"
cabecalhos = {
    "Content-Type": "application/json",
    "x-api-key": os.environ["ZAPZAP_API_KEY"],
    "x-api-secret": os.environ["ZAPZAP_API_SECRET"],
}
corpo = {"number": "5511999999999", "text": "Olá! Sua consulta está confirmada."}

resposta = requests.post(url, json=corpo, headers=cabecalhos, timeout=30)
resposta.raise_for_status()
print(resposta.json())

Enviar un mensaje de WhatsApp con PHP

En PHP, el cURL nativo resuelve, sin biblioteca extra.

PHP

<?php
$url = "https://api.zapzapapi.com/api/v1/" . getenv("ZAPZAP_INSTANCE_ID") . "/send/text";

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTPHEADER => [
        "Content-Type: application/json",
        "x-api-key: " . getenv("ZAPZAP_API_KEY"),
        "x-api-secret: " . getenv("ZAPZAP_API_SECRET"),
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "number" => "5511999999999",
        "text" => "Olá! Seu boleto vence amanhã.",
    ]),
]);

$resposta = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status >= 400) {
    throw new RuntimeException("Falha $status: $resposta");
}
echo $resposta;

Buenas prácticas antes de ir a producción

Valida el número antes de enviar: código de país más código de área más número, solo dígitos. Un número mal formado es el error más común y el más fácil de evitar. Trata la respuesta: un estado 4xx casi siempre es un problema de la solicitud y repetirla igual no ayuda, mientras que un fallo de red o un 5xx se puede repetir algunas veces con esperas crecientes.

Mantén el secreto en el servidor y ejecuta la llamada en una cola o tarea en segundo plano, no dentro del clic del usuario, para que un envío lento no bloquee tu pantalla. La API responde de forma síncrona, y cada envío muestra el indicador de escribiendo antes de entregar, con duración proporcional al largo del texto, lo que lo hace más natural.

Respeta el ritmo. Enviar muchos mensajes iguales seguidos a personas que no los esperan es el patrón que más lleva a denuncias. Ninguna técnica elimina el riesgo de bloqueo, pero calentar el número, variar el texto y enviar solo a quien aceptó recibir reduce la probabilidad. La guía antibloqueo detalla cada punto.

Próximos pasos: recibir respuestas e integrar

Enviar es la mitad del flujo. Para recibir las respuestas de los clientes, configura un webhook y trata los eventos en tu sistema, como muestra la documentación de webhooks. Si usas herramientas no-code, mira las integraciones con n8n, Make y otras, que hacen ese mismo envío sin escribir código.

Resumen rápido

  • El envío es un POST a /api/v1/{instanceId}/send/text con x-api-key y x-api-secret.
  • El cuerpo mínimo tiene number (con código de país, solo dígitos) y text.
  • Guarda la clave y el secreto en el servidor, en variables de entorno.
  • Trata los errores: no repitas un 4xx igual, repite un 5xx con esperas crecientes.
  • Ningún método elimina el riesgo de bloqueo: consentimiento, calentamiento y ritmo ayudan.

Preguntas frecuentes

¿Cómo enviar un mensaje de WhatsApp por API en PHP, Python o Node.js?

Haz un POST a https://api.zapzapapi.com/api/v1/{instanceId}/send/text con las cabeceras x-api-key y x-api-secret y un cuerpo JSON con number (con código de país) y text. El artículo trae el código listo para cURL, Node.js, Python y PHP.

¿Necesito OAuth o un token que expira?

No. La API v1 usa solo la clave y el secreto enviados en las cabeceras de cada solicitud. Guarda el secreto en el servidor y nunca en el navegador.

¿En qué formato va el número de teléfono?

Solo dígitos, con código de país y código de área. Para Brasil, 55 más el código de área y el número, por ejemplo 5511999999999.

¿La API cobra por mensaje enviado?

En ZapZap el valor es por número activo al mes, prepago, sin cobro por mensaje. Mira los detalles en la [página de precios](/precos).

¿Se puede desactivar el indicador de escribiendo?

Sí, enviando digitando como false en el cuerpo de la solicitud cuando necesitas una respuesta casi inmediata. Por defecto queda activado y hace el envío más natural.

Empieza ahora

Crea tu cuenta, conecta un número en minutos y prueba la API con calentamiento y anti-bloqueo. R$15 por número activo/mes, prepago, sin permanencia.