---
title: Token flow & setup backend
description: Il pattern apiKey-server-side / token-effimero-client e l'endpoint da implementare per emettere i token di sessione dell'SDK.
---

L'Operator SDK gira **nel browser**, dove un segreto non può vivere in sicurezza.
L'Account API Key — che dà pieno accesso al tuo Account — deve restare **solo sul
tuo backend**. Per questo l'SDK non riceve mai l'API Key: ottiene invece un
**token di sessione effimero** tramite una callback `getToken` che fornisci tu.

## Il pattern

```text
browser (SDK)  ──getToken()──▶  il tuo backend  ──X-API-Key──▶  Audin API
                                                                POST /operator-sessions/token
browser (SDK)  ◀──{ token }───  il tuo backend  ◀──{ token }──
```

Il tuo backend custodisce l'Account API Key, parla con l'API Audin e restituisce
al browser solo il token a vita breve. Così il segreto non lascia mai il server.

## I tre passaggi

<Steps>
<Step>
**Il client chiama il tuo endpoint.** Quando l'SDK ha bisogno di un token (alla
connessione, alla riconnessione e all'apertura del canale audio di una chiamata),
invoca la callback `getToken` che hai fornito. Tipicamente fa una `POST` a un
endpoint del **tuo** backend.
</Step>

<Step>
**Il tuo backend chiama l'API Audin.** L'endpoint, autenticandosi con l'header
`X-API-Key`, chiama `https://api.audin.ai/operator-sessions/token` indicando un
identificatore stabile dell'operatore. Audin firma un token effimero (~1 ora) e
lo restituisce.
</Step>

<Step>
**Restituisci `{ token, expiresAt? }` al client.** Il tuo endpoint inoltra al
browser almeno il `token`. Includere anche `expiresAt` (ISO-8601) è opzionale ma
consigliato: l'SDK lo usa per rinnovare il token in anticipo rispetto alla
scadenza.
</Step>
</Steps>

## Esempio: endpoint backend

L'API Key resta qui, lato server, e non entra mai nel browser:

```ts
// Sul TUO server — l'API Key sta qui, mai nel browser.
app.post("/api/operator/token", async (req, res) => {
  const r = await fetch("https://api.audin.ai/operator-sessions/token", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-Key": process.env.AUDIN_ACCOUNT_API_KEY, // segreto lato server
    },
    body: JSON.stringify({
      operatorRef: req.user.id, // il tuo identificatore stabile dell'operatore
      displayName: req.user.name,
      phoneNumberIds: req.user.assignedPhoneNumberIds,
    }),
  });
  const data = await r.json();
  // Restituisci almeno { token }. (expiresAt è opzionale ma consigliato.)
  res.json({ token: data.token, expiresAt: data.expiresAt });
});
```

<Callout type="info">
  `operatorRef` è un **identificatore stabile dell'operatore** scelto da te (es.
  l'id dell'utente nel tuo sistema): Audin lo usa per riconoscere lo stesso
  operatore tra le sessioni. Proteggi questo endpoint con la tua autenticazione,
  così solo i tuoi operatori autenticati possono richiedere un token.
</Callout>

## Durata e rinnovo del token

Il token è valido per **circa un'ora**. L'SDK chiama `getToken` ogni volta che ha
bisogno di un token nuovo — alla connessione, a ogni riconnessione e all'apertura
del canale audio di una chiamata. Per questo la tua callback deve **sempre
recuperare un token fresco**, non restituirne uno scaduto messo in cache.

```ts
const op = new AudinOperator({
  coreUrl: "https://core.audin.ai",
  getToken: async () => {
    const r = await fetch("/api/operator/token", { method: "POST" });
    return r.json(); // { token, expiresAt? }
  },
});
```

<Callout type="warn">
  - **Non esporre mai l'Account API Key nel client.** Circola esclusivamente sul
    tuo backend; nel browser vive solo il token effimero.
  - **Non cachare un token scaduto.** `getToken` deve poter sempre restituire un
    token valido: l'SDK la richiama proprio quando il precedente non è più usabile.
</Callout>

## Prossimo passo

Con l'endpoint token pronto, sei pronto per inizializzare l'SDK: vedi il
[Quickstart](/docs/operator-sdk/quickstart).
