Enlace wa.me con mensaje prellenado y código QR para tu agente
Cómo crear un enlace wa.me de WhatsApp con mensaje prellenado, convertirlo en código QR y saber qué usuario escribió, con TypeScript funcional y la API de whasp.

Lo esencial
- Un enlace wa.me es https://wa.me/ más el número completo en formato internacional, sin signo más, ceros, paréntesis ni guiones, y ?text= añade un mensaje codificado como URL que aparece en el cuadro de texto del chat del usuario.
- El usuario aún tiene que tocar enviar y puede editar el texto prellenado, así que un código dentro de él es una afirmación que debes contrastar con tus registros, no una prueba de identidad.
- Con whasp, GET /v1/numbers/pick devuelve el número con más margen y un wa_link listo para usar, de modo que cada chat empieza con el usuario escribiendo primero.
- Un código QR es el mismo enlace codificado, y todo lo que imprimas debe codificar tu propia URL de redirección, porque los números se llenan y pueden ser reemplazados.
Un enlace wa.me es la URL de clic para chatear de WhatsApp. El formato es https://wa.me/<número>, donde el número va en formato internacional completo, sin signo más, ceros, paréntesis ni guiones, y ?text= añade un primer mensaje codificado como URL. Al tocar el enlace se abre un chat con el número de tu agente, así que el usuario escribe primero y tu agente puede responder.
¿Cuál es el formato exacto del enlace wa.me?
La página de ayuda de clic para chatear de WhatsApp documenta tres formas:
https://wa.me/15555550100
https://wa.me/15555550100?text=Hola%20Ava
https://wa.me/?text=Hola%20Ava
La primera abre un chat con ese número. La segunda además pone el texto en el cuadro de mensaje. La tercera no lleva número: WhatsApp muestra una lista de contactos a los que enviar el mensaje, así que sirve para compartir, no para iniciar un chat con tu agente.
La regla del número en esa página es “un número de teléfono completo en formato internacional”, sin ceros, paréntesis ni guiones. Su ejemplo de lo que no se debe usar es https://wa.me/+001-(XXX)XXXXXXX. whasp devuelve los números en formato E.164 (+15555550100), así que quita el signo más.
Tres comportamientos que conviene conocer:
- El enlace funciona en teléfonos y en WhatsApp Web.
- Funciona con un número que no está en la agenda del usuario, siempre que el número tenga una cuenta de WhatsApp activa.
- El texto prellenado queda en el campo de texto. No se envía. El usuario toca enviar, y antes puede editar o borrar el texto.
¿Cómo se construye el enlace en código?
Para construir el enlace, quita del número E.164 todo lo que no sea un dígito y después codifica el texto como URL. Nunca pegues texto en bruto en la URL: un & corta el parámetro antes de tiempo y un # abre un fragmento. encodeURIComponent resuelve ambos casos.
export function waLink(e164: string, text?: string): string {
const digits = e164.replace(/\D/g, "").replace(/^0+/, ""); // "+1 555 555 0100" -> "15555550100"
return `https://wa.me/${digits}` + (text ? `?text=${encodeURIComponent(text)}` : "");
}
Cuatro errores que evitar:
- Dejar el signo más, un
00inicial o espacios en el número. La página de WhatsApp indica que se quiten. - Saltarse la codificación, de modo que un
&en el mensaje corta el texto. - Construir el enlace una vez y guardarlo en caché. Los números se llenan y se reemplazan.
- Dar el mensaje prellenado por enviado. Queda en el campo de texto hasta que el usuario toca enviar.
Mantén el texto prellenado corto y sencillo. La página de WhatsApp no indica un límite de longitud para él, pero Meta limita el texto prellenado a 140 caracteres en sus propios códigos QR y enlaces cortos, un tope razonable para cualquier mensaje de entrada.
Evita los emojis en ese texto. El 19 de octubre de 2026 solicitamos enlaces wa.me con emojis en ?text= y la redirección a api.whatsapp.com/send devolvió los emojis sustituidos por el carácter de reemplazo de Unicode (%EF%BF%BD). Las letras latinas con acento llegaron intactas, y el mismo texto enviado directamente a api.whatsapp.com/send conservó el emoji. Puedes repetir la comprobación:
curl -sI "https://wa.me/15555550100?text=Hola%20%F0%9F%91%8B" | grep -i location
WhatsApp puede cambiar este comportamiento, así que prueba en teléfonos reales antes de depender de uno u otro.
¿Cómo se hace un código QR para un enlace wa.me?
Un código QR de clic para chatear es el propio enlace, codificado. Genéralo a partir de la URL completa con cualquier librería de QR y muéstralo en las páginas de escritorio, donde el usuario no tiene el teléfono en la mano. La cámara del teléfono lee un código QR que contiene una URL y ofrece abrirla, y wa.me entrega entonces el chat a WhatsApp. La documentación de Meta describe el mismo flujo de escanear con la cámara para sus propios códigos QR.
import QRCode from "qrcode";
const link = waLink("+15555550100", "Hola Ava");
const svg = await QRCode.toString(link, { type: "svg", margin: 2, errorCorrectionLevel: "M" });
await QRCode.toFile("ava.png", link, { width: 512, margin: 2 });
Ese es el paquete qrcode. Usa el SVG para imprimir, porque escala sin perder nitidez (la documentación de códigos QR de Meta hace la misma recomendación), y el PNG para pantallas. Una URL más corta da un código más simple, que se escanea con más facilidad. Prueba el código impreso a su tamaño final, en dos o tres teléfonos distintos, antes de encargar mil pegatinas.
No lo confundas con los códigos QR y enlaces cortos propios de Meta. Esa función pertenece a la WhatsApp Business Platform: hasta 2.000 por número de teléfono de empresa, texto prellenado de hasta 140 caracteres, sin analíticas de escaneo, y se gestiona con la Business Management API. Un número de whasp es una cuenta personal de WhatsApp, así que usas enlaces wa.me normales.
¿Cómo sabe tu agente quién acaba de escribir?
Un evento message.received lleva el número de teléfono del remitente (chat), su nombre de WhatsApp (sender_name) y el texto. No lleva el id de tu usuario. Si la persona tocó un botón dentro de tu app, quieres conectar ambos datos. Pon un código de un solo uso en el texto prellenado.
import { randomBytes } from "node:crypto";
const API = "https://api.whasp.ai/v1";
const pending = new Map<string, { userId: string; expires: number }>(); // usa tu base de datos
export async function startChat(userId: string) {
const code = randomBytes(3).toString("hex"); // p. ej. "9f3a1c"
pending.set(code, { userId, expires: Date.now() + 24 * 60 * 60 * 1000 });
const text = `Hola Ava, mi código es ${code}`;
const res = await fetch(`${API}/numbers/pick?text=${encodeURIComponent(text)}`, {
headers: { Authorization: `Bearer ${process.env.WHASP_API_KEY}` },
});
if (res.status === 409) return null; // no_capacity: todos los números están llenos, sin conexión o con problemas de salud
if (!res.ok) throw new Error(`whasp answered ${res.status}`);
return (await res.json()) as { number: string; wa_link: string };
}
// En tu manejador de message.received: ¿quién es?
export function claimCode(text: string): string | null {
const code = /mi c[oó]digo es ([0-9a-f]{6})\b/i.exec(text)?.[1]?.toLowerCase();
const hit = code ? pending.get(code) : undefined;
if (!code || !hit || hit.expires < Date.now()) return null;
pending.delete(code); // de un solo uso
return hit.userId;
}
Cuando claimCode devuelve un id de usuario, guarda el trío: el chat del remitente, el number que recibió el mensaje y tu usuario. A partir de ahí, reconoce a esa persona por su número de teléfono. El manejo del webhook en sí (verificación de la firma, deduplicación por el id del evento) está en Webhook de WhatsApp: firma, reintentos y eventos duplicados.
El código es una afirmación, no una prueba. El usuario puede editar el texto, y cualquiera que reciba el enlace puede enviarlo. Hazlo de un solo uso y de corta duración, opaco (nunca una dirección de correo ni un token), y no pongas nunca un secreto en un enlace que acaba en el historial del navegador y en un chat.
¿Cómo elige whasp el número del enlace?
GET /v1/numbers/pick de whasp devuelve el número sano y conectado con más margen para un usuario nuevo, además de un wa_link con tu text prellenado. Responde 409 no_capacity cuando todos los números están llenos, sin conexión o con problemas de salud. Un número admite hasta 100 chats activos en 30 días y 40 chats nuevos en 24 horas, y después deja de aparecer en pick (los mensajes entrantes siguen llegando). Llama a pick cuando el usuario pide el chat, no al compilar y no una sola vez para toda una campaña.
Los usuarios que vuelven deben regresar al mismo número. El evento message.received incluye el number que lo recibió, y un envío sin from sale del número al que la persona escribió por última vez. Guárdalo junto al usuario y construye su siguiente enlace con waLink(number, text).
Los números también cambian. Si WhatsApp banea uno, whasp lo retira y te da un reemplazo. Los chats no se trasladan, y el número nuevo no puede escribir primero, así que un enlace que apunta al número antiguo está muerto. Genera los enlaces bajo demanda y lee Cómo migrar usuarios a un número nuevo de WhatsApp tras un baneo para ver la guía completa. ¿Cuántos números de WhatsApp necesita tu agente de IA? trata la capacidad.
¿Por qué ayuda que los usuarios escriban primero?
Un número de whasp no puede abrir un chat: un envío a alguien que nunca escribió devuelve 409 chat_not_open. El enlace y el código QR son la puerta de entrada. También mantienen sano el número. Desarrolladores que usan librerías no oficiales informan del error 463, el “reachout timelock”, desde al menos marzo de 2026, y la teoría más extendida lo relaciona con escribir a personas que nunca te habían escrito. Error 463 de WhatsApp y el reachout timelock, explicado separa lo confirmado de lo teórico. Con clic para chatear, toda conversación empieza con un mensaje entrante, y un mensaje prellenado da a tu agente su primera entrada de inmediato.
¿Dónde deben ir el enlace y el código QR?
| Dónde | Qué mostrar | Por qué |
|---|---|---|
| Página de registro completado, en un teléfono | Un botón con el enlace de cada usuario | Un toque, con el código incluido |
| La misma página, en un navegador de escritorio | Un código QR de ese enlace, junto al botón | La cámara del teléfono hace el traspaso |
| Correo de bienvenida | Un botón que apunta a tu propia URL | El enlace se construye al hacer clic, así que nunca caduca ni apunta a un número retirado |
| Impresión, embalaje, perfiles en redes sociales | Un código QR de tu propia URL, no del enlace wa.me | Puedes cambiar el número que hay detrás sin reimprimir |
Para las dos últimas filas, apunta a una redirección en tu propio dominio que pida un número nuevo a whasp y reenvíe al visitante:
import { createServer } from "node:http";
createServer(async (req, res) => {
if (req.url !== "/chat") return void res.writeHead(404).end();
const pick = await fetch(`https://api.whasp.ai/v1/numbers/pick?text=${encodeURIComponent("Hola Ava")}`, {
headers: { Authorization: `Bearer ${process.env.WHASP_API_KEY}` },
});
if (pick.ok) {
const { wa_link } = (await pick.json()) as { wa_link: string };
res.writeHead(302, { Location: wa_link }).end();
} else {
res.writeHead(503).end("Todos nuestros números están ocupados. Inténtalo de nuevo en unos minutos.");
}
}).listen(3000);
Un visitante anónimo no tiene código, así que deja que el agente pida lo que necesite cuando el chat esté abierto. Para un usuario conocido, como en la fila del correo, haz que la redirección llame a startChat(userId) de la sección anterior en lugar de usar un texto fijo. WhatsApp también publica un botón oficial “Chat on WhatsApp” en verde y blanco, y su página de ayuda indica usarlo sin modificarlo.
¿Qué hacer ahora?
Crea un número en el panel y sigue el inicio rápido para recibir el primer evento message.received. Añade a tu sitio la redirección de arriba, pon su URL detrás de un botón y de un código QR, y comprueba el recorrido completo en un iPhone y en un teléfono Android. Si estás construyendo un compañero, Cómo lanzar un compañero de IA en WhatsApp muestra dónde encaja este enlace en el onboarding.
Preguntas
¿Cómo creo un enlace de WhatsApp con un mensaje prellenado?
Usa https://wa.me/<número>?text=<textocodificado>, donde el número va en formato internacional completo y el texto está codificado como URL. En código, construye la parte del texto con encodeURIComponent. El mensaje aparece en el cuadro de texto del chat y el usuario toca enviar.
¿Funciona un enlace wa.me si el número no está guardado en los contactos del usuario?
Sí. La página de ayuda de WhatsApp dice que clic para chatear inicia un chat sin que el número esté guardado en la agenda, siempre que el número tenga una cuenta de WhatsApp activa. Funciona en teléfonos y en WhatsApp Web.
¿Cómo convierto un enlace wa.me en un código QR?
Un código QR de clic para chatear es simplemente la URL codificada. Pasa el enlace wa.me completo a cualquier librería de QR, por ejemplo el paquete qrcode para Node, y exporta SVG para imprimir o PNG para pantallas.
¿Puedo poner emojis en un mensaje prellenado de wa.me?
Pruébalo antes. Cuando lo comprobamos el 19 de octubre de 2026, wa.me sustituyó los emojis del texto por un carácter de reemplazo, mientras que las letras latinas con acento se conservaron. El texto plano es la opción segura.
¿Puede mi agente de whasp escribir a un usuario antes de que él escriba?
No. Un número de whasp no puede abrir un chat en frío y la API responde 409 chat_not_open. El usuario escribe primero, y un enlace wa.me o un código QR es la forma de lograr que lo haga.


