---
title: "Inviare un messaggio WhatsApp via API: cURL, Node, Python, PHP"
description: "Come inviare un messaggio WhatsApp con una API: esempi in cURL, Node.js, Python e PHP per template e messaggi di sessione, con stati ed errori."
canonical: "https://omnichannels.ai/it/blog/send-whatsapp-message-api-examples/"
language: "it"
updated: "2026-10-16"
publisher: "BroadNet Technologies"
brand: "OmniChannels.ai"
category: "integration"
primaryQuery: "send whatsapp message api"
keywords: ["esempio api whatsapp curl", "inviare template whatsapp node.js", "api whatsapp python", "api whatsapp php", "whatsapp business api invio messaggi", "messaggio di sessione whatsapp api", "api whatsapp multipart form-data"]
published: "2026-10-16"
author: "OmniChannels.ai Editorial Team"
reviewer: "BroadNet Messaging Solutions Team"
readingMinutes: 10
answer: "Con l'API di OmniChannels.ai inviate ogni messaggio WhatsApp tramite un unico endpoint, POST https://api.broadnet.me/whatsapp/message/sendbulk, come multipart form data con un header Authorization: Bearer. Il campo messageType seleziona il payload: TEMPLATE per i template approvati, necessari per avviare una conversazione o scrivere fuori dalla finestra di 24 ore, e TEXT, IMAGE o INTERACTIVE per le risposte al suo interno."
takeaways: ["Tutti i messaggi WhatsApp passano da POST /whatsapp/message/sendbulk; messageType (TEMPLATE, TEXT, IMAGE, INTERACTIVE e altri) decide quali campi sono obbligatori.", "La richiesta è multipart/form-data, non JSON, quindi in Python serve files= e in PHP un array come corpo per evitare l'url-encoding.", "Fuori dalla finestra di assistenza clienti di 24 ore si può inviare solo un template approvato; al suo interno si possono inviare testo libero, contenuti multimediali e messaggi interattivi.", "La chiamata mette in coda i messaggi e restituisce subito un batchId; gli stati per destinatario arrivano al vostro webhook e dall'endpoint bulk-insights.", "L'API non accetta una chiave di idempotenza, quindi registrate ogni invio prima di effettuarlo e dopo un timeout controllate lo stato invece di reinviare."]
faq: 
  - q: "I messaggi WhatsApp si inviano come JSON o come form data?"
    a: "Come form data. L'endpoint di invio WhatsApp, POST /whatsapp/message/sendbulk, accetta multipart/form-data, con ogni campo come parte del form. Gli invii singoli di SMS usano invece JSON, il che è una fonte comune di confusione. In Python inviate i campi con files= anziché data=, e in PHP passate un array come corpo, così cURL costruisce il multipart."
  - q: "Posso inviare un messaggio WhatsApp senza template?"
    a: "Solo all'interno della finestra di assistenza clienti. Quando un cliente vi scrive si apre una finestra di 24 ore in cui potete rispondere con testo, contenuti multimediali o messaggi interattivi. Fuori dalla finestra, o per avviare una conversazione, dovete inviare un template approvato. L'API applica le regole di Meta e un invio in testo libero verso una finestra chiusa non andrà a buon fine."
  - q: "Come so se il messaggio è stato consegnato?"
    a: "La chiamata di invio conferma solo che i messaggi sono stati messi in coda e restituisce un batchId. Gli stati per destinatario passano da SUBMITTED, SENT, DELIVERED e READ, oppure terminano come FAILED o REJECTED. Vengono inviati al vostro webhook e potete leggerli anche per batch dall'endpoint bulk-insights."
  - q: "Posso inviare a molti destinatari in una sola richiesta?"
    a: "Sì. destinationNo accetta più numeri separati da virgole, punti e virgola o a capo, e destinationFiles accetta un file TXT, CSV o XLSX. Per un template con variabili diverse per destinatario, caricate un file personalizzato con una riga per destinatario. Impostate allowDuplicate su false per rimuovere i numeri duplicati."
  - q: "Esiste una chiave di idempotenza per evitare invii duplicati?"
    a: "No. L'API non accetta una chiave di idempotenza. Se una richiesta va in timeout, dal client non potete sapere se sia stata accettata. Registrate ogni invio nel vostro database prima della chiamata, memorizzate il batchId restituito e controllate lo stato o l'elenco dei batch prima di qualsiasi nuovo tentativo."
  - q: "Serve l'opt-in prima di inviare?"
    a: "Sì. La policy di Meta richiede che ogni destinatario abbia dato l'opt-in a ricevere messaggi dalla vostra azienda e i template devono essere approvati prima dell'uso. L'API non verifica il consenso al posto vostro. Raccogliete l'opt-in alla fonte, conservate la prova ed escludete chi si disiscrive."
