---
title: Messaging & email
description: Conversazioni, template WhatsApp, invio messaggi WhatsApp/SMS e lettura dello stato di messaggi ed email Audin Mail con l'API REST partner.
---

Il gruppo **Messaging & email** copre l'invio e il monitoraggio delle
comunicazioni: le **conversazioni** chat, i **template WhatsApp** approvati,
l'**invio di messaggi** WhatsApp/SMS e la lettura dello **stato** di un messaggio
o di un'**email** inviata via Audin Mail.

## Le risorse

| Path | Descrizione |
|------|-------------|
| `/conversations` | Conversazioni chat (webchat, WhatsApp, widget) |
| `POST /conversations/{id}/send` | Invia testo o template in una conversazione esistente (JSON) |
| `POST /conversations/{id}/attachments` | Invia uno o più allegati in una conversazione esistente (multipart) |
| `GET /conversations/{id}/messages` | Lista messaggi di una conversazione, allegati inclusi in `media[]` |
| `/whatsapp-templates` | Template WhatsApp approvati |
| `POST /messages/send` | Invia un messaggio WhatsApp o SMS |
| `POST /messages/send-attachments` | Invia uno o più allegati a un numero (multipart) |
| `GET /messages/{id}` | Stato e metadati di un messaggio inviato |
| `GET /emails/{id}` | Stato di un'email inviata via Audin Mail |

Tutte le rotte richiedono l'header `X-API-Key`. Lo schema completo resta sullo
[Swagger](https://api.audin.ai/docs/partners).

## Inviare un messaggio

`POST /messages/send` invia un messaggio WhatsApp o SMS a un numero. Se il numero
non esiste ancora nel tuo Account, il lead e la conversazione vengono creati
automaticamente. Campi del body:

| Campo | Tipo | Obbligatorio | Note |
|-------|------|:---:|------|
| `to` | string | sì | Numero E.164 (es. `+393334445566`) |
| `channel` | enum | sì | `WHATSAPP` o `SMS` |
| `type` | enum | sì | `template` o `text` |
| `body` | string | se `type=text` | Contenuto del messaggio |
| `templateId` | string | se `type=template` | Id di un template WhatsApp **approvato** |
| `templateVars` | object | no | Variabili del template, es. `{ "1": "Mario" }` |
| `name`, `email` | string | no | Usati per il lead auto-creato (ignorati se il numero esiste già) |

<Tabs items={["curl", "JavaScript"]}>
<Tab value="curl">

```bash
curl -X POST https://api.audin.ai/messages/send \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+393334445566",
    "channel": "WHATSAPP",
    "type": "template",
    "templateId": "<whatsapp-template-id>",
    "templateVars": { "1": "Mario" }
  }'
```

</Tab>
<Tab value="JavaScript">

```js
const res = await fetch("https://api.audin.ai/messages/send", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.AUDIN_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    to: "+393334445566",
    channel: "WHATSAPP",
    type: "template",
    templateId: whatsappTemplateId,
    templateVars: { "1": "Mario" },
  }),
});
const { data } = await res.json(); // { messageId, conversationId, status }
```

</Tab>
</Tabs>

La risposta riporta `messageId`, `conversationId` e lo **status iniziale**
(`PENDING` o `SENT`). Lo status finale (consegna, lettura, errore) si legge poi
con `GET /messages/{id}`.

<Callout type="warn">
  `POST /messages/send` è una delle poche rotte che **avvolge** la risposta in un
  envelope `{ "success": true, "data": { … } }` (e gli errori in
  `{ "success": false, "error": { … } }`), per compatibilità storica — diverso dal
  formato **raw** delle altre rotte di risorsa (vedi
  [Formato e convenzioni](/docs/api-rest/formato-e-convenzioni)). Per questo
  l'esempio legge `const { data } = await res.json()`.
</Callout>

<Callout type="info">
  L'invio WhatsApp **`type=text`** richiede una finestra di conversazione aperta.
  Se la finestra è chiusa, l'unico modo per riaprirla è inviare prima un messaggio
  **`type=template`**. I codici di errore dedicati (es. finestra chiusa, template
  non approvato, nessun numero abilitato) sono descritti sullo
  [Swagger](https://api.audin.ai/docs/partners).
</Callout>

## Stato di un messaggio

`GET /messages/{id}` (usa il `messageId` ritornato dall'invio) restituisce stato
e metadati completi del messaggio, inclusi gli eventuali **allegati**.

Campi rilevanti della risposta:

- `status` — uno tra `PENDING`, `SENT`, `DELIVERED`, `READ`, `FAILED`.
- `direction` — `INBOUND` (dal cliente) o `OUTBOUND` (verso il cliente).
- `deliveredAt`, `readAt` — timestamp degli eventi (quando disponibili).
- `media` — array di allegati; ogni elemento espone un `signedUrl` temporaneo
  (TTL ~1 ora) per scaricare il file.
- `conversation` — riepilogo della conversazione di appartenenza (canale,
  stato, conteggio messaggi).

<Tabs items={["curl", "JavaScript"]}>
<Tab value="curl">

```bash
curl "https://api.audin.ai/messages/<messageId>" \
  -H "X-API-Key: $API_KEY"
```

</Tab>
<Tab value="JavaScript">

```js
const res = await fetch(`https://api.audin.ai/messages/${messageId}`, {
  headers: { "X-API-Key": process.env.AUDIN_API_KEY },
});
const message = await res.json();
console.log(message.status); // PENDING | SENT | DELIVERED | READ | FAILED

// Gli allegati espongono un URL firmato temporaneo (TTL ~1h)
for (const m of message.media ?? []) {
  console.log(m.fileName, m.signedUrl);
}
```

</Tab>
</Tabs>

<Callout type="info">
  Il `signedUrl` di un allegato scade (~1 ora): scaricalo subito o richiama
  `GET /messages/{id}` per ottenerne uno fresco. Può essere `null` se la
  generazione non è disponibile.
</Callout>

## Conversazioni e template WhatsApp

- `GET /conversations` elenca le conversazioni dell'Account (webchat, WhatsApp,
  widget). Da una conversazione puoi leggere i messaggi
  (`GET /conversations/{id}/messages`), inviare (`POST /conversations/{id}/send`)
  o effettuare un human takeover.
- `GET /whatsapp-templates` (e `GET /whatsapp-templates/approved/list` per i soli
  approvati) elenca i template WhatsApp disponibili; usa l'`id` di un template
  **approvato** come `templateId` in `POST /messages/send`.

### Inviare in una conversazione esistente

`POST /conversations/{id}/send` invia un messaggio **testo o template** in una
conversazione già identificata dal suo `id` (a differenza di `POST /messages/send`,
che risolve o crea il lead a partire dal numero). È **JSON-only**: per gli
allegati usa `POST /conversations/{id}/attachments`.

Permesso richiesto: `Conversation:UPDATE`. Body
`{ content?, templateId?, templateVars? }` — almeno uno tra `content`
(testo free-form) e `templateId` (template **approvato**) è obbligatorio.

```bash
curl -X POST https://api.audin.ai/conversations/<conversationId>/send \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Buongiorno, la richiamiamo a breve."
  }'
