# Link wa.me e QR code: far scrivere gli utenti al tuo agente AI

> Come creare un link wa.me con messaggio precompilato, trasformarlo in QR code e capire quale utente ha scritto, con TypeScript funzionante e l'API di whasp.

Source: https://whasp.ai/it/blog/link-wa-me-qr-code-whatsapp · 2026-10-20

## In breve

- Un link wa.me è https://wa.me/ più il numero completo in formato internazionale, senza segno più, zeri, parentesi o trattini, e ?text= aggiunge un messaggio codificato come URL che compare nella casella di testo dell'utente.
- L'utente deve comunque toccare invio e può modificare il testo precompilato, quindi un codice al suo interno è una dichiarazione da confrontare con i tuoi dati, non una prova d'identità.
- Con whasp, GET /v1/numbers/pick restituisce il numero con più spazio libero e un wa_link già pronto, così ogni chat inizia con l'utente che scrive per primo.
- Un QR code è lo stesso link codificato, e tutto ciò che stampi dovrebbe codificare un tuo URL di redirect, perché i numeri si riempiono e possono essere sostituiti.

Un link wa.me è l'URL di click-to-chat di WhatsApp. Il formato è `https://wa.me/<numero>`, dove il numero è in formato internazionale completo, senza segno più, zeri, parentesi o trattini, e `?text=` aggiunge un primo messaggio codificato come URL. Toccando il link si apre una chat con il numero del tuo agente: l'utente scrive per primo e il tuo agente può rispondere.

## Qual è il formato esatto di un link wa.me?

La [pagina di aiuto di WhatsApp su click to chat](https://faq.whatsapp.com/5913398998672934) documenta tre forme:

```text
https://wa.me/15555550100
https://wa.me/15555550100?text=Ciao%20Ava
https://wa.me/?text=Ciao%20Ava
```

Il primo apre una chat con quel numero. Il secondo mette anche il testo nella casella del messaggio. Il terzo non ha un numero: WhatsApp mostra un elenco di contatti a cui inviare il messaggio, quindi serve a condividere, non ad avviare una chat con il tuo agente.

La regola sul numero in quella pagina è «un numero di telefono completo in formato internazionale», senza zeri iniziali, parentesi o trattini. Come esempio di ciò che non va usato, la pagina riporta `https://wa.me/+001-(XXX)XXXXXXX`. whasp restituisce i numeri in formato E.164 (`+15555550100`), quindi togli il segno più.

Tre comportamenti da conoscere:

- Il link funziona sui telefoni e su WhatsApp Web.
- Funziona anche per un numero che non è in rubrica all'utente, purché abbia un account WhatsApp attivo.
- Il testo precompilato finisce nella casella di testo. Non viene inviato. L'utente tocca invio e prima può modificare o cancellare il testo.

## Come si costruisce il link nel codice?

Per costruire il link, togli dal numero E.164 ogni carattere che non sia una cifra, poi codifica il testo come URL. Non incollare mai il testo grezzo nell'URL: una `&` chiude il parametro in anticipo e un `#` inizia un frammento. [`encodeURIComponent`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) gestisce entrambi i casi.

```ts
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)}` : "");
}
```

Quattro errori da evitare:

- Lasciare nel numero il segno più, uno `00` iniziale o gli spazi. La pagina di WhatsApp dice di toglierli.
- Saltare la codifica, così una `&` nel messaggio taglia il testo a metà.
- Costruire il link una volta sola e metterlo in cache. I numeri si riempiono e vengono sostituiti.
- Trattare il messaggio precompilato come se fosse già inviato. Resta nella casella di testo finché l'utente non tocca invio.

Tieni il testo precompilato breve e semplice. La pagina di WhatsApp non indica un limite di lunghezza, ma Meta limita il testo precompilato a 140 caratteri nei propri QR code e link brevi, un tetto sensato per qualunque messaggio d'ingresso.

Evita le emoji in quel testo. Il 19 ottobre 2026 abbiamo richiesto link `wa.me` con emoji in `?text=` e il redirect verso `api.whatsapp.com/send` è tornato con le emoji sostituite dal carattere sostitutivo Unicode (`%EF%BF%BD`). Le lettere latine accentate sono passate intatte, e lo stesso testo inviato direttamente a `api.whatsapp.com/send` ha mantenuto le emoji. Puoi ripetere la verifica:

```bash
curl -sI "https://wa.me/15555550100?text=Ciao%20%F0%9F%91%8B" | grep -i location
```

WhatsApp può cambiare questo comportamento, quindi prova su telefoni veri prima di fare affidamento su uno dei due.

## Come si crea un QR code per un link wa.me?

Un QR code per click-to-chat è il link stesso, codificato. Generalo dall'URL completo con una qualsiasi libreria per QR code e mostralo nelle pagine desktop, dove l'utente non ha il telefono in mano. La fotocamera del telefono legge un QR code che contiene un URL e propone di aprirlo, e wa.me passa poi la chat a WhatsApp. La documentazione di Meta descrive lo stesso flusso di scansione con la fotocamera per i propri QR code.

```ts
import QRCode from "qrcode";

