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

# Consultar gastos e uso

>  - Consultar gastos e estatísticas de chamadas em um período
- Filtrar por modelo e agrupar por modelo ou dia civil
- Consultar a API Key atual ou a conta inteira
- Retornar valores em USD, créditos, chamadas e tokens 

Use uma API Key para consultar os gastos de um período, com filtros por modelo e agrupamento por modelo, dia civil ou ambos. O resultado agregado é retornado diretamente, sem criar tarefas nem consultar seu status repetidamente.

<RequestExample>
  ```bash cURL theme={null}
  curl --get 'https://api.apimart.ai/v1/usage' \
    --header 'Authorization: Bearer <token>' \
    --data-urlencode 'start=2026-09-01T00:00:00+08:00' \
    --data-urlencode 'end=2026-09-08T00:00:00+08:00' \
    --data-urlencode 'group_by=model'
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      "https://api.apimart.ai/v1/usage",
      headers={"Authorization": "Bearer <token>"},
      params={
          "start": "2026-09-01T00:00:00+08:00",
          "end": "2026-09-08T00:00:00+08:00",
          "group_by": "model",
      },
      timeout=30,
  )

  payload = response.json()
  if not response.ok or not payload.get("success"):
      message = payload.get("error", {}).get("message", "Falha na consulta de uso")
      raise RuntimeError(f"HTTP {response.status_code}: {message}")

  print(payload["data"]["total"])
  print(payload["data"]["items"])
  ```

  ```javascript JavaScript theme={null}
  const url = new URL("https://api.apimart.ai/v1/usage");
  url.search = new URLSearchParams({
    start: "2026-09-01T00:00:00+08:00",
    end: "2026-09-08T00:00:00+08:00",
    group_by: "model",
  }).toString();

  const response = await fetch(url, {
    headers: { Authorization: "Bearer <token>" },
  });
  const payload = await response.json();

  if (!response.ok || !payload.success) {
    throw new Error(
      `HTTP ${response.status}: ${payload.error?.message ?? "Falha na consulta de uso"}`,
    );
  }

  console.log(payload.data.total);
  console.log(payload.data.items);
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "success": true,
    "data": {
      "scope": "key",
      "start": 1788192000,
      "end": 1788796800,
      "tz": "Asia/Shanghai",
      "group_by": "model",
      "total": {
        "amount_usd": 12.3456,
        "credits": 123.456,
        "requests": 1834,
        "prompt_tokens": 902311,
        "completion_tokens": 215044
      },
      "items": [
        {
          "model": "gpt-5.6-luna",
          "amount_usd": 9.1271,
          "credits": 91.271,
          "requests": 1520,
          "prompt_tokens": 880120,
          "completion_tokens": 201300
        },
        {
          "model": "sora-2",
          "amount_usd": 3.2185,
          "credits": 32.185,
          "requests": 314,
          "prompt_tokens": 22191,
          "completion_tokens": 13744
        }
      ]
    }
  }
  ```

  ```json 400 theme={null}
  {
    "success": false,
    "error": {
      "code": "range_too_large",
      "message": "Time range must not exceed 31 days.",
      "type": "usage_query_error"
    }
  }
  ```
</ResponseExample>

## Autenticação

