> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sunra.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Utilizzo dei token

Ogni risposta LLM include un oggetto `usage` che riporta i token consumati dalla richiesta. Sunra riporta l'utilizzo secondo la semantica dell'endpoint che hai chiamato: una risposta Messages segue il contratto Anthropic, mentre una risposta Chat Completions o Responses segue il contratto OpenAI.

Queste forme differiscono, deliberatamente. Un SDK OpenAI che legge una risposta Chat Completions presuppone la semantica OpenAI, e un SDK Anthropic che legge una risposta Messages presuppone la semantica Anthropic. Ogni endpoint rispetta quanto promette la propria specifica invece di essere forzato in un'unica forma condivisa.

| Endpoint               | Campo di conteggio del prompt | I token letti dalla cache sono inclusi?                                               |
| ---------------------- | ----------------------------- | ------------------------------------------------------------------------------------- |
| `/v1/messages`         | `input_tokens`                | No — i tre bucket di input sono mutuamente esclusivi                                  |
| `/v1/chat/completions` | `prompt_tokens`               | Sì — i token della cache sono un sottoinsieme, dettagliato in `prompt_tokens_details` |
| `/v1/responses`        | `input_tokens`                | Sì — i token della cache sono un sottoinsieme, dettagliato in `input_tokens_details`  |

<Warning>
  `/v1/messages` e `/v1/responses` utilizzano entrambi il nome di campo `input_tokens`, che però non significa la stessa cosa nei due casi. Su Messages indica solo l'input nuovo. Su Responses indica l'intero prompt, inclusi i token letti dalla cache.
</Warning>

## Messages

Su `/v1/messages`, i tre bucket di input sono **mutuamente esclusivi**. Nessun token viene conteggiato due volte, quindi il totale del prompt è la loro somma:

```
total prompt = input_tokens + cache_creation_input_tokens + cache_read_input_tokens
```

<ResponseField name="input_tokens" type="integer">
  Solo i token di input nuovi. Esclude entrambi i bucket di cache.
</ResponseField>

<ResponseField name="cache_creation_input_tokens" type="integer">
  Token scritti nella cache da questa richiesta.
</ResponseField>

<ResponseField name="cache_read_input_tokens" type="integer">
  Token serviti a questa richiesta dalla cache.
</ResponseField>

<ResponseField name="output_tokens" type="integer">
  Token generati dal modello.
</ResponseField>

<ResponseField name="total_tokens" type="integer">
  I tre bucket di input più `output_tokens`. Presente nelle risposte non in streaming.
</ResponseField>

Un bucket assente o `null` conta come zero.

### Esempio pratico

Lo stesso prefisso da 19.000 token inviato due volte a `claude-opus-4-8`. La prima richiesta scrive la cache; la seconda la legge.

```json Richiesta a freddo (scrittura in cache) theme={null}
{
  "usage": {
    "input_tokens": 8,
    "cache_creation_input_tokens": 19349,
    "cache_read_input_tokens": 0,
    "output_tokens": 2,
    "total_tokens": 19359,
    "sunra_usage_semantics": "anthropic.exclusive.v1"
  }
}
```

```json Richiesta a caldo (lettura dalla cache) theme={null}
{
  "usage": {
    "input_tokens": 8,
    "cache_creation_input_tokens": 0,
    "cache_read_input_tokens": 19349,
    "output_tokens": 2,
    "total_tokens": 19359,
    "sunra_usage_semantics": "anthropic.exclusive.v1"
  }
}
```

`input_tokens` rimane a 8 in entrambe le richieste, perché 8 è l'input effettivamente nuovo ogni volta. Il prefisso da 19.349 token passa dal bucket di creazione al bucket di lettura. Entrambe le richieste sommano allo stesso totale di 19.359 token ma non hanno lo stesso costo: le scritture in cache e le letture dalla cache sono tariffate con proprie tariffe per token, ed è per questo che sono riportate come bucket separati.

## Chat Completions e Responses

Questi endpoint riportano la semantica OpenAI, invariata. Il conteggio del prompt è il prompt **intero**, e i token della cache ne sono un **sottoinsieme** riportato separatamente.

```json /v1/chat/completions theme={null}
{
  "usage": {
    "prompt_tokens": 19357,
    "completion_tokens": 2,
    "total_tokens": 19359,
    "prompt_tokens_details": {
      "cached_tokens": 19349
    }
  }
}
```

