---
title: Chiamate in uscita
description: Comporre una chiamata in uscita con dial, presentare un numero dell'account come caller ID e seguire gli stati della chiamata.
---

Per far partire una chiamata da un operatore usa `dial(to, { callerId })`. La
chiamata viene instradata dal **gateway Audin** verso il numero di destinazione,
presentando come mittente uno dei numeri del tuo account.

## `dial(to, { callerId })`

```ts
const numbers = await op.listPhoneNumbers();
const mine = numbers[0];

const call = await op.dial("+39021234567", { callerId: mine.phoneNumber });
```

- **`to`** — il numero di destinazione, in formato **E.164** (es.
  `"+39021234567"`).
- **`callerId`** (in `DialOptions`) — il numero da presentare come mittente.
  **DEVE essere un numero del tuo account e attivo.** Usa il campo `phoneNumber`
  (E.164) di un elemento ritornato da
  [`listPhoneNumbers()`](/docs/operator-sdk/numeri-presenza).

<Callout type="warn">
  Il `callerId` non è libero: la piattaforma richiede che sia un numero **di
  proprietà del tuo account e attivo**. Passare un numero non valido fa fallire
  la chiamata. Prendi sempre il valore da `listPhoneNumbers()` — non comporlo a
  mano.
</Callout>

La `Promise` ritornata da `dial` si risolve quando la **piattaforma accetta** la
richiesta e il bridge audio si sta aprendo. A quel punto ricevi anche l'evento
`callStarted` con lo stesso oggetto `OperatorCall`.

## Gli stati della chiamata

Una chiamata in uscita attraversa questi stati (`CallState`), leggibili dal
getter `call.state`:

| Stato | Significato |
|---|---|
| `connecting` | `dial()` accettato; il bridge audio si sta stabilendo. |
| `active` | Leg audio aperto. **Attenzione: il destinatario può ancora stare squillando** — la conversazione inizia con `callAnswered` (vedi sotto). |
| `ended` | Chiamata terminata (ispeziona `call.endReason`). |

Lo stato `ringing` riguarda invece solo le offerte **in entrata** — vedi
[Chiamate in entrata](/docs/operator-sdk/chiamate-in-entrata).

## Squillo vs conversazione: `callAnswered`

Su una chiamata in uscita il leg audio si apre **prima** che il destinatario
risponda: `callStarted` (e `state === "active"`) significano solo "audio
collegato al gateway", non "conversazione iniziata". Quando il chiamato
risponde davvero, la piattaforma lo notifica e l'SDK emette **`callAnswered`**
valorizzando `call.answered` e `call.answeredAt`:

```ts
op.on("callAnswered", (call) => {
  // Il chiamato ha risposto: fai partire il cronometro QUI.
  console.log("risposta alle", call.answeredAt);
});

op.on("callEnded", (call) => {
  if (call.answered && call.answeredAt) {
    const conversazioneMs = Date.now() - call.answeredAt.getTime();
    console.log("durata conversazione:", Math.round(conversazioneMs / 1000), "s");
  } else {
    console.log("nessuna conversazione (non risposto / occupato):", call.endReason);
  }
});
```

Sulle chiamate **in entrata** `callAnswered` viene emesso subito dopo
`callStarted` (il chiamante è già in linea quando l'operatore accetta): puoi
quindi usare `callAnswered` come unico punto di partenza dei timer in entrambe
le direzioni.

```ts
op.on("callStarted", (call) => {
  // call.direction === "outbound"
  console.log("connessa:", call.callSid);
});

op.on("callEnded", (call) => {
  console.log("terminata:", call.callSid, "motivo:", call.endReason);
});
```

I valori possibili di `call.endReason` per una chiamata in uscita includono
`hangup` (l'operatore ha riagganciato), `remote_hangup` (la controparte ha
riagganciato o la piattaforma ha chiuso), `no_answer` (il chiamato non ha
risposto) e `failed` (occupato, o un errore ha impedito di connettere).
L'elenco completo di `CallEndReason` è nella
[API reference](/docs/operator-sdk/api-reference).

`callEnded` arriva in modo affidabile anche quando il chiamato **non risponde
mai** o **riaggancia dal proprio telefono**: la piattaforma notifica la fine
chiamata sul canale di presenza, quindi non serve alcun timeout lato app.

## Controlli durante la chiamata

Sull'oggetto `OperatorCall` hai i controlli attivi:

```ts
call.mute(true);   // silenzia il microfono dell'operatore
call.mute(false);  // riattiva il microfono
console.log(call.muted); // true | false
call.hangup();     // termina la chiamata
```

Microfono, mute e audio sono trattati in dettaglio nella pagina
[Audio & microfono](/docs/operator-sdk/audio-microfono).

## Esempio completo

```ts
// 1. Scegli un numero dell'account come caller ID.
const numbers = await op.listPhoneNumbers();
const mine = numbers[0];

// 2. (Se non già online) vai online sul numero.
await op.goOnline([mine.id]);

// 3. Componi la chiamata.
const call = await op.dial("+39021234567", { callerId: mine.phoneNumber });

// 4. Segui il ciclo di vita via eventi.
op.on("callEnded", (ended) => {
  if (ended.callSid === call.callSid) {
    console.log("fine chiamata:", ended.endReason);
  }
});
```

<Callout type="warn">
  **Nessun ringback (MVP).** Durante la connessione di una chiamata in uscita
  **non c'è tono di libero**: l'operatore sente silenzio finché l'audio non è
  stabilito (stato `active`). Suggeriamo di riflettere lo stato `connecting`
  nella tua UI (es. un indicatore "in connessione…") per dare un feedback visivo
  all'operatore.
</Callout>

<Callout type="warn">
  **Una sola chiamata attiva per operatore (MVP).** Se una chiamata è già in
  corso, `dial()` **fallisce** (la `Promise` viene rigettata). Termina la
  chiamata corrente prima di comporne un'altra.
</Callout>

## Prossimi passi

<Cards>
  <Card href="/docs/operator-sdk/audio-microfono" title="Audio & microfono" description="Gestione del microfono, mute, selezione del device e diagnosi audio." />
  <Card href="/docs/operator-sdk/api-reference" title="API reference" description="dial, DialOptions, CallState e CallEndReason al completo." />
  <Card href="/docs/operator-sdk/troubleshooting" title="Troubleshooting" description="Errori comuni e domande frequenti." />
</Cards>
