---
title: Numeri & presenza
description: Elencare i numeri dell'account, andare online sui numeri voice e gestire la disponibilità dell'operatore.
---

Prima di poter ricevere o fare chiamate, un operatore deve dichiararsi
**disponibile** (online) su uno o più numeri dell'account. Questa pagina copre
l'elenco dei numeri, la gestione della presenza e lo stato dell'operatore.

## Elencare i numeri dell'account

`listPhoneNumbers()` restituisce i numeri che l'account possiede. Viene recuperato
**dall'SDK stesso**, usando lo stesso token di sessione effimero dei WebSocket:
l'Account API Key non entra mai nel browser.

```ts
const numbers = await op.listPhoneNumbers();
// → [{ id: "pn_1", phoneNumber: "+390299999999", displayName: "Milano" }, ...]
```

Ogni elemento è un `OperatorPhoneNumber`:

| Campo | Tipo | Note |
|---|---|---|
| `id` | `string` | Identificatore stabile: passalo a `goOnline([...])`. |
| `phoneNumber` | `string` | Numero in formato E.164: usalo come `callerId` per `dial`. |
| `displayName` | `string \| null` | Etichetta leggibile, quando impostata. |

Tipicamente mostri questa lista nella tua UI e lasci che l'operatore scelga su
quale numero (o numeri) operare.

<Callout type="warn">
  Se il token di sessione non è valido in modo persistente, `listPhoneNumbers()`
  lancia un `OperatorRequestError`:

  - **`UNAUTHORIZED`** — `401` persistente (l'SDK scarta il token in cache e
    riprova una volta con un token fresco; se anche quello fallisce, lancia).
  - **`REQUEST_FAILED`** — altri errori di rete o di risposta.

  In entrambi i casi assicurati che la tua callback `getToken` restituisca sempre
  un token valido (vedi [Token flow](/docs/operator-sdk/token-flow)).
</Callout>

## Modello "by-account"

La presenza è **per account**: un operatore va online sugli **id dei numeri voice
dell'account**, scelti tra quelli ritornati da `listPhoneNumbers()`. Le chiamate
in entrata su quei numeri vengono poi offerte agli operatori online, e le chiamate
in uscita possono presentare uno di quei numeri come caller ID.

## Andare online

`goOnline(phoneNumberIds)` connette il canale di presenza e annuncia la
disponibilità dell'operatore sui numeri indicati (per `id`):

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

Puoi chiamare `goOnline` di nuovo in qualsiasi momento per **cambiare l'insieme
di numeri** su cui l'operatore è disponibile.

### Conferma della disponibilità

Il server conferma su quali numeri l'operatore è effettivamente andato online
tramite l'evento `availabilityChanged`, che riporta gli id `accepted` e
`rejected`:

```ts
op.on("availabilityChanged", ({ accepted, rejected }) => {
  console.log("online su:", accepted);
  if (rejected.length) console.warn("non accettati:", rejected);
});
```

Un numero può finire tra i `rejected` se, ad esempio, non è un numero voice
valido per l'account. Usa questo evento per riflettere nella UI lo stato reale di
disponibilità.

## Andare offline

`goOffline()` annulla la disponibilità, termina l'eventuale chiamata attiva e
chiude il canale di presenza (interrompendo anche la riconnessione automatica):

```ts
await op.goOffline();
```

Chiamalo quando l'operatore fa logout o chiude l'applicazione.

## Stato della presenza

Il getter `state` espone lo stato corrente del canale di presenza
(`PresenceState`):

```ts
console.log(op.state); // "offline" | "connecting" | "online" | "reconnecting"
```

| Stato | Significato |
|---|---|
| `offline` | Non connesso; nessuna disponibilità annunciata. |
| `connecting` | Connessione del canale di presenza in corso. |
| `online` | Connesso e disponibile sui numeri confermati. |
| `reconnecting` | Connessione caduta; riconnessione automatica in corso (backoff). |

Puoi anche reagire ai cambi di stato con l'evento `presenceStateChanged`:

```ts
op.on("presenceStateChanged", (state) => {
  console.log("presenza:", state);
});
```

<Callout type="info">
  L'SDK mantiene la presenza viva con heartbeat periodici e si **riconnette
  automaticamente** secondo un backoff configurabile. Vedi le opzioni
  `heartbeatIntervalMs` e `reconnectBackoffMs` nella
  [API reference](/docs/operator-sdk/api-reference).
</Callout>

## Prossimi passi

<Cards>
  <Card href="/docs/operator-sdk/chiamate-in-entrata" title="Chiamate in entrata" description="Ricevere e accettare le offerte di chiamata sui numeri su cui sei online." />
  <Card href="/docs/operator-sdk/chiamate-in-uscita" title="Chiamate in uscita" description="Comporre una chiamata usando un numero dell'account come caller ID." />
</Cards>