Sommare `prompt_tokens` e `cached_tokens` porta a un doppio conteggio. Per ottenere l'input nuovo su questi endpoint, sottrai:

```
fresh input = prompt_tokens - prompt_tokens_details.cached_tokens
```

La stessa regola vale per `/v1/responses` con `input_tokens` e `input_tokens_details.cached_tokens`.

## Il marcatore `sunra_usage_semantics`

Le risposte che Sunra ha normalizzato contengono un marcatore all'interno di `usage`:

```json theme={null}
"sunra_usage_semantics": "anthropic.exclusive.v1"
```

Il marcatore è una promessa sulla **risposta**, non su un singolo evento o campo. In una risposta non in streaming compare nell'oggetto `usage` radice; in una risposta in streaming compare in `message_start`, l'evento che contiene i bucket di input. Quando è presente con questo valore, valgono le garanzie descritte in questa pagina: i tre bucket di input sono mutuamente esclusivi e `total_tokens` — dove presente — è la loro somma più `output_tokens`.

**Anche la sua assenza è una promessa.** Sunra normalizza solo le forme di risposta che ha misurato. Tutto il resto viene inoltrato dal provider upstream senza modifiche e lasciato senza marcatore, e una risposta priva del marcatore è una risposta per i cui bucket Sunra non offre garanzie.

Verifica il marcatore invece di ispezionare i numeri per indovinare quale convenzione segue una risposta. Il riconoscimento della forma è proprio ciò che questo campo esiste per sostituire: un'euristica come "i bucket devono essere esclusivi perché la loro somma supera il conteggio del prompt" è soddisfatta da più di una convenzione e prima o poi leggerà una risposta in modo errato.

```python theme={null}
usage = response["usage"]

if usage.get("sunra_usage_semantics") == "anthropic.exclusive.v1":
    total_prompt = (
        usage["input_tokens"]
        + usage.get("cache_creation_input_tokens", 0)
        + usage.get("cache_read_input_tokens", 0)
    )
else:
    # Not normalized by Sunra. Treat the upstream shape as unverified
    # and consult that provider's own documentation.
    total_prompt = None
```

Solo le risposte di `/v1/messages` contengono il marcatore. Chat Completions e Responses seguono la specifica OpenAI e non sono marcate.

Il valore è versionato. Una modifica incompatibile al significato di questi campi viene rilasciata con un nuovo valore, così un controllo di uguaglianza con `anthropic.exclusive.v1` non inizierà silenziosamente a leggere un contratto diverso.

## Streaming

In una richiesta Messages in streaming, l'utilizzo arriva in due eventi. `message_start` contiene il lato input e il marcatore. Il `message_delta` finale contiene solo `output_tokens`. Verifica il marcatore in `message_start`, poi esegui la consueta fusione dei due eventi — applicare l'utilizzo dell'evento successivo su quello precedente — per ottenere i valori documentati sopra.

`total_tokens` è omesso dalle risposte in streaming. Nessun singolo evento conosce sia il lato input sia il lato output, quindi qualsiasi totale calcolato durante lo stream sarebbe errato. Somma tu stesso i bucket una volta completato lo stream.

## Migrazione dal comportamento precedente

In precedenza Sunra inoltrava l'oggetto `usage` upstream così com'era su `/v1/messages`. Il livello di traduzione davanti ad alcuni provider ripiega i token di creazione della cache **dentro** `input_tokens`, quindi un chiamante che seguiva il contratto Anthropic e sommava i tre bucket conteggiava due volte i token di creazione della cache.

* **Se sommi i tre bucket**, come descrive il contratto Anthropic, ora sei nel giusto. Non è richiesta alcuna modifica da parte tua.
* **Se avevi compensato il vecchio comportamento** — sottraendo tu stesso `cache_creation_input_tokens` da `input_tokens`, o ricostruendo in altro modo il ripiegamento — **smetti**. Quella correzione ora sottrae token che erano già esclusi e sottostimerà il tuo input.
* **Se leggi `total_tokens`**, il campo continua a riportare il conteggio completo: input nuovo, entrambi i bucket di cache e output.

Vincola la modifica al marcatore anziché a una data di rilascio, così lo stesso percorso di codice sarà corretto sia con risposte marcate sia con risposte non marcate.