```

<Callout type="info">
  Il testo **free-form** è consentito solo **dentro la finestra di assistenza
  WhatsApp di 24 ore**. Fuori dalla finestra l'unico modo per riaprirla è
  inviare un messaggio **template approvato**.
</Callout>

### Inviare allegati

Gli allegati (immagini, documenti, audio, video) si inviano con endpoint
**multipart dedicati** (campi form, non JSON). Ne esistono due, a seconda che tu
abbia già una conversazione o solo un numero:

- `POST /conversations/{id}/attachments` — in una conversazione **esistente**.
- `POST /messages/send-attachments` — direttamente a un **numero** (Audin
  risolve o crea lead e conversazione, come `POST /messages/send`).

Permesso richiesto in entrambi i casi: `Conversation:UPDATE`.

WhatsApp consente **1 media per messaggio**: con più `file` Audin invia una
**sequenza di N messaggi** (uno per allegato) con una **sola chiamata** — non
devi orchestrarlo tu.

<Tabs items={["Conversazione esistente", "A un numero"]}>
<Tab value="Conversazione esistente">

Campi form: `file` (il binario — **ripeti il campo per più allegati**, max 10),
`content` (didascalia opzionale; con più file accompagna l'**ultimo**),
`saveToDrive` (`true`/`false`, default `false`).

```bash
# Più allegati: 3 messaggi, il testo accompagna l'ultimo
curl -X POST https://api.audin.ai/conversations/<conversationId>/attachments \
  -H "X-API-Key: $API_KEY" \
  -F "file=@/path/to/foto1.jpg" \
  -F "file=@/path/to/foto2.jpg" \
  -F "file=@/path/to/preventivo.pdf" \
  -F "content=In allegato le foto e il preventivo"