sources: 
  - title: "WhatsApp Business Messaging Policy"
    url: "https://business.whatsapp.com/policy"
  - title: "Pricing on the WhatsApp Business Platform — Meta for Developers"
    url: "https://developers.facebook.com/documentation/business-messaging/whatsapp/pricing"
  - title: "RFC 7578: Returning Values from Forms: multipart/form-data"
    url: "https://www.rfc-editor.org/rfc/rfc7578"
---

# Inviare un messaggio WhatsApp via API: cURL, Node, Python, PHP

Canonical: https://omnichannels.ai/it/blog/send-whatsapp-message-api-examples/
Language: it
Publisher: OmniChannels.ai by BroadNet Technologies

Questa guida è per gli sviluppatori che integrano l'invio WhatsApp in un'applicazione. Mostra richieste funzionanti in cURL, Node.js, Python e PHP, spiega la differenza tra messaggi template e di sessione e tratta tracciamento ed errori. Ogni endpoint e campo deriva dal nostro [riferimento dell'API WhatsApp](/developers/whatsapp/) e dalla specifica OpenAPI.

## Come si invia un messaggio WhatsApp tramite l'API?

Eseguite una `POST` autenticata a `https://api.broadnet.me/whatsapp/message/sendbulk` con campi di form. Il campo `messageType` sceglie il tipo di messaggio e la risposta conferma che i messaggi sono stati messi in coda.

| Elemento | Valore |
|---|---|
| URL di base | `https://api.broadnet.me` (senza prefisso `/v1`) |
| Endpoint | `POST /whatsapp/message/sendbulk` |
| Autenticazione | `Authorization: Bearer $BROADNET_TOKEN` |
| Content type | `multipart/form-data` (impostato automaticamente dal client HTTP) |
| Risposta | Riepilogo JSON del batch con un `batchId` |

Le credenziali di test vengono rilasciate dopo una breve richiesta di accesso e gli invii di prova vanno ai vostri numeri verificati. Vedi il [quickstart](/developers/quickstart/) e le pagine sull'autenticazione. Tenete il token solo sul vostro server.

## Template o messaggio di sessione: quale inviare?

Inviate un template per avviare una conversazione o per scrivere fuori dalla finestra, e un messaggio di sessione quando il cliente vi ha scritto nelle ultime 24 ore. Questa regola la stabilisce Meta, non noi.

| | Messaggio template | Messaggio di sessione |
|---|---|---|
| `messageType` | `TEMPLATE` | `TEXT`, `IMAGE`, `VIDEO`, `AUDIO`, `DOCUMENT`, `INTERACTIVE` e altri |
| Quando è consentito | In qualsiasi momento, una volta approvato il template | Solo mentre la finestra di assistenza clienti è aperta |
| Richiede approvazione | Sì, da parte di Meta | No |
| Uso tipico | Aggiornamenti sugli ordini, OTP, promemoria, campagne | Risposte di assistenza, risposte a domande |

Meta addebita ogni messaggio consegnato in base alla categoria e le sue regole per i messaggi di servizio e i template di utilità sono cambiate il 1° ottobre 2026. La nostra [guida alla finestra](/it/blog/whatsapp-24-hour-customer-service-window/) tratta la meccanica, mentre la [pagina dei prezzi](/it/whatsapp-pricing/) e il [calcolatore](/it/tools/whatsapp-pricing-calculator/) trattano i costi.

## Come si invia un template approvato?

Impostate `messageType=TEMPLATE`, indicate il nome del template e il suo codice lingua e passate i valori delle variabili. Create `batchId=0` per avviare un nuovo batch.

```bash
curl -X POST https://api.broadnet.me/whatsapp/message/sendbulk \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -F batchId=0 \
  -F campaignName=order-updates \
  -F destinationNo=971500000000 \
  -F messageType=TEMPLATE \
  -F templateName=order_update \
  -F templateLanguage=en_US \
  -F bodyTemplateVariables=INV-400
```

```js
// Node.js 18+ (fetch e FormData integrati)
const form = new FormData();
form.append("batchId", "0");
form.append("campaignName", "order-updates");
form.append("destinationNo", "971500000000");
form.append("messageType", "TEMPLATE");
form.append("templateName", "order_update");
form.append("templateLanguage", "en_US");
form.append("bodyTemplateVariables", "INV-400");

const res = await fetch("https://api.broadnet.me/whatsapp/message/sendbulk", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.BROADNET_TOKEN}` }, // fetch imposta il boundary multipart
  body: form,
});
console.log(await res.json());
```

```python
import os
import requests

