Indice dei contenuti
Iniziare
Connetti e invia
Ricevi e automatizza
API di WhatsApp con PitoneInvia, ricevi e automatizza messaggi
Tutto ciò di cui hai bisogno per usare il API di WhatsApp in Python: quale libreria scegliere, come connettere un account collegato con un codice QR, come inviare e ricevere messaggi con
richieste e httpx, e come collegare un webhook FastAPI per un bot o un agente IA. API REST oggi, nessuna verifica Meta Business necessaria
import requests
BASE_URL = "https://{YOUR_DSN}/api/v1"
HEADERS = {"X-API-KEY": "YOUR_ACCESS_TOKEN"}
def send_whatsapp(chat_id: str, text: str) -> dict:
response = requests.post(
f"{BASE_URL}/chats/{chat_id}/messages",
headers=HEADERS,
data={"text": text},
)
response.raise_for_status()
return response.json()
send_whatsapp("9f9uio56sopa456s", "Hello from Python!")200 OK, messaggio inviato
Definizione
Cos'è l'API di WhatsApp in Python?
Il API di WhatsApp in Python significa chiamare la messaggistica di WhatsApp Business dal codice Python invece di cliccare su WhatsApp Web. Uno script Python o un servizio di backend invia una richiesta HTTP, solitamente con
richieste o httpx, a un'API REST che espone chat, messaggi e webhook, sia direttamente alla Cloud API di Meta sia a un provider unificato come Unipile che collega WhatsApp insieme a LinkedIn, Instagram e Telegram dietro un'unica interfaccia. Meta non pubblica un SDK Python ufficiale e all-in-one per WhatsApp, motivo per cui quasi ogni integrazione Python in questa guida, e la maggior parte di ciò che troverai nel resto del web, comunica direttamente con gli endpoint REST.Un'API REST per WhatsApp, LinkedIn, Instagram e Telegram
Collegato tramite codice QR o codice di associazione, nessuna verifica Meta Business
richieste per gli script semplici, httpx per l'asincrono su scala Per il livello di orientamento, accesso, costi e limiti, iniziare con il Guida all'accesso, ai costi e ai limiti delle API di WhatsApp. Costruire in PHP invece che in Python?
Leggi la stessa integrazione in PHP Prima di costruire
Di cosa hai bisogno prima di iniziare?
Non è necessario un account Meta Business o un'approvazione della Piattaforma WhatsApp Business per iniziare a inviare e ricevere messaggi da Python. Ti serve un ambiente Python funzionante, un client HTTP, un posto in cui ricevere i webhook e un account Unipile.
Python 3.9+
Corrisponde alla versione minima richiesta dal SDK Python di Unipile
pydantic dipendenza, e dal moderno httpx e le versioni di FastAPI.requests o httpx
Un tunnel locale
Uno strumento come
ngrok o cloudflared per esporre la tua rotta webhook di FastAPI su un URL HTTPS pubblico durante lo sviluppo.Token di accesso e DSN
Entrambi provengono dalla dashboard di Unipile. Il DSN è l'host che chiami, l'Access Token va inserito nel
CHIAVE X-API intestazione di ogni richiesta.Confronto librerie
Quale libreria Python dovresti usare per WhatsApp?
Non esiste una risposta unica e ovvia, e la maggior parte dei post di blog su questo argomento promuove il pacchetto gestito dal proprio autore. Ecco un confronto basato sui fatti dei cinque modi in cui gli sviluppatori Python utilizzano effettivamente WhatsApp oggi, dall'automazione del browser a un provider unificato, in modo da poter scegliere in base a ciò che ciascuna opzione fa realmente, non al marketing.
Libreria / approccio
Ciò che chiama realmente
Verifica aziendale di Meta
Mantenuto
Il migliore per
pywhatkit
Gestisce WhatsApp Web in una scheda del browser (automazione da tastiera), non un'API lato server
N/D, nessuna API
Comunità, sporadico
Script usa e getta e demo su una macchina con schermo, non per invio in produzione
whatsapp-cloud-api
Sottile wrapper in Python per gli endpoint dell'API Cloud di WhatsApp di Meta
Richiesto
Wrapper della community
Team già approvate sulla Cloud API che desiderano un client Pythonico
whatsapp-api-client-python
Chiama il SaaS green-api, che a sua volta mantiene la sessione di WhatsApp
Non richiesto
Gestito dal fornitore
Team a loro agio nel dipendere da un secondo fornitore SaaS mono-funzione
richieste, direttamente a Meta
Endpoint dell'API Cloud di Meta, nessun wrapper
Richiesto
Fai da te
Team idonei alla verifica aziendale Meta che desiderano il controllo completo
Unipile, requests o httpx
L'API di messaggistica unificata di Unipile, WhatsApp insieme a LinkedIn, Instagram e Telegram
Non richiesto
Attivamente mantenuto, SDK Python in beta
Prodotti SaaS che collegano molti account WhatsApp di utenti finali per conto di ciascun utente
pywhatkit
ChiamateEsegue WhatsApp Web in una scheda del browser, non un'API lato server
Verifica MetaN/D, nessuna API
MantenutoComunità, sporadico
Il migliore perScript usa e getta e demo, non per la produzione
whatsapp-cloud-api
ChiamateSottile wrapper attorno agli endpoint dell'API Cloud di Meta
Verifica MetaRichiesto
MantenutoWrapper della community
Il migliore perTeam già approvati sulla Cloud API
whatsapp-api-client-python
ChiamateIl SaaS green-api, che mantiene la sessione di WhatsApp
Verifica MetaNon richiesto
MantenutoGestito dal fornitore
Il migliore perTeam a proprio agio con un secondo fornitore SaaS
richieste, direttamente a Meta
ChiamateEndpoint dell'API Cloud di Meta, senza wrapper
Verifica MetaRichiesto
MantenutoFai da te
Il migliore perTeam già autorizzati per la verifica di Meta Business
Unipile, requests o httpx
ChiamateAPI di messaggistica unificata, WhatsApp con LinkedIn, Instagram, Telegram
Verifica MetaNon richiesto
MantenutoAttivamente mantenuto, SDK Python in beta
Il migliore perProdotti SaaS che collegano molti account di utenti finali
Ogni opzione che mantiene Verifica aziendale Meta richiesta in ultima analisi comunica con l'API Cloud di WhatsApp di Meta (vedi Documentazione della piattaforma WhatsApp Business di Meta), che è la scelta giusta se gestisci già un numero aziendale verificato. Se invece colleghi account WhatsApp per conto di molti utenti finali diversi, un flusso con codice QR o codice di associazione elimina del tutto tale fase di verifica, che è il modello utilizzato nel resto di questa guida.
Connessione del conto
Come si collega un account WhatsApp in Python?
Ogni chiamata in questa guida viene eseguita per conto di un utente autenticato che ha collegato il proprio account WhatsApp. Non è prevista alcuna fase di verifica di Meta Business: da Python, si invia un singolo
POST /api/v1/accounts richiesta con provider imposta su WHATSAPP, e l'utente conferma il collegamento scansionando un codice QR o inserendo un codice di associazione sul proprio telefono.Opzione A: codice QR (predefinito)
Vattene
abbinamento_numero_di_telefono fuori dal corpo della richiesta e Unipile restituisce un checkpoint contenente il payload del codice QR. Visualizzalo con una libreria come codice QR e visualizzalo affinché l'utente possa eseguirne la scansione da WhatsApp > Dispositivi collegati.import requests
BASE_URL = "https://{YOUR_DSN}/api/v1"
HEADERS = {"X-API-KEY": "YOUR_ACCESS_TOKEN", "accept": "application/json"}
def connect_whatsapp_qr() -> dict:
response = requests.post(
f"{BASE_URL}/accounts",
headers=HEADERS,
json={"provider": "WHATSAPP"},
)
response.raise_for_status()
return response.json()
account = connect_whatsapp_qr()
print(account)
# account contiene un nuovo account_id e un oggetto checkpoint.
# Visualizza il checkpoint come codice QR e chiedi all’utente di scansionarlo
# da WhatsApp > Dispositivi collegati.Opzione B: codice di associazione
Passare
abbinamento_numero_di_telefono solo con cifre E.164, con il prefisso internazionale per primo, senza segno più né spazi. Unipile restituisce un checkpoint contenente un codice breve che l'utente digita su WhatsApp invece di scansionare alcunché, il che è più adatto a un server headless privo di schermo su cui visualizzare un codice QR.def connect_whatsapp_pairing_code(phone_e164_digits: str) -> dict:
response = requests.post(
f"{BASE_URL}/accounts",
headers=HEADERS,
json={
"provider": "WHATSAPP",
"pairing_phone_number": phone_e164_digits,
},
)
response.raise_for_status()
return response.json()
# Prefisso internazionale + numero, solo cifre, ad es. Francia
account = connect_whatsapp_pairing_code("33612345678")
# Il checkpoint dell’account contiene il codice di accoppiamento da visualizzare nell’interfaccia utente.
# L’utente lo inserisce in WhatsApp > Dispositivi collegati > Collega con numero di telefono.Conferma che l'account è connesso
Una volta che l'utente ha scansionato il codice QR o digitato il codice di accoppiamento, è necessario sapere quando l'account è effettivamente pronto per inviare e ricevere. Unipile offre due opzioni.
Verifica lo stato dell'account
Chiama
GET /api/v1/accounts/{account_id} ogni paio di secondi finché l'account non ha più bisogno del suo checkpoint. Semplice, ma spreca richieste mentre aspetti.Webhook dello stato dell'account
Registra un webhook con
fonte imposta su stato_account (stesso POST /api/v1/webhooks endpoint utilizzato per i messaggi) e Unipile invia {"AccountStatus": {"account_id": "...", "message": "OK"}} non appena l'account è pronto. Questo è ciò che utilizza la maggior parte delle integrazioni di produzione.import time
def wait_for_connection(account_id: str, timeout_seconds: int = 120) -> dict:
deadline = time.time() + timeout_seconds
while time.time() < deadline:
response = requests.get(f"{BASE_URL}/accounts/{account_id}", headers=HEADERS)
response.raise_for_status()
account = response.json()
print(account) # ispeziona il payload in tempo reale per verificare lo stato
time.sleep(2)
raise TimeoutError("L'account WhatsApp non ha confermato la connessione in tempo")Inviare
Come si invia un messaggio WhatsApp con Python?
Inviare un messaggio WhatsApp da Python richiede una singola chiamata HTTP:
POST /api/v1/chats/{chat_id}/messages, con il chat_id che hai già ottenuto dalle chat in elenco o da un webhook in entrata, e un text campo. L'endpoint accetta sia corpi codificati in formato form che in formato JSON, quindi un testo semplice richieste.post con dati= funziona senza bisogno di alcuna configurazione aggiuntiva.Se non esiste già
chat_id, ad esempio il primo messaggio inviato a un nuovo contatto, chiamare POST /api/v1/chats anziché con un account_id e del destinatario attendees_ids; Unipile crea la chat 1:1 e invia il messaggio nella stessa richiesta.import requests
BASE_URL = "https://{YOUR_DSN}/api/v1"
HEADERS = {"X-API-KEY": "YOUR_ACCESS_TOKEN"}
def send_message(chat_id: str, text: str) -> dict:
response = requests.post(
f"{BASE_URL}/chats/{chat_id}/messages",
headers=HEADERS,
data={"text": text},
)
response.raise_for_status()
return response.json()
def start_chat(account_id: str, attendee_provider_id: str, text: str) -> dict:
response = requests.post(
f"{BASE_URL}/chats",
headers=HEADERS,
data={
"account_id": account_id,
"attendees_ids": attendee_provider_id,
"text": text,
},
)
response.raise_for_status()
return response.json()I tipi di messaggio (testo, media, note vocali, template) e la finestra di assistenza clienti di 24 ore costituiscono un argomento a sé, trattato integralmente nella guida a tipi di messaggi supportati dall'API di WhatsApp. Questa sezione tratta esclusivamente gli aspetti tecnici di Python.
A partire da luglio 2025, Meta addebiterà i messaggi API di WhatsApp per singolo messaggio inviato, non per conversazione. Vedi Come funziona il sistema di tariffazione dell'API di WhatsApp per singolo messaggio per le tariffe correnti per paese.
Concorrenza
Come si inviano messaggi WhatsApp in modo asincrono in Python?
Quando invii a molti destinatari contemporaneamente, una trasmissione, uno svuotamento della coda, un’attività di follow-up di massa, un ciclo che ne attende uno
richieste.post in questo momento il collo di bottiglia è l'API, non il contrario. httpx.AsyncClient combinato con asyncio.gather invia molte richieste contemporaneamente da un singolo ciclo di eventi, senza bisogno di thread. Un semaforo è ciò che ti permette di essere un buon cittadino: gli account WhatsApp sono comunque soggetti ai limiti di velocità della piattaforma stessa, quindi una concorrenza illimitata si limita a sostituire un ciclo lento con una valanga di risposte 429.import asyncio
import httpx
BASE_URL = "https://{YOUR_DSN}/api/v1"
HEADERS = {"X-API-KEY": "YOUR_ACCESS_TOKEN"}
CONCURRENCY_LIMIT = 5
async def send_message_async(
client: httpx.AsyncClient,
semaphore: asyncio.Semaphore,
chat_id: str,
text: str,
) -> dict:
async with semaphore:
response = await client.post(
f"{BASE_URL}/chats/{chat_id}/messages",
headers=HEADERS,
data={"text": text},
)
response.raise_for_status()
return response.json()
async def send_bulk(messages: list[tuple[str, str]]) -> list:
semaphore = asyncio.Semaphore(CONCURRENCY_LIMIT)
async with httpx.AsyncClient(timeout=30) as client:
tasks = [
send_message_async(client, semaphore, chat_id, text)
for chat_id, text in messages
]
return await asyncio.gather(*tasks, return_exceptions=True)
messages = [
("9f9uio56sopa456s", "Il tuo ordine è stato spedito!"),
("a1b2c3d4e5f6g7h8", "Il tuo ordine è stato spedito!"),
]
results = asyncio.run(send_bulk(messages))
for chat_id_text, result in zip(messages, results):
if isinstance(result, Exception):
print("fallito:", chat_id_text[0], result)Conserva
LIMITE_DI_CONCORRENZA conservativo e aumentalo solo dopo aver osservato i tassi di errore reali. return_exceptions=True significa che un invio non riuscito non annulla il resto del lotto, il che è importante una volta che si stanno inviando centinaia di messaggi in una sola esecuzione. La sezione sui limiti di frequenza e sui tentativi qui sotto si basa su questo stesso schema.Ganci web
Come si ricevono i messaggi di WhatsApp con un webhook di FastAPI?
Un webhook è il modo in cui il tuo servizio Python viene a conoscenza di un nuovo messaggio WhatsApp nel momento esatto in cui arriva, anziché doverlo cercare continuamente tramite polling. Registri un endpoint presso Unipile e ogni evento corrispondente viene inviato al tuo server sotto forma di JSON. FastAPI è una scelta naturale per il lato ricevente: un
pydantic il modello convalida il payload per te, e Attività in background permetti alla tua rotta di restituire una risposta immediatamente mentre il lavoro reale, ovvero chiamare un modello e scrivere su un database, avviene dopo.1. Registrare il webhook
Punto
url_richiesta alla tua rotta FastAPI. Durante lo sviluppo locale, ciò significa l'URL HTTPS che il tuo tunnel (dalla sezione dei prerequisiti sopra) espone, non localhost.import requests
BASE_URL = "https://{YOUR_DSN}/api/v1"
HEADERS = {"X-API-KEY": "YOUR_ACCESS_TOKEN"}
response = requests.post(
f"{BASE_URL}/webhooks",
headers=HEADERS,
json={
"source": "messaging",
"request_url": "https://your-tunnel.example.com/webhooks/whatsapp",
"name": "whatsapp-fastapi",
"format": "json",
"events": ["message_received"],
},
)
response.raise_for_status()
print(response.json())2. Riceverlo in FastAPI
Il payload inviato da Unipile trasporta la chat, il mittente e il testo del messaggio come campi piatti, più un elenco di allegati quando ce ne sono. Modella solo ciò di cui hai bisogno; Pydantic ignora i campi extra per impostazione predefinita.
from typing import List, Optional
from fastapi import BackgroundTasks, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Sender(BaseModel):
attendee_id: str
attendee_name: Optional[str] = None
attendee_provider_id: str
class Attachment(BaseModel):
id: str
type: str
mimetype: Optional[str] = None
unavailable: bool = False
class WhatsAppMessageEvent(BaseModel):
account_id: str
account_type: str
event: str
chat_id: str
message_id: str
message: Optional[str] = None
timestamp: str
webhook_name: Optional[str] = None
mittente: Mittente
allegati: Lista[Allegato] = []
def gestisci_messaggio(evento: WhatsAppMessageEvent) -> Nessuno:
if evento.tipo_account != "WHATSAPP" or evento.evento != "message_received":
return
# Unipile include i messaggi inviati dall'account collegato stesso, da
# un altro dispositivo o dalle tue chiamate API. Confronta il mittente
# con il titolare dell'account che hai memorizzato al momento della connessione se
# desideri reagire solo ai messaggi provenienti dall'altra parte.
print(f"Nuovo messaggio WhatsApp nella chat {event.chat_id}: {event.message}")
# Da qui puoi inoltrarlo alla tua coda, al tuo database o a un agente AI
@app.post("/webhooks/whatsapp")
async def whatsapp_webhook(
event: WhatsAppMessageEvent,
background_tasks: BackgroundTasks,
):
background_tasks.add_task(handle_message, event)
return {"status": "received"}Eseguilo con
uvicorn main:app --reload, punta il tuo tunnel alla porta 8000 e registra quell'URL pubblico come url_richiesta nel passaggio 1. Ritorno {"status": "received"} prima che il messaggio sia completamente elaborato è importante: Unipile si aspetta una risposta rapida e Attività in background è ciò che mantiene gestisci_messaggio dall'impedirlo.Un'altra cosa che vale la pena integrare fin dall'inizio: memorizzare ciascuno elaborato
id_messaggio prima di agire su di esso e salta qualsiasi cosa tu abbia già visto. Se l'account WhatsApp collegato si disconnette e si riconnette, Unipile consegna i messaggi arrivati durante quell'intervallo una volta che si è rimesso in pari, e un nuovo deployment o un'attività in background bloccata possono far sì che il tuo gestore veda separatamente lo stesso evento due volte, quindi trattare id_messaggio come una chiave di idempotenza impedisce a un bot di WhatsApp di rispondere due volte.Leggi
Come si recuperano le chat e la cronologia dei messaggi in Python?
Ogni endpoint di elenco nell'API di Unipile, chat, messaggi, partecipanti, è paginato allo stesso modo: la risposta contiene un
articoli array e un cursore. Passamelo cursore torna sulla prossima chiamata e fermati non appena ritorna nullo. Di Python mentre True il ciclo si mappa direttamente su quel pattern.Elenca tutte le chat di WhatsApp per un account
import requests
BASE_URL = "https://{YOUR_DSN}/api/v1"
HEADERS = {"X-API-KEY": "YOUR_ACCESS_TOKEN"}
def list_all_whatsapp_chats(account_id: str) -> list:
chats = []
cursor = None
while True:
params = {"account_id": account_id, "limit": 100}
if cursor:
params["cursor"] = cursor
response = requests.get(f"{BASE_URL}/chats", headers=HEADERS, params=params)
response.raise_for_status()
page = response.json()
chats.extend(page["items"])
cursor = page["cursor"]
if not cursor:
break
return chats
for chat in list_all_whatsapp_chats("Yk08cDzzdsqs9_8ds"):
print(chat["id"], chat["name"], chat["unread_count"])Leggi la cronologia dei messaggi e i partecipanti di una chat
I messaggi più recenti vengono restituiti per primi. Usa lo stesso
limite e cursore modello per scorrere all'indietro nella cronologia meno recente e chiamare l'endpoint dei partecipanti ogni volta che è necessario determinare chi si trova effettivamente in una chat, individuale o di gruppo.def get_chat_history(chat_id: str, limit: int = 100) -> list:
response = requests.get(
f"{BASE_URL}/chats/{chat_id}/messages",
headers=HEADERS,
params={"limit": limit},
)
response.raise_for_status()
return response.json()["items"]
def get_chat_attendees(chat_id: str) -> list:
response = requests.get(
f"{BASE_URL}/chats/{chat_id}/attendees",
headers=HEADERS,
)
response.raise_for_status()
return response.json()["items"]
messages = get_chat_history("9f9uio56sopa456s")
attendees = get_chat_attendees("9f9uio56sopa456s")Questo è anche il percorso del codice che una sincronizzazione CRM o una casella di posta di supporto eseguono effettivamente in Python: su una nuova connessione, attraversa ogni chat una volta con
elenca_tutte_le_chat_di_whatsapp per popolare il tuo database, poi affidati al webhook della sezione precedente per mantenerlo aggiornato anziché ripetere il polling. Il GET /chat anche l'endpoint accetta un non letto filtro, in modo che un processo più leggero che controlla solo le chat non lette secondo una pianificazione non debba scorrere l'intera cronologia dell'account ogni volta che viene eseguito.Anche i gruppi di WhatsApp sono chat, quindi la stessa
GET /chat e GET /chats/{chat_id}/attendees chiama la lista di essi e dei loro membri da Python senza codice extra. Per aggiungere o rimuovere un partecipante, o per recuperare il link d'invito, usa PATCH /chats/{chat_id} con un aggiungiPartecipante, rimuoviPartecipante, o ottieniLinkInvito azione. La procedura dettagliata completa, insieme ai limiti di partecipazione imposti da Meta sulla sua API nativa per i Gruppi, si trova nella guida a aggiungere o rimuovere partecipanti dai gruppi WhatsApp.Automazione
Come si sviluppa un bot di WhatsApp o un agente IA in Python?
Ogni bot di WhatsApp o agente IA segue gli stessi tre passaggi: riceve un messaggio tramite il webhook, decide cosa farne, invia una risposta sullo stesso
chat_id. Nulla riguardo ai passaggi uno e tre cambia quando metti un LLM nel mezzo, motivo per cui il gestore di FastAPI e il invia_messaggio Le funzioni delle sezioni precedenti costituiscono già la maggior parte del codice necessario.da openai import OpenAI # o qualsiasi client LLM che utilizzi
llm = OpenAI()
_recent_bot_replies: dict = {}
def generate_reply(incoming_text: str) -> str:
completion = llm.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Sei un agente di supporto WhatsApp molto disponibile."},
{"role": "user", "content": incoming_text},
],
)
return completion.choices[0].message.content
def handle_message(event: WhatsAppMessageEvent) -> None:
if event.account_type != "WHATSAPP" or event.event != "message_received":
return
if not event.message:
return
if _recent_bot_replies.get(event.chat_id) == event.message:
return # eco della nostra ultima risposta, ignorala
reply_text = generate_reply(event.message)
_recent_bot_replies[event.chat_id] = reply_text
send_message(event.chat_id, reply_text)Il
_ultime_risposte_bot la guardia conta più di quanto sembri: quella di Unipile messaggio_ricevuto l'evento si attiva anche per i messaggi inviati dall'account collegato, da un altro dispositivo o tramite le proprie chiamate API, quindi senza una protezione un agente rischia di finire per rispondere alla propria risposta. Un dizionario va bene per una demo; un agente di produzione dovrebbe mantenere quello stato in Redis o in un database insieme alla cronologia della conversazione e a una chiave di idempotenza.Il payload del webhook e il
invia_messaggio Le chiamate hanno lo stesso aspetto su WhatsApp, LinkedIn, Instagram e Telegram, soltanto tipo_di_account modifiche, in modo che lo stesso gestore FastAPI possa indirizzare le risposte di un agente su tutti i canali a cui un utente si è connesso. Mantenere corretti il tono, la formattazione e i limiti di frequenza specifici del canale quando lo fai è trattato nella guida alla API multicanale per agenti AI.Affidabilità
Come gestisci i limiti di frequenza e i tentativi in Python?
Unipile restituisce un corpo JSON con un
tipo campo, come errori/credenziali_non_valide o errori/account_disconnesso, ogni volta che una richiesta fallisce. Alcune di queste meritano di essere ripetute, come una connessione caduta o un temporaneo problema del provider; altre, come credenziali errate, non si risolveranno da sole per quante volte si riprovi a chiamare. La velocità e la quantità di messaggi inviati da un singolo account WhatsApp rimangono una decisione del cliente, definita dai limiti di frequenza che WhatsApp stesso impone su quell'account, e non un numero fisso imposto da Unipile.Il
tenacia trasforma il pacchetto in un decoratore anziché in un ciclo fatto a mano. Avvolgi lo stesso invia_messaggio funzione dalla sezione di invio con backoff esponenziale e un numero massimo di tentativi limitato:# pip install tenacity
import requests
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
@retry(
stop=stop_after_attempt(5),
wait=wait_exponential(multiplier=1, min=2, max=30),
retry=retry_if_exception_type(requests.exceptions.HTTPError),
)
def invia_messaggio_con_riprova(id_chat: str, testo: str) -> dict:
response = requests.post(
f"{BASE_URL}/chats/{chat_id}/messages",
headers=HEADERS,
data={"text": text},
)
response.raise_for_status()
return response.json()Cinque tentativi con un backoff esponenziale da 2 a 30 secondi sono un'impostazione predefinita ragionevole per un job in background; riduci il numero di tentativi per qualsiasi cosa venga eseguita nel percorso di una richiesta rivolta all'utente, poiché
tenacia altrimenti manterrà la richiesta aperta mentre effettua nuovi tentativi. Lo stesso decoratore avvolge la versione asincrona della sezione sulla concorrenza, basta aggiungere await dove tenacia lo sostiene attraverso AsyncRetrying.SDK
Esiste un SDK Python ufficiale di Unipile?
Sì.
unipile/unipile-python è reale e attivamente mantenuto, con un commit inviato di recente l'11 agosto 2026. Due cose vale la pena sapere prima di utilizzarlo: non è ancora pubblicato su PyPI e si rivolge all'API v2 di Unipile, che è ancora in versione beta, mentre ogni endpoint utilizzato in questa guida è v1.Attivamente mantenuto, solo su GitHub
Python 3.9+, pydantic 2.11+
Non su PyPI, installa da GitHub
Ha come obiettivo la API v2 beta, non la v1
pip install git+https://github.com/unipile/unipile-python.gitimport unipile
configuration = unipile.Configuration()
configuration.api_key["apiKey"] = "YOUR_ACCESS_TOKEN"
api_client = unipile.ApiClient(configuration)
messaging_api = unipile.MessagingApi(api_client)Per tutto ciò che questa guida tratta oggi, basati sugli endpoint REST v1 con
richieste o httpxsono stabili, documentati e rappresentano ciò su cui è effettivamente basato ogni esempio di codice sopra. Una volta che l'SDK Python sarà uscito dalla fase beta e sarà disponibile su PyPI, la migrazione consisterà principalmente nel sostituire le chiamate HTTP con metodi di client tipizzati; gli endpoint e il modello di account connesso sottostanti non cambiano. Per un confronto, l'SDK Node.js è quello attualmente menzionato in tutto l'indice della documentazione principale di Unipile, mentre il vecchio SDK PHP è stato archiviato dall'ottobre 2023.Stai costruendo lo stesso tipo di integrazione per un altro canale? Il API di Instagram con Python la guida segue l'identico schema di connessione, invio, ricezione e webhook mostrato in questo articolo.
API di WhatsApp in Python: FAQ
Risposte chiare su librerie, connessione, SDK e webhook per la creazione dell'API di WhatsApp in Python.
Non esiste un'unica libreria migliore, dipende da ciò che hai già. Se sei già stato approvato sulla Cloud API di Meta,
whatsapp-cloud-api ti offre un wrapper Python. Se vuoi saltare completamente la verifica di Meta Business e connettere invece gli account WhatsApp per conto dei tuoi utenti, l'API REST di Unipile chiamata con richieste o httpx copre WhatsApp insieme a LinkedIn, Instagram e Telegram da un'unica interfaccia. pywhatkit vale la pena scartarlo subito: gestisce WhatsApp Web in un browser e non tramite un'API lato server, quindi non è adatto per un backend di produzione.Invia un
POSTA richiesta a /api/v1/chat/{chat_id}/messaggi with a text campo e tuo CHIAVE X-API intestazione, per esempio requests.post(url, headers=headers, data={"text": "Hello"}). Se non ne hai uno chat_id eppure, POST /api/v1/chats con un account_id e del destinatario attendees_ids crea la chat e invia il primo messaggio nella stessa chiamata.Sì. La connessione di un account WhatsApp tramite Unipile richiede solo che il proprietario dell'account scanni un codice QR o inserisca un codice di associazione, nello stesso modo in cui funziona WhatsApp Web. Non è presente alcuna applicazione Meta Business Platform né alcuna verifica del numero di telefono con Meta, poiché l'integrazione viene eseguita per conto dell'utente autenticato piuttosto che tramite un numero WhatsApp Business registrato.
Sì,
unipile/unipile-python è un SDK ufficiale attivamente mantenuto, ma non è ancora su PyPI: installalo con pip install git+https://github.com/unipile/unipile-python.git. Inoltre, prende di mira l'API v2 di Unipile, che è in versione beta, mentre ogni endpoint di questa guida utilizza la versione stabile v1 dell'API, quindi la maggior parte delle integrazioni in Python oggi è ancora costruita direttamente su richieste o httpx piuttosto che l'SDK.richieste è più semplice e sufficiente per script, cron job e invii a basso volume. httpx vale la pena passare a questa soluzione quando si inviano messaggi a troppi destinatari contemporaneamente o quando si sviluppa un servizio FastAPI asincrono, perché AsyncClient consente di inviare più richieste contemporaneamente dallo stesso event loop invece di bloccarle una per una.Esegui un'applicazione FastAPI in locale, esponila con un tunnel come
ngrok o cloudflared per ottenere un URL HTTPS pubblico e registrare quell'URL come url_richiesta quando crei un webhook con fonte imposta su messaging. Unipile invia ogni nuovo messaggio a quell'URL del tunnel, che lo inoltra direttamente alla tua rotta FastAPI locale mentre sviluppi.Sì. I gruppi di WhatsApp vengono visualizzati come chat normali, quindi
GET /chat e GET /chats/{chat_id}/attendees elencali e i loro membri senza distinzioni di maiuscole/minuscole. Per aggiungere un partecipante, rimuoverne uno o recuperare il link di invito al gruppo, invia un PATCH /chats/{chat_id} richiesta con un aggiungiPartecipante, rimuoviPartecipante, o ottieniLinkInvito azione, dettagliata nella guida a aggiunta e rimozione di membri dai gruppi di WhatsApp.Gli endpoint sottostanti sono identici, la differenza sta nel runtime e nel suo ecosistema: Python favorisce
richieste o httpx con asyncio per la concorrenza e FastAPI per i webhook, mentre le integrazioni in PHP utilizzano tipicamente Guzzle e si inseriscono in un'applicazione Laravel con processi in coda. Se il vostro stack è PHP, la stessa integrazione in PHP percorre ogni passaggio equivalente.Avete ancora domande? Il nostro team è qui per aiutarvi.