<ParamField header="Authorization" type="string" required>
  Use a mesma API Key das chamadas aos modelos com autenticação Bearer Token. Obtenha a chave na [página de gerenciamento de API Keys](https://apimart.ai/keys).

  ```
  Authorization: Bearer YOUR_API_KEY
  ```
</ParamField>

<Info>
  A consulta funciona mesmo com saldo 0. O saldo não é verificado, mas o status e a validade da chave, a lista de IPs permitidos e o status da conta são verificados.
</Info>

## Endpoints

```text theme={null}
GET /v1/usage
GET /usage
```

Os dois endpoints têm a mesma função e suportam CORS. Proteja sua API Key e não a exponha em código público de frontend.

## Parâmetros da requisição

Todos os parâmetros são enviados na query da URL.

<ParamField query="start" type="integer | string">
  Início do período, inclusive. Aceita timestamp Unix em segundos ou string RFC3339 com fuso horário, como `2026-09-01T00:00:00+08:00`.

  Se omitido, usa 24 horas antes de `end`. Os timestamps são em segundos, não milissegundos.
</ParamField>

<ParamField query="end" type="integer | string">
  Fim do período, exclusivo. Mesmo formato de `start`; se omitido, usa o horário atual.

  Deve ser posterior a `start`, e `end - start` não pode exceder 31 dias.
</ParamField>

<ParamField query="model" type="string">
  Nome do modelo. Se omitido, inclui todos os modelos. Separe vários modelos por vírgulas; máximo de `50`.

  Correspondência exata, sem diferenciar maiúsculas e minúsculas. Não aceita curingas.

  Exemplo: `gpt-5.6-luna,sora-2`
</ParamField>

<ParamField query="group_by" type="string" default="none">
  Agrupamento:

  * `none`: apenas o total; `items` é um array vazio
  * `model`: por modelo
  * `date`: por dia civil
  * `model,date`: por modelo e dia civil
</ParamField>

<ParamField query="tz" type="string" default="Asia/Shanghai">
  Nome de fuso horário IANA. Padrão: `Asia/Shanghai`.

  Afeta apenas os limites dos dias quando `group_by` inclui `date`, sem alterar os instantes de início e fim. Horários RFC3339 são interpretados conforme seu próprio fuso.
</ParamField>

<ParamField query="scope" type="string" default="key">
  Escopo das estatísticas:

  * `key`: apenas a API Key atual (padrão)
  * `account`: todas as API Keys da conta à qual pertence a chave atual
</ParamField>

<Note>
  O intervalo é `[start, end)`: inclui o início e exclui o fim. Use o mesmo instante para o `end` da consulta anterior e o `start` da seguinte para evitar contagem duplicada na fronteira.

  Ao montar a URL manualmente, codifique o `+` de RFC3339 como `%2B`. cURL `--data-urlencode`, Python `params` e JavaScript `URLSearchParams` nos exemplos fazem isso automaticamente.
</Note>

## Exemplos de requisição

### Total da API Key atual nas últimas 24 horas

Sem parâmetros de query, são usados o período, escopo e agrupamento padrão.

```bash theme={null}
curl 'https://api.apimart.ai/v1/usage' \
  --header 'Authorization: Bearer <token>'
```

### Gastos diários da conta inteira para modelos específicos

Consultar os gastos de 11 a 18 de setembro de 2026 no horário de Pequim, excluindo 18 de setembro.

```bash theme={null}
curl --get 'https://api.apimart.ai/v1/usage' \
  --header 'Authorization: Bearer <token>' \
  --data-urlencode 'start=1789056000' \
  --data-urlencode 'end=1789660800' \
  --data-urlencode 'model=gpt-5.6-luna' \
  --data-urlencode 'group_by=date' \
  --data-urlencode 'scope=account' \
  --data-urlencode 'tz=Asia/Shanghai'
```

### Agrupar por modelo e dia civil

```bash theme={null}
curl --get 'https://api.apimart.ai/v1/usage' \
  --header 'Authorization: Bearer <token>' \
  --data-urlencode 'start=2026-09-01T00:00:00+08:00' \
  --data-urlencode 'end=2026-09-08T00:00:00+08:00' \
  --data-urlencode 'model=gpt-5.6-luna,sora-2' \
  --data-urlencode 'group_by=model,date' \
  --data-urlencode 'tz=Asia/Shanghai'
```

Nesse agrupamento, cada elemento de `items` contém `model` e `date`.

## Campos da resposta

<ResponseField name="success" type="boolean">
  Sucesso da consulta: `true` em caso de sucesso e `false` em caso de erro na consulta de uso.
</ResponseField>

<ResponseField name="data" type="object">
  Em caso de sucesso, retorna o escopo, o total e os detalhes agrupados.

  <Expandable title="Propriedades de data">
    <ResponseField name="scope" type="string">
      Escopo: `key` ou `account`.
    </ResponseField>

    <ResponseField name="start" type="integer">
      Início efetivo como timestamp Unix em segundos, inclusive.
    </ResponseField>

    <ResponseField name="end" type="integer">
      Fim efetivo como timestamp Unix em segundos, exclusivo.
    </ResponseField>

    <ResponseField name="tz" type="string">
      Fuso horário usado no agrupamento por dia civil.
    </ResponseField>

    <ResponseField name="group_by" type="string">
      Agrupamento: `none`, `model`, `date` ou `model,date`.
    </ResponseField>

    <ResponseField name="total" type="object">
      Total do intervalo consultado. Veja os campos estatísticos na tabela abaixo.
    </ResponseField>

    <ResponseField name="items" type="object[]">
      Detalhes agrupados em ordem decrescente de `amount_usd`. Array vazio se `group_by=none`. Cada elemento contém os campos estatísticos da tabela abaixo.

      * Se `group_by` inclui `model`, o elemento contém `model`
      * Se `group_by` inclui `date`, o elemento contém `date` no formato `YYYY-MM-DD`; os dias seguem `tz`
    </ResponseField>
  </Expandable>
</ResponseField>

`data.total` e `data.items[]` compartilham os campos estatísticos a seguir:

| Campo               | Tipo    | Descrição                                                                                      |
| ------------------- | ------- | ---------------------------------------------------------------------------------------------- |
| `amount_usd`        | number  | Valor em USD, arredondado para 6 casas decimais                                                |
| `credits`           | number  | Créditos do serviço: `amount_usd × 10`, na mesma unidade do site                               |
| `requests`          | integer | Número de chamadas faturadas com sucesso                                                       |
| `prompt_tokens`     | integer | Tokens de entrada; geralmente 0 para modelos de imagem e vídeo cobrados por chamada ou segundo |
| `completion_tokens` | integer | Tokens de saída; geralmente 0 para modelos de imagem e vídeo cobrados por chamada ou segundo   |

<ResponseField name="error" type="object">
  Em erros de consulta de uso, contém `code`, `message` e `type`, sendo `type` igual a `usage_query_error`. Erros de autenticação 401 / 403 são retornados pela camada de autenticação.
</ResponseField>

## Limites e cache

* Máximo de `60` consultas por minuto por API Key; limites globais da API também se aplicam
* Resultados com os mesmos parâmetros ficam em cache por `60` segundos; o cabeçalho `X-Usage-Cache` é `hit` ou `miss`
* Os gastos geralmente aparecem em até 1 segundo, mas o último minuto pode estar incompleto e há possíveis atrasos do cache
* Recomenda-se intervalo de pelo menos 1 minuto; não use como notificação de cobrança em tempo real

## Critérios de contabilização

* Baseado em chamadas faturadas com sucesso, com os mesmos dados do painel do site
* Chamadas com falha e tarefas reembolsadas após falha são excluídas; não é preciso compensá-las manualmente. Lotes de imagens parcialmente bem-sucedidos são cobrados pelas imagens efetivamente entregues
* Considera o momento do lançamento da cobrança. Tarefas assíncronas de imagem e vídeo são contabilizadas na conclusão, não no envio; tarefas que passam da meia-noite pertencem ao dia da conclusão
* Uma API Key recriada após exclusão é uma nova chave. A consulta `scope=key` da nova chave não inclui o histórico da anterior
* Ajustes manuais de saldo não são gastos de chamadas e ficam fora das estatísticas
* Dados posteriores a 27 de abril de 2026 estão disponíveis

## Tratamento de erros

| Status HTTP | `error.code`                    | Descrição                                                          |
| ----------- | ------------------------------- | ------------------------------------------------------------------ |
| 400         | `invalid_start` / `invalid_end` | Formato inválido de início ou fim                                  |
| 400         | `invalid_range`                 | `end` não é posterior a `start`                                    |
| 400         | `range_too_large`               | Mais de 31 dias; divida em vários intervalos                       |
| 400         | `invalid_tz`                    | Fuso horário IANA desconhecido                                     |
| 400         | `invalid_group_by`              | Agrupamento inválido                                               |
| 400         | `invalid_scope`                 | Escopo inválido                                                    |
| 400         | `too_many_models`               | Mais de 50 modelos                                                 |
| 401 / 403   | —                               | API Key inválida ou expirada, IP não permitido ou conta desativada |
| 429         | —                               | Mais de 60 consultas por chave por minuto ou limite global da API  |
| 503         | `usage_unavailable`             | Dados temporariamente indisponíveis; tente novamente mais tarde    |

<Warning>
  `503 usage_unavailable` não retorna valores monetários. Significa que a consulta está indisponível, não que os gastos são 0. Não converta falhas em valores zero nem sobrescreva um resultado anterior bem-sucedido.
</Warning>

## Comparação com outros endpoints

| Endpoint                          | Recurso                                                                              |
| --------------------------------- | ------------------------------------------------------------------------------------ |
| `GET /v1/dashboard/billing/usage` | Apenas gastos acumulados; sem filtro por modelo ou período                           |
| `POST /v1/logs/export`            | Exportação assíncrona dos detalhes de chamadas (CSV / XLSX); agregação por sua conta |
| `GET /v1/usage`                   | Consulta por período e modelo com retorno direto do total e dos detalhes agrupados   |

Para o saldo restante, use [Consultar saldo do token](/pt/api-reference/account/token-balance) ou [Consultar saldo do usuário](/pt/api-reference/account/user-balance).