const link = waLink("+15555550100", "Ciao Ava");
const svg = await QRCode.toString(link, { type: "svg", margin: 2, errorCorrectionLevel: "M" });
await QRCode.toFile("ava.png", link, { width: 512, margin: 2 });
```

Quello usato qui è il [pacchetto `qrcode`](https://github.com/soldair/node-qrcode). Usa l'SVG per la stampa, perché si ingrandisce senza sfocarsi (la documentazione di Meta sui QR code dà lo stesso consiglio), e il PNG per gli schermi. Un URL più corto dà un codice più semplice, che si scansiona meglio. Prova il codice stampato alla dimensione finale, su due o tre telefoni diversi, prima di ordinare mille adesivi.

Non confonderlo con i [QR code e link brevi](https://developers.facebook.com/docs/whatsapp/business-management-api/qr-codes) di Meta. Quella funzione appartiene alla WhatsApp Business Platform: fino a 2.000 per numero di telefono aziendale, testo precompilato fino a 140 caratteri, nessuna analisi delle scansioni, gestione tramite la Business Management API. Un numero whasp è un account WhatsApp personale, quindi si usano normali link wa.me.

## Come fa il tuo agente a sapere chi ha appena scritto?

Un evento `message.received` porta il numero di telefono del mittente (`chat`), il suo nome su WhatsApp (`sender_name`) e il testo. Non porta il tuo id utente. Se la persona ha cliccato un pulsante dentro la tua app, vuoi collegare le due cose. Metti un codice monouso nel testo precompilato.

```ts
import { randomBytes } from "node:crypto";

const API = "https://api.whasp.ai/v1";
const pending = new Map<string, { userId: string; expires: number }>(); // usa il tuo database

