> ## 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.

# Uso de tokens

Toda resposta de LLM carrega um objeto `usage` que informa os tokens que a requisição consumiu. Sunra informa o uso na semântica do endpoint que você chamou: uma resposta Messages segue o contrato Anthropic, e uma resposta Chat Completions ou Responses segue o contrato OpenAI.

Esses formatos diferem, deliberadamente. Um SDK OpenAI lendo uma resposta Chat Completions assume a semântica OpenAI, e um SDK Anthropic lendo uma resposta Messages assume a semântica Anthropic. Cada endpoint honra o que sua própria especificação promete, em vez de ser forçado a um formato único compartilhado.

| Endpoint               | Campo de contagem do prompt | Os tokens em cache estão incluídos nele?                                           |
| ---------------------- | --------------------------- | ---------------------------------------------------------------------------------- |
| `/v1/messages`         | `input_tokens`              | Não — os três buckets de entrada são mutuamente exclusivos                         |
| `/v1/chat/completions` | `prompt_tokens`             | Sim — os tokens em cache são um subconjunto, detalhados em `prompt_tokens_details` |
| `/v1/responses`        | `input_tokens`              | Sim — os tokens em cache são um subconjunto, detalhados em `input_tokens_details`  |

<Warning>
  `/v1/messages` e `/v1/responses` usam ambos o nome de campo `input_tokens`, e ele não significa a mesma coisa nos dois. Em Messages, é apenas a entrada nova. Em Responses, é o prompt inteiro, tokens em cache incluídos.
</Warning>

## Messages

Em `/v1/messages`, os três buckets de entrada são **mutuamente exclusivos**. Nenhum token é contado duas vezes, então o total do prompt é a soma deles:

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

<ResponseField name="input_tokens" type="integer">
  Apenas os tokens de entrada novos. Exclui ambos os buckets de cache.
</ResponseField>

<ResponseField name="cache_creation_input_tokens" type="integer">
  Tokens escritos no cache por esta requisição.
</ResponseField>

<ResponseField name="cache_read_input_tokens" type="integer">
  Tokens servidos a esta requisição a partir do cache.
</ResponseField>

<ResponseField name="output_tokens" type="integer">
  Tokens gerados pelo modelo.
</ResponseField>

<ResponseField name="total_tokens" type="integer">
  Os três buckets de entrada mais `output_tokens`. Presente em respostas não-streaming.
</ResponseField>

Um bucket ausente ou `null` conta como zero.

### Exemplo prático

O mesmo prefixo de 19.000 tokens enviado duas vezes contra `claude-opus-4-8`. A primeira requisição escreve o cache; a segunda o lê.

```json Requisição fria (escrita no 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 Requisição quente (leitura do 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` permanece em 8 nas duas requisições, porque 8 é a entrada genuinamente nova em cada uma. O prefixo de 19.349 tokens passa do bucket de criação para o bucket de leitura. Ambas as requisições somam os mesmos 19.359 tokens no total, mas não custam o mesmo: escritas de cache e leituras de cache são precificadas com suas próprias taxas por token, e é por isso que são reportadas como buckets separados.

## Chat Completions e Responses

Esses endpoints reportam a semântica OpenAI, inalterada. A contagem do prompt é o prompt **inteiro**, e os tokens em cache são um **subconjunto** dele, reportado separadamente.

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

Somar `prompt_tokens` e `cached_tokens` conta em duplicidade. Para obter a entrada nova nesses endpoints, subtraia:

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

A mesma regra se aplica a `/v1/responses` com `input_tokens` e `input_tokens_details.cached_tokens`.

## O marcador `sunra_usage_semantics`

Respostas que Sunra normalizou carregam um marcador dentro de `usage`:

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

O marcador é uma promessa sobre a **resposta**, não sobre qualquer evento ou campo individual. Em uma resposta não-streaming ele aparece no objeto `usage` raiz; em uma resposta com streaming ele aparece em `message_start`, o evento que carrega os buckets de entrada. Quando ele está presente com este valor, as garantias desta página valem: os três buckets de entrada são mutuamente exclusivos, e `total_tokens` — quando presente — é a soma deles mais `output_tokens`.

**A ausência dele também é uma promessa.** Sunra normaliza apenas os formatos de resposta que mediu. Qualquer outro é encaminhado do provedor upstream intocado e deixado sem marcação, e uma resposta sem o marcador é uma resposta cujos buckets Sunra não garante.

Verifique o marcador em vez de inspecionar os números para adivinhar qual convenção uma resposta segue. Farejar o formato é exatamente o que este campo existe para substituir — uma heurística como "os buckets devem ser exclusivos porque somam mais do que a contagem do prompt" é satisfeita por mais de uma convenção e mais cedo ou mais tarde lerá uma resposta de forma errada.

```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
```

Apenas respostas de `/v1/messages` carregam o marcador. Chat Completions e Responses seguem a especificação OpenAI e não são marcadas.

O valor é versionado. Uma mudança incompatível no significado desses campos é publicada sob um novo valor, então uma verificação de igualdade contra `anthropic.exclusive.v1` não começará silenciosamente a ler um contrato diferente.

## Streaming

Em uma requisição Messages com streaming, o uso chega em dois eventos. `message_start` carrega o lado da entrada e o marcador. O `message_delta` final carrega apenas `output_tokens`. Verifique o marcador em `message_start` e então faça a fusão usual dos dois eventos — aplicar o uso do evento posterior sobre o anterior — para chegar aos valores documentados acima.

`total_tokens` é omitido em respostas com streaming. Nenhum evento isolado conhece tanto o lado da entrada quanto o da saída, então qualquer total calculado no meio do stream estaria errado. Some os buckets você mesmo depois que o stream terminar.

## Migrando do comportamento anterior

Sunra anteriormente encaminhava o objeto `usage` upstream literalmente em `/v1/messages`. A camada de tradução na frente de alguns provedores dobra os tokens de criação de cache **dentro** de `input_tokens`, então quem seguia o contrato Anthropic e somava os três buckets contava os tokens de criação de cache duas vezes.

* **Se você soma os três buckets**, como o contrato Anthropic descreve, você agora está correto. Nenhuma mudança é necessária do seu lado.
* **Se você compensava o comportamento antigo** — subtraindo `cache_creation_input_tokens` de `input_tokens` você mesmo, ou de outra forma fazendo engenharia reversa da dobra — **pare**. Essa correção agora subtrai tokens que já estavam excluídos e vai subestimar sua entrada.
* **Se você lê `total_tokens`**, ele continua reportando a contagem completa: entrada nova, ambos os buckets de cache e saída.

Condicione a mudança ao marcador em vez de a uma data de deploy, para que o mesmo caminho de código esteja correto tanto com respostas marcadas quanto não marcadas.