```

</Tab>
<Tab value="A un numero">

Stessi campi form più `to` (numero E.164) e `channel` (`WHATSAPP`/`SMS`). Il lead
e la conversazione vengono risolti o creati dal numero.

```bash
curl -X POST https://api.audin.ai/messages/send-attachments \
  -H "X-API-Key: $API_KEY" \
  -F "to=+393334445566" \
  -F "channel=WHATSAPP" \
  -F "file=@/path/to/foto1.jpg" \
  -F "file=@/path/to/preventivo.pdf" \
  -F "content=In allegato la foto e il preventivo"
```

La risposta è incapsulata nell'envelope `{ success, data }` come
`POST /messages/send`.

</Tab>
</Tabs>

Vincoli sugli allegati (validi per entrambi gli endpoint):

- **1 media per messaggio** (limite WhatsApp); più `file` ⇒ più messaggi,
  **max 10 per richiesta**.
- **Tipi ammessi:** immagini JPEG/PNG/WebP, PDF, DOC/DOCX, audio MP3/OGG/AMR,
  video MP4/3GPP.
- **Dimensione massima:** 16 MB per file.
- Con `saveToDrive=true` i file restano archiviati nel Drive dell'Account; con
  `false` (default) sono effimeri e rimossi dopo la consegna.

La risposta è un riepilogo per-file (`data.sent`, `data.total`, `data.partial`,
`data.messages[]` con `fileName`, `status` `SENT`/`FAILED`/`SKIPPED` e
`messageId`/`error`). Status: `200` = tutti inviati, `207` = invio parziale
(`partial: true`), `502` = nessuno inviato.

<Callout type="warn">
  Gli allegati sono consentiti solo **dentro la finestra di assistenza WhatsApp
  di 24 ore**: fuori dalla finestra l'invio fallisce con `422` (riapri con un
  template approvato). Un file non ammesso, oltre 16 MB, più di 10 allegati o
  nessun file restituisce `400`.
</Callout>

### Leggere i messaggi e gli allegati ricevuti

`GET /conversations/{id}/messages` elenca i messaggi della conversazione
(dal più vecchio al più recente; `limit` e `beforeId` per la paginazione).
Ogni messaggio espone in `media[]` gli allegati inviati e ricevuti: ciascun
elemento ha `url` (signed URL temporaneo, `null` se l'allegato effimero è già
stato rimosso), `mediaType` (`IMAGE`/`VIDEO`/`AUDIO`/`DOCUMENT`), `mimeType`,
`fileName` e `deletedAt`.

```bash
curl "https://api.audin.ai/conversations/<conversationId>/messages?limit=50" \
  -H "X-API-Key: $API_KEY"
```

## Stato di un'email (Audin Mail)

`GET /emails/{id}` restituisce lo stato corrente di un'email inviata via Audin
Mail, con i timestamp di ogni evento del ciclo di vita.

Campi rilevanti della risposta:

- `status` — uno tra `PENDING`, `SENT`, `DELIVERED`, `OPENED`, `CLICKED`,
  `BOUNCED`, `FAILED`, `DROPPED`.
- `sentAt`, `deliveredAt`, `openedAt`, `clickedAt`, `bouncedAt` — timestamp degli
  eventi corrispondenti (valorizzati man mano che avvengono).
- `toEmail`, `toName` — destinatario.
- `template` — il template risolto (`source` `account` o `system`), oppure
  `null` se l'email non era basata su template.

<Tabs items={["curl", "JavaScript"]}>
<Tab value="curl">

```bash
curl "https://api.audin.ai/emails/<emailLogId>" \
  -H "X-API-Key: $API_KEY"
```

</Tab>
<Tab value="JavaScript">

```js
const res = await fetch(`https://api.audin.ai/emails/${emailLogId}`, {
  headers: { "X-API-Key": process.env.AUDIN_API_KEY },
});
const email = await res.json();
// PENDING | SENT | DELIVERED | OPENED | CLICKED | BOUNCED | FAILED | DROPPED
console.log(email.status, email.openedAt);
```

</Tab>
</Tabs>

<Callout type="info">
  Come tutto il resto dell'API, lo stato di messaggi ed email è **polling-only**:
  non ci sono webhook. Interroga `GET /messages/{id}` / `GET /emails/{id}`
  periodicamente per seguire l'evoluzione. Schema completo:
  [Swagger](https://api.audin.ai/docs/partners).
</Callout>

## Prossimo passo

<Cards>
  <Card href="/docs/api-rest/lettura" title="Lettura & sistema" description="Risorse di sola lettura: utenti, ruoli, call, numeri ed endpoint di sistema." />
  <Card href="/docs/api-rest/documenti" title="Documenti" description="Invia preventivi e contratti e segui il loro stato." />
</Cards>
