UC-009 — Conversazione Bidirezionale
| Campo | Valore |
|---|---|
| ID | UC-009 |
| Obiettivo | Gestire conversazioni bidirezionali con i clienti |
| Canale | WhatsApp / RCS |
| Complessità | ⭐⭐⭐ Avanzato |
| Tempo stimato | 20 minuti |
| API coinvolte | POST /api/partner-gateway/v1/webhooks/delivery-status, GET /api/partner-gateway/v1/inbox/conversations, GET /api/partner-gateway/v1/inbox/conversations/{chatId}/messages, POST /api/partner-gateway/v1/inbox/conversations/reply, PATCH /api/partner-gateway/v1/inbox/conversations/{chatId}/read, PATCH /api/partner-gateway/v1/inbox/conversations/{chatId}/archive |
Scenari reali
- TechStore — Chat di assistenza clienti: Un cliente scrive su WhatsApp per chiedere informazioni su un ordine; il sistema riceve il messaggio, lo assegna a un operatore e risponde con lo stato della spedizione.
- Studio Dentistico Bianchi — Conferma prenotazione con risposta: Dopo l'invio di un promemoria appuntamento, il paziente conferma o chiede di spostare la visita rispondendo al messaggio.
- FashionOutlet — Raccolta feedback post-vendita: Un sondaggio post-acquisto chiede al cliente di rispondere con un voto da 1 a 5; il sistema raccoglie e cataloga le risposte automaticamente.
Prerequisiti
Prima di iniziare, assicurati di avere:
- API Key attiva → Come ottenerla
- Credito sufficiente → Verificalo nella Dashboard Qlara
- Webhook configurato + numero WhatsApp o agente RCS
Flusso di interazione
Guida passo-passo
Step 1 — Configurare il webhook per i messaggi inbound
Per prima cosa registra un webhook per ricevere i messaggi in arrivo. Nonostante il nome, il webhook delivery-status riceve tutti gli eventi del tuo account: DELIVERY, READ e INBOUND. Vedi la guida Webhooks per la configurazione completa.
curl -X POST "https://api.qlara.ai/api/partner-gateway/v1/webhooks/delivery-status" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"callbackUrl": "https://api.techstore.it/webhooks/qlara"
}'
Risposta: 201 Created
{
"companyId": 189,
"callbackUrl": "https://api.techstore.it/webhooks/qlara"
}
Ogni account ha un solo callback URL, condiviso da SMS, RCS e WhatsApp. Se un webhook è già configurato, la chiamata risponde 409 Conflict e lascia invariato quello esistente: verificalo con GET /webhooks/delivery-status e cambia l'URL con PUT sullo stesso path. L'URL deve essere HTTPS sulla porta 443 o 8443 e raggiungibile pubblicamente, altrimenti la chiamata risponde 400.
Step 2 — Ricevere un messaggio inbound
Quando un cliente invia un messaggio, il tuo endpoint riceve un payload come questo. Gli eventi INBOUND esistono solo per RCS e WhatsApp.
Inbound TEXT:
{
"eventType": "INBOUND",
"channel": "WHATSAPP",
"messageId": "msg-wa-in-001",
"source": "+393471234567",
"destination": "+393209998877",
"receivedDate": "2026-04-09T11:15:22+02:00",
"messageType": "TEXT",
"text": "Buongiorno, vorrei sapere lo stato del mio ordine ORD-2026-1584"
}
Inbound IMAGE:
{
"eventType": "INBOUND",
"channel": "WHATSAPP",
"messageId": "msg-wa-in-002",
"source": "+393471234567",
"destination": "+393209998877",
"receivedDate": "2026-04-09T11:16:05+02:00",
"messageType": "IMAGE",
"mediaKey": "b394ab72/efd4987c/39b4879f6fed01f0d622453be1488c93"
}
| Campo | Descrizione |
|---|---|
eventType | Sempre INBOUND per un messaggio scritto dall'utente finale |
channel | WHATSAPP o RCS |
messageId | Identificativo del messaggio nella conversazione |
source | Numero di telefono dell'utente finale |
destination | Il tuo numero WhatsApp (WhatsApp) o l'id del tuo agente (RCS) |
receivedDate | Momento di ricezione del messaggio. Gli eventi INBOUND non hanno eventDate |
messageType | TEXT per i messaggi di testo; i messaggi media (es. IMAGE) portano un mediaKey |
text | Testo del messaggio |
mediaKey | Chiave dell'allegato, presente nei messaggi media |
I campi nulli vengono omessi dal payload, quindi un messaggio di testo non ha mediaKey.
Per scaricare un file media allegato, usa GET /api/files/{mediaKey}?expireMinutes=180. La risposta contiene un URL pre-firmato temporaneo. Vedi UC-026: Download Media da Messaggi Inbound.
Step 3 — Elencare le conversazioni
Recupera le conversazioni, tenendo solo quelle con messaggi non letti:
curl -X GET "https://api.qlara.ai/api/partner-gateway/v1/inbox/conversations?unreadOnly=true" \
-H "X-Api-Key: YOUR_API_KEY"
Risposta:
[
{
"id": 1042,
"hasUnreadMessages": true,
"userName": "Marco Bianchi",
"phoneNumber": "+393471234567",
"unreadCount": 2,
"lastMessageText": "Buongiorno, vorrei sapere lo stato del mio ordine ORD-2026-1584",
"lastMessageDate": "2026-04-09 09:15:22.041+0000",
"socialMedia": "WHATSAPP",
"companyProfileName": "TechStore Italia",
"companyPhoneNumber": "+393209998877",
"whatsappWindowExpire": "2026-04-10 09:15:22.041+0000"
}
]
Step 4 — Ottenere i messaggi della conversazione
Recupera il thread completo di una conversazione:
curl -X GET "https://api.qlara.ai/api/partner-gateway/v1/inbox/conversations/1042/messages" \
-H "X-Api-Key: YOUR_API_KEY"
Risposta:
{
"profile": {
"userName": "Marco Bianchi",
"profilePicture": null,
"additionalInfo": "+393471234567"
},
"messages": [
{
"id": 5001,
"text": "Buongiorno, vorrei sapere lo stato del mio ordine ORD-2026-1584",
"isRead": false,
"isUserReply": true,
"createdAt": "2026-04-09 09:15:22.041+0000",
"attachments": [],
"status": "DELIVERED"
}
]
}
isUserReply: true indica un messaggio scritto dal contatto, false una tua risposta. Un chatId inesistente o che non appartiene al tuo account riceve 404.
Step 5 — Rispondere alla conversazione
Invia una risposta all'interno della conversazione esistente:
curl -X POST "https://api.qlara.ai/api/partner-gateway/v1/inbox/conversations/reply" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"chatId": 1042,
"message": "Buongiorno Marco! Il suo ordine ORD-2026-1584 è in fase di spedizione. Riceverà il tracking entro oggi pomeriggio."
}'
Risposta: 202 Accepted
chatId è obbligatorio. Puoi inviare anche replyTo (l'id del messaggio che stai citando) e attachments (una lista di {"mediaId": …} dalla tua libreria media). La risposta parte sul canale della conversazione; segui la consegna tramite l'evento webhook DELIVERY.
Su WhatsApp le risposte free-form sono possibili solo entro 24 ore dall'ultimo messaggio del cliente. Controlla il campo whatsappWindowExpire della conversazione. Fuori dalla finestra la risposta può comunque essere accettata (202) ma non viene consegnata: l'evento DELIVERY riporta statusCode: 12 (conversation closed). Dopo la scadenza, usa un template approvato da Meta. Vedi la guida WhatsApp.
Step 6 — Segnare come letta e archiviare
Dopo aver gestito la richiesta, segna la conversazione come letta:
curl -X PATCH "https://api.qlara.ai/api/partner-gateway/v1/inbox/conversations/1042/read" \
-H "X-Api-Key: YOUR_API_KEY"
Risposta: 204 No Content
Quando la conversazione è conclusa, archiviala:
curl -X PATCH "https://api.qlara.ai/api/partner-gateway/v1/inbox/conversations/1042/archive" \
-H "X-Api-Key: YOUR_API_KEY"
Risposta: 204 No Content
Una conversazione archiviata può essere ripristinata in qualsiasi momento con PATCH /conversations/{chatId}/unarchive. Se il contatto scrive di nuovo, di norma la conversazione torna da sola nell'inbox attiva.
Parametri di filtro delle conversazioni
| Parametro | Tipo | Descrizione |
|---|---|---|
channelIds | string | ID dei canali separati da virgola (es. WHATSAPP-123,RCS-456) |
dateFrom | string | Data ISO: solo le conversazioni aggiornate dopo questa data |
orderBy | string | Campo di ordinamento con prefisso +/- (es. -lastMessageDate) |
section | string | Sezione dell'inbox, per stato di assegnazione (es. solo le conversazioni assegnate a te o quelle non assegnate) |
unreadOnly | boolean | Se true, restituisce solo le conversazioni con messaggi non letti |
Paginazione dei messaggi
Per i thread lunghi usa i parametri idFrom (id messaggio maggiore o uguale) e idTo (id messaggio minore o uguale):
curl -X GET "https://api.qlara.ai/api/partner-gateway/v1/inbox/conversations/1042/messages?idFrom=5000&idTo=5050" \
-H "X-Api-Key: YOUR_API_KEY"
Dietro le quinte
Quando un cliente invia un messaggio, il carrier (Meta per WhatsApp, Google per RCS) lo recapita alla piattaforma Qlara, che:
- Crea o aggiorna la conversazione -- Se il contatto ha già una conversazione aperta sullo stesso canale, il messaggio viene aggiunto al thread esistente. Altrimenti ne viene creata una nuova.
- Ti avvisa via webhook -- Il payload
INBOUNDviene inviato al callback URL registrato. Il tuo server deve rispondere con un qualsiasi2xxentro 5 secondi. Le consegne fallite vengono ritentate, quindi lo stesso evento può arrivare più di una volta: deduplica sueventType+messageId. - Gestisce la finestra -- Su WhatsApp la piattaforma sposta automaticamente in avanti la scadenza della finestra di 24 ore ogni volta che il cliente scrive.
- Instrada la risposta -- Quando invii una risposta con
POST /conversations/reply, la piattaforma la invia automaticamente sullo stesso canale della conversazione originale.
Risultato atteso
| Aspetto | Dettaglio |
|---|---|
| Azione completata | Messaggio inbound ricevuto, risposta inviata, conversazione archiviata |
| Canale usato | WhatsApp / RCS |
| Conferma di consegna | Via webhook (statusCode: 3) entro 5-60 secondi |
Errori comuni
| Problema | Causa probabile | Soluzione |
|---|---|---|
HTTP 401 | API Key mancante o non valida | Controlla l'header X-Api-Key |
HTTP 409 su POST /webhooks/delivery-status | Un webhook è già configurato per l'account | Verificalo con GET /webhooks/delivery-status; cambia l'URL con PUT sullo stesso path |
HTTP 400 su POST /webhooks/delivery-status | Il callback URL non è un URL HTTPS pubblico sulla porta 443 o 8443 | Usa un URL HTTPS raggiungibile pubblicamente, senza credenziali né fragment |
HTTP 400 sulla risposta | Body malformato o chatId mancante | Invia chatId (obbligatorio) e message |
HTTP 404 — Conversazione non trovata | Il chatId non esiste o non appartiene al tuo account | Ottieni un chatId valido da GET /inbox/conversations |
| Risposta accettata ma non consegnata | La finestra WhatsApp di 24 ore è chiusa (evento DELIVERY con statusCode: 12) | Controlla whatsappWindowExpire; usa invece un template approvato da Meta |
| Nessun webhook INBOUND ricevuto | Webhook non configurato, oppure endpoint irraggiungibile o che non risponde 2xx entro 5 secondi | Verifica la registrazione con GET /webhooks/delivery-status e controlla il tuo endpoint |
Prossimi passi
- Guida Webhooks -- Configurazione completa dei webhook
- WhatsApp API -- Invio di messaggi e template WhatsApp
- RCS API -- Invio di messaggi rich con card e carousel
- UC-018: Gestire l'Inbox -- Smistare, assegnare e archiviare le conversazioni
- UC-013: Template WhatsApp -- Quando la finestra di 24 ore scade, usa i template