fields = {
    "batchId": "0",
    "campaignName": "order-updates",
    "destinationNo": "971500000000",
    "messageType": "TEMPLATE",
    "templateName": "order_update",
    "templateLanguage": "en_US",
    "bodyTemplateVariables": "INV-400",
}
# Inviate ogni campo come parte multipart (files=) e non url-encoded (data=).
r = requests.post(
    "https://api.broadnet.me/whatsapp/message/sendbulk",
    headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
    files={k: (None, v) for k, v in fields.items()},
    timeout=30,
)
print(r.json())
```

```php
<?php
$ch = curl_init("https://api.broadnet.me/whatsapp/message/sendbulk");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("BROADNET_TOKEN")],
    // Un array (non una stringa) fa inviare a cURL multipart/form-data.
    CURLOPT_POSTFIELDS => [
        "batchId" => "0",
        "campaignName" => "order-updates",
        "destinationNo" => "971500000000",
        "messageType" => "TEMPLATE",
        "templateName" => "order_update",
        "templateLanguage" => "en_US",
        "bodyTemplateVariables" => "INV-400",
    ],
]);
echo curl_exec($ch);
curl_close($ch);
```

La destinazione è prefisso internazionale più numero, solo cifre. La chiamata risponde subito con un riepilogo del batch:

```json
{
  "totalFiles": 1,
  "totalSuccess": 1,
  "totalFailed": 0,
  "totalDuplicates": 0,
  "batchId": "2609091405000000001",
  "fileResults": [
    {
      "fileName": "direct",
      "totalRecords": 1,
      "successCount": 1,
      "failedRecipients": [],
      "duplicateRecipients": []
    }
  ],
  "message": "Messages queued for delivery"
}
```

Memorizzate il `batchId` accanto al vostro record. «In coda» non significa «consegnato».

## Quali campi della richiesta contano di più?

I campi obbligatori dipendono da `messageType`. Questi sono i più comuni.

| Campo | Obbligatorio | Descrizione |
|---|---|---|
| `messageType` | Sì | `TEXT`, `IMAGE`, `VIDEO`, `AUDIO`, `DOCUMENT`, `STICKER`, `LOCATION`, `CONTACTS`, `TEMPLATE`, `INTERACTIVE`, `REACTION` o `FLOW` |
| `destinationNo` o `destinationFiles` | Uno dei due | Numeri separati da virgole, punti e virgola o a capo; oppure un file TXT, CSV o XLSX |
| `batchId` | No | `0` avvia un nuovo batch |
| `campaignName` | No | La vostra etichetta per la reportistica |
| `allowDuplicate` | No | `false` rimuove i destinatari duplicati |
| `templateName`, `templateLanguage` | Per `TEMPLATE` | Nome del template approvato e codice lingua, come `en_US` o `ar` |
| `bodyTemplateVariables` | Per template | Valore della variabile del corpo; i parametri con nome si passano come JSON |
| `buttonsTemplateVariable` | Per template | Valore dinamico del pulsante: suffisso URL, codice coupon o codice OTP |
| `content` | Per `TEXT` | Corpo del testo, fino a 4.096 caratteri, o didascalia per i contenuti multimediali |
| `mediaUrl` | Per tipo | URL HTTPS pubblico del contenuto multimediale |
| `interactivePayload` | Per `INTERACTIVE` | Oggetto interattivo di Meta come stringa JSON |

La programmazione dell'invio usa `scheduled`, `scheduleTime` e `gmt`, mentre `delay` rallenta la consegna. L'elenco completo è nel [riferimento dell'API WhatsApp](/developers/whatsapp/).

## Come si invia un template con un pulsante o un OTP?

Aggiungete il valore del pulsante in `buttonsTemplateVariable`. Per un template di autenticazione con pulsante «copia codice», passate il codice sia nel corpo sia nei campi del pulsante.

```bash
curl -X POST https://api.broadnet.me/whatsapp/message/sendbulk \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -F batchId=0 \
  -F destinationNo=971500000000 \
  -F messageType=TEMPLATE \
  -F templateName=login_code \
  -F templateLanguage=en_US \
  -F bodyTemplateVariables=482913 \
  -F buttonsTemplateVariable=482913
```

Qui `login_code` è un segnaposto per il vostro template di autenticazione approvato. Con più pulsanti, `buttonsTemplateVariable` accetta un array JSON. Generate il codice sul server, memorizzatelo come hash con una scadenza e non registratelo mai nei log. La nostra [guida agli OTP](/it/blog/otp-authentication-messages-guide/) tratta la consegna one-tap, zero-tap e copy-code.

## Come si risponde all'interno della finestra di assistenza clienti?

Usate un tipo di messaggio di sessione. Una risposta in testo semplice richiede `messageType=TEXT` e `content`.

```bash
curl -X POST https://api.broadnet.me/whatsapp/message/sendbulk \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -F batchId=0 \
  -F destinationNo=971500000000 \
  -F messageType=TEXT \
  -F campaignName=support \
  -F "content=Your order has shipped. Reply here if you need anything."
```

Per i pulsanti di risposta, inviate `messageType=INTERACTIVE` e un `interactivePayload` che segua il formato dei messaggi interattivi di Meta.

```bash
curl -X POST https://api.broadnet.me/whatsapp/message/sendbulk \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -F batchId=0 \
  -F destinationNo=971500000000 \
  -F messageType=INTERACTIVE \
  -F campaignName=support \
  -F 'interactivePayload={"type":"button","body":{"text":"Confirm your delivery slot?"},"action":{"buttons":[{"type":"reply","reply":{"id":"slot_ok","title":"Confirm"}},{"type":"reply","reply":{"id":"slot_change","title":"Change"}}]}}'
```

Per segnare come letto un messaggio in arrivo, e facoltativamente mostrare l'indicatore di scrittura, chiamate `POST /whatsapp/message/read` con JSON:

```bash
curl -X POST https://api.broadnet.me/whatsapp/message/read \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "messageId": "wamid.HBgMOTcxNTAwMDAwMDAwFQIAEhgg", "typing": true }'
```

Consultate la nostra guida ai messaggi interattivi per indicazioni di progettazione.

## Come si traccia la consegna?

Gli stati vengono inviati al webhook configurato sul vostro account e si possono leggere anche per batch. Ogni destinatario passa da `SUBMITTED`, `SENT`, `DELIVERED` e `READ`, oppure termina come `FAILED` o `REJECTED` con un motivo.

```bash
curl "https://api.broadnet.me/whatsapp/message/bulk-insights?batch_Id=2609091405000000001&status=FAILED&page=0&size=50" \
  -H "Authorization: Bearer $BROADNET_TOKEN"
