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

# Reportar saldos

> Envie as leituras de saldo de licenças para a Aira em lote, com validação atômica e histórico versionado por cliente.

> Sua aplicação informa quantas licenças cada cliente tem naquele momento. Cada leitura declara um estado, não acumula como um evento, e a Aira cobra a última quantidade conhecida a cada ciclo.

<h2 id="enviar-as-leituras">
  Enviar as leituras
</h2>

Sua aplicação envia as leituras em lote, com uma chave de API que tenha a permissão `licenses:write`.

```bash theme={null}
curl -X POST https://api.useaira.com/v1/licenses/report-balances \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: sua_chave_api" \
  -d '{
    "balances": [
      {
        "code": "usuarios_ativos",
        "customerExternalId": "acme_001",
        "occurredAt": "2024-01-15T03:00:00Z",
        "total": 3,
        "payload": [
          { "id": "u_1024", "name": "Ana Souza", "perfil": "admin" },
          { "id": "u_1088", "name": "Bruno Lima", "perfil": "operador" },
          { "id": "u_1153", "name": "Carla Dias", "perfil": "operador" }
        ]
      }
    ]
  }'
```

| Campo                | Descrição                                                                                                                                 |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `code`               | Código da licença no catálogo, sensível a maiúsculas e minúsculas                                                                         |
| `customerExternalId` | ID externo do cliente. Um ID que não existe no cadastro é aceito e gravado, mas nunca entra em nenhuma fatura                             |
| `occurredAt`         | Momento da leitura em ISO 8601 **com fuso explícito**, como `2024-01-15T03:00:00Z`. Não pode estar no futuro                              |
| `total`              | Quantidade reportada. Inteiro maior ou igual a `0`                                                                                        |
| `payload`            | Um item por unidade contada, cada um com um `id` e, opcionalmente, um `name`. O tamanho do array deve ser **exatamente igual** ao `total` |

<Tip>
  Você pode enviar até **10.000 leituras por requisição**, em um corpo de até 16 MiB. Não há limite de requisições por minuto, mas recomendamos distribuir o envio ao longo do tempo para evitar picos.
</Tip>

O `payload` existe para auditoria: sem ele, uma fatura afirmaria "47 usuários" sem que ninguém pudesse conferir **quais** 47. Chaves além de `id` e `name` são preservadas como propriedades da unidade, visíveis junto da leitura.

<Frame>
  <img src="https://mintcdn.com/aira-e93056c6/EK-hZ7zZzaymZBxr/static/license-balance-drawer.png?fit=max&auto=format&n=EK-hZ7zZzaymZBxr&q=85&s=9b39380adf2c2087dad510e3f2d714cf" alt="Aira — Itens do payload de uma leitura, na aba Atual" width="4056" height="2380" data-path="static/license-balance-drawer.png" />
</Frame>

<br />

<h2 id="lote-atomico">
  Lote atômico
</h2>

O envio opera como uma **transação atômica**: se qualquer leitura do lote falhar na validação, nenhuma leitura é registrada.

<Note>
  Se você enviar 500 leituras e 1 tiver o `code` errado, as 499 válidas também são rejeitadas. Valide antes de enviar ou trate o erro e reenvie o lote corrigido. Os códigos de erro estão em [Respostas de erro](/api-reference/error-responses).
</Note>

<br />

<h2 id="correcoes-e-versionamento">
  Correções e versionamento
</h2>

Uma leitura é identificada pela combinação de `code`, `customerExternalId` e `occurredAt`. O histórico é somente-anexação: nada é atualizado nem apagado.

* **Reenvio idêntico** não grava nada, então timeouts e retentativas não criam duplicatas
* **Reenvio com `total` ou `payload` diferente** anexa uma nova versão que passa a valer, e o histórico mostra o dia marcado como **Corrigido**
* **Um `occurredAt` novo** é uma leitura independente, com seu próprio histórico de versões

<Frame>
  <img src="https://mintcdn.com/aira-e93056c6/EK-hZ7zZzaymZBxr/static/license-balance-history.png?fit=max&auto=format&n=EK-hZ7zZzaymZBxr&q=85&s=84f13c10d639daee7af799578e15ae5f" alt="Aira — Histórico de saldos de um cliente, com um dia marcado como Corrigido" width="4056" height="2380" data-path="static/license-balance-history.png" />
</Frame>

<Note>
  Uma correção enviada depois que a fatura do ciclo já foi emitida **não altera essa fatura**. Cada cálculo é fixado nas versões que existiam quando ele rodou.
</Note>

<br />

<h2 id="boas-praticas">
  Boas práticas
</h2>

* **Reporte uma leitura por cliente por dia:** a quantidade de um dia é definida pela última leitura enviada até o fim daquele dia. Se nenhuma leitura chegar, a última quantidade conhecida é mantida, inclusive por ciclos inteiros.

* **Para corrigir o passado, reenvie o mesmo momento:** repita `code`, `customerExternalId` e `occurredAt` com o `total` e o `payload` corretos.

* **Para carregar histórico, envie os momentos passados:** cada `occurredAt` distinto é uma leitura independente, então um único lote pode cobrir meses.

<br />

<h2 id="proximos-passos">
  Próximos passos
</h2>

* [Licenças](/licencas/visao-geral) — o que são licenças e como criar o catálogo
* [Planos](/planos/criar-planos) — monte o plano que vai precificar a licença