export async function startChat(userId: string) {
  const code = randomBytes(3).toString("hex"); // es. "9f3a1c"
  pending.set(code, { userId, expires: Date.now() + 24 * 60 * 60 * 1000 });

  const text = `Ciao Ava, il mio codice è ${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: tutti i numeri sono pieni, offline o non in salute
  if (!res.ok) throw new Error(`whasp answered ${res.status}`);
  return (await res.json()) as { number: string; wa_link: string };
}

// Nel tuo gestore di message.received: chi è questa persona?
export function claimCode(text: string): string | null {
  const code = /il mio codice è ([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); // monouso
  return hit.userId;
}
```

Quando `claimCode` restituisce un id utente, salva la coppia: la `chat` del mittente, il `number` che ha ricevuto il messaggio e il tuo utente. Da quel momento riconosci la persona dal numero di telefono. La gestione del webhook in sé (verifica della firma, deduplica sull'id dell'evento) è in [Webhook WhatsApp: verifica della firma, retry e duplicati](https://whasp.ai/it/blog/webhook-whatsapp-firma-retry-duplicati).

Il codice è una dichiarazione, non una prova. L'utente può modificare il testo, e chiunque riceva il link può inviarlo. Fallo monouso e di breve durata, rendilo opaco (mai un indirizzo email o un token) e non mettere mai un segreto in un link che finisce nella cronologia del browser e in una chat.

## Come sceglie whasp il numero nel link?

`GET /v1/numbers/pick` di whasp restituisce il numero in salute e online con più spazio per un nuovo utente, più un `wa_link` con il tuo `text` già precompilato. Risponde 409 `no_capacity` quando tutti i numeri sono pieni, offline o non in salute. Un numero accoglie fino a 100 chat attive in 30 giorni e 40 nuove chat in 24 ore, poi esce da `pick` (i messaggi in arrivo continuano a funzionare). Chiama `pick` quando l'utente chiede la chat, non al momento della build e non una sola volta per un'intera campagna.

Gli utenti che tornano devono ritrovare lo stesso numero. L'evento `message.received` include il `number` che l'ha ricevuto, e un invio senza `from` parte dal numero a cui la persona ha scritto per ultimo. Salvalo insieme all'utente e costruisci il suo prossimo link con `waLink(number, text)`.

Anche i numeri cambiano. Se WhatsApp ne banna uno, whasp lo ritira e ti dà un sostituto. Le chat non si spostano e il nuovo numero non può scrivere per primo, quindi un link che punta al vecchio numero è morto. Genera i link al momento e leggi [Come spostare gli utenti su un nuovo numero WhatsApp dopo un ban](https://whasp.ai/it/blog/spostare-utenti-nuovo-numero-whatsapp-ban) per la procedura completa. [Scalare un agente AI su WhatsApp: quanti numeri servono](https://whasp.ai/it/blog/scalare-agente-ai-whatsapp-piu-numeri) tratta la capacità.

## Perché conviene che gli utenti scrivano per primi?

Un numero whasp non può aprire una chat: un invio a qualcuno che non ha mai scritto restituisce 409 `chat_not_open`. Il link e il QR code sono la porta d'ingresso. Tengono anche il numero in salute. Gli sviluppatori che usano librerie non ufficiali segnalano da almeno marzo 2026 l'[errore 463, il «reachout timelock»](https://github.com/WhiskeySockets/Baileys/issues/2441), e la teoria più diffusa lo collega ai messaggi mandati a persone che non avevano mai scritto. [Errore 463 WhatsApp e reachout timelock](https://whasp.ai/it/blog/errore-463-whatsapp-reachout-timelock) separa ciò che è confermato da ciò che è teoria. Con click to chat, ogni conversazione parte da un messaggio in arrivo, e un messaggio precompilato dà subito al tuo agente il primo input.

## Dove vanno messi il link e il QR code?

| Dove | Cosa mostrare | Perché |
| --- | --- | --- |
| Pagina di conferma dopo la registrazione, su telefono | Un pulsante con il link per quell'utente | Un tocco, codice incluso |
| Stessa pagina, su un browser desktop | Un QR code di quel link, accanto al pulsante | Il passaggio lo fa la fotocamera del telefono |
| Email di benvenuto | Un pulsante che punta a un tuo URL | Il link viene costruito al clic, quindi non scade mai e non punta a un numero ritirato |
| Stampa, packaging, profili social | Un QR code del tuo URL, non del link wa.me | Puoi cambiare il numero dietro il QR senza ristampare |

Per le ultime due righe, punta a un redirect sul tuo dominio che chiede a whasp un numero aggiornato e manda avanti il visitatore:

```ts
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("Ciao 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("Tutti i nostri numeri sono occupati. Riprova tra qualche minuto.");
  }
}).listen(3000);
```

Un visitatore anonimo non ha un codice, quindi lascia che sia l'agente a chiedere ciò che gli serve quando la chat è aperta. Per un utente noto, come nella riga dell'email, fai chiamare al redirect `startChat(userId)` della sezione precedente invece di usare un testo fisso. WhatsApp pubblica anche un pulsante ufficiale «Chat on WhatsApp» in verde e bianco, e la sua pagina di aiuto dice di usarlo senza modifiche.

## Cosa fare adesso

Crea un numero nella dashboard, poi segui il [quickstart](https://whasp.ai/docs#quickstart) per ricevere il primo evento `message.received`. Aggiungi al tuo sito il redirect qui sopra, metti il suo URL dietro un pulsante e un QR code, e controlla l'intero percorso su un iPhone e su un telefono Android. Se stai costruendo un companion, [Come creare un AI companion su WhatsApp](https://whasp.ai/it/blog/creare-ai-companion-whatsapp) mostra dove si inserisce questo link nell'onboarding.

## Domande

### Come si crea un link WhatsApp con un messaggio precompilato?

Usa https://wa.me/<numero>?text=<testocodificato>, dove il numero è in formato internazionale completo e il testo è codificato come URL. Nel codice, costruisci la parte del testo con encodeURIComponent. Il messaggio compare nella casella di testo e l'utente tocca invio.

### Un link wa.me funziona se il numero non è salvato tra i contatti dell'utente?

Sì. La pagina di aiuto di WhatsApp dice che click to chat avvia una chat anche senza il numero salvato in rubrica, purché il numero abbia un account WhatsApp attivo. Funziona sui telefoni e su WhatsApp Web.

### Come trasformo un link wa.me in un QR code?

Un QR code per click-to-chat è semplicemente l'URL codificato. Passa il link wa.me completo a una qualsiasi libreria per QR code, per esempio il pacchetto qrcode per Node, ed esporta in SVG per la stampa o in PNG per gli schermi.

### Posso mettere emoji nel messaggio precompilato di un link wa.me?

Provaci prima. Quando abbiamo controllato, il 19 ottobre 2026, wa.me sostituiva le emoji nel testo con un carattere sostitutivo, mentre le lettere latine accentate passavano intatte. Il testo semplice è la scelta sicura.

### Il mio agente whasp può scrivere a un utente prima che sia lui a farlo?

No. Un numero whasp non può aprire una chat a freddo e l'API risponde 409 chat_not_open. L'utente scrive per primo, e un link wa.me o un QR code è il modo per farglielo fare.