```

`batch_Id` è obbligatorio; `status`, `destination`, `search`, `page` e `size` sono facoltativi e `page` parte da zero. Usate il polling come rete di sicurezza per gli eventi persi e costruite il vostro ricevitore come descritto nella nostra [guida ai webhook](/it/blog/whatsapp-webhooks-guide/). I batch si possono anche mettere in pausa, riprendere e interrompere con gli endpoint dei batch descritti nel riferimento.

## Quali errori devo gestire?

Leggete prima lo stato HTTP, poi il corpo dell'errore. L'API segnala gli errori in un corpo JSON a cinque campi e i fallimenti specifici di WhatsApp possono provenire da Meta.

| Stato | Significato | Azione |
|---|---|---|
| `400` | Errore di validazione, ad esempio un campo specifico del tipo mancante o una destinazione non valida | Correggete la richiesta; non riprovate invariata |
| `401` / `403` | Token mancante o non valido, oppure operazione non consentita | Correggete il token o chiedeteci di abilitare l'operazione |
| `404` | Template o mittente non trovato | Controllate nome e lingua del template |
| `413` | File caricato troppo grande | Riducete il file |
| `429` | Limite di richieste | Attendete `Retry-After` |
| `502` | Meta ha rifiutato la chiamata; `message` riporta codice e testo dell'errore di Meta | Leggetelo; riprovate solo se transitorio |
| `500`, `503`, `504` | Problemi del server o a monte | Riprovate con backoff esponenziale e jitter |

La nostra guida ai codici di errore spiega i codici Meta più comuni. Poiché non esiste una chiave di idempotenza, seguite i passaggi di protezione dai duplicati in [Errori e limiti](/developers/errors-and-limits/): scrivete prima un record in sospeso, memorizzate il `batchId` restituito e dopo un timeout controllate lo stato prima di inviare di nuovo.

## Esempio pratico: un servizio di notifica degli ordini

«Souq Rafiq» (nome di fantasia), un rivenditore degli Emirati, invia un template `order_update` quando un ordine viene spedito.

1. Il servizio ordini scrive una riga con chiave `order-8842-shipped` e stato `pending`.
2. Chiama `sendbulk` con il template e il numero d'ordine come `bodyTemplateVariables`.
3. Con `200` memorizza il `batchId` e segna la riga come `accepted`.
4. Il gestore del webhook aggiorna la riga a `DELIVERED` o `READ`, oppure `FAILED` con un motivo.
5. Se il cliente risponde, lo strumento di assistenza usa un messaggio di sessione `TEXT` all'interno della finestra.
6. Un job notturno legge `bulk-insights` per i batch del giorno prima e riconcilia gli eventuali stati mancanti.

## Quali sono gli errori comuni?

- **Inviare JSON.** L'endpoint di invio WhatsApp è multipart; `Content-Type: application/json` non funziona.
- **`data=` in Python** invece di `files=`, che esegue l'url-encoding del form.
- **Testo libero fuori dalla finestra**, che fallisce. Usate un template.
- **Codice lingua sbagliato**, come `en` invece di `en_US` del template.
- **Considerare `200` come consegnato.** Significa in coda.
- **Nuovi tentativi alla cieca** dopo un timeout, che possono scrivere due volte a un cliente.
- **Token nel codice client.** Chiamate l'API solo dal backend.
- **Limiti:** i dettagli del payload variano per template. Confermate con il nostro team la struttura delle variabili per la prima campagna personalizzata.

## Come vi aiuta OmniChannels.ai

BroadNet è un Meta Business Solution Provider ufficiale e l'attivazione sulla WhatsApp Business API usa l'Embedded Signup di Meta; il nostro team prepara la registrazione con voi, mentre le approvazioni restano a Meta. L'API REST è documentata con una specifica OpenAPI 3.1 e un SDK TypeScript, `@broadnet/cpaas-sdk`, e gli stati di consegna sono normalizzati tra i canali. Partite dalla [documentazione dell'API WhatsApp](/developers/whatsapp/) o dal [quickstart](/developers/quickstart/).
