> ## 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 y uso

>  - Consultar gastos y estadísticas de llamadas en un período
- Filtrar por modelo y agrupar por modelo o día natural
- Consultar la API Key actual o toda la cuenta
- Obtener importes en USD, créditos, llamadas y tokens 

Utilice una API Key para consultar los gastos de un período, con filtros por modelo y agrupación por modelo, día natural o ambos. El resultado agregado se devuelve directamente, sin crear tareas ni consultar su estado periódicamente.

<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", "Error al consultar el 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 ?? "Error al consultar el 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>

## Autenticación

<ParamField header="Authorization" type="string" required>
  Utilice la misma API Key que para llamar a los modelos, con autenticación Bearer Token. Obtenga la clave en la [página de gestión de API Keys](https://apimart.ai/keys).

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

<Info>
  La consulta funciona incluso con saldo 0. No se comprueba el saldo, pero sí el estado y la caducidad de la clave, la lista de IP permitidas y el estado de la cuenta.
</Info>

## Endpoints

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

Ambos endpoints tienen la misma función y admiten CORS. Proteja su API Key y no la exponga en código frontend público.

## Parámetros de solicitud

Todos los parámetros se envían en la cadena de consulta de la URL.

<ParamField query="start" type="integer | string">
  Inicio del período, incluido. Admite un timestamp Unix en segundos o una cadena RFC3339 con zona horaria, como `2026-09-01T00:00:00+08:00`.

  Si se omite, se usan 24 horas antes de `end`. Los timestamps están en segundos, no milisegundos.
</ParamField>

<ParamField query="end" type="integer | string">
  Fin del período, excluido. Mismo formato que `start`; si se omite, se usa la hora actual.

  Debe ser posterior a `start`, y `end - start` no puede superar 31 días.
</ParamField>

<ParamField query="model" type="string">
  Nombre del modelo. Si se omite, se incluyen todos los modelos. Separe varios modelos con comas; máximo `50`.

  Coincidencia exacta sin distinguir mayúsculas y minúsculas. No admite comodines.

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

<ParamField query="group_by" type="string" default="none">
  Agrupación:

  * `none`: solo el total; `items` es un array vacío
  * `model`: por modelo
  * `date`: por día natural
  * `model,date`: por modelo y día natural
</ParamField>

<ParamField query="tz" type="string" default="Asia/Shanghai">
  Nombre de zona horaria IANA. Predeterminado: `Asia/Shanghai`.

  Solo afecta a los límites de los días cuando `group_by` incluye `date`; no cambia los instantes de inicio y fin. Las horas RFC3339 se interpretan según su propia zona horaria.
</ParamField>

<ParamField query="scope" type="string" default="key">
  Ámbito de las estadísticas:

  * `key`: solo la API Key actual (predeterminado)
  * `account`: todas las API Keys de la cuenta a la que pertenece la clave actual
</ParamField>

<Note>
  El intervalo es `[start, end)`: incluye el inicio y excluye el final. Use el mismo instante para el `end` de la consulta anterior y el `start` de la siguiente para evitar duplicar el límite.

  Al construir la URL manualmente, codifique el `+` de RFC3339 como `%2B`. cURL `--data-urlencode`, Python `params` y JavaScript `URLSearchParams` en los ejemplos lo hacen automáticamente.
</Note>

## Ejemplos de solicitud

### Gastos de la API Key actual en las últimas 24 horas

Sin parámetros de consulta se utilizan el período, ámbito y agrupación predeterminados.

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

### Gastos diarios de toda la cuenta para modelos concretos

Consultar los gastos del 11 al 18 de septiembre de 2026, hora de Pekín, sin incluir el 18 de septiembre.

```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 y día natural

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

Cada elemento de `items` contiene tanto `model` como `date` con esta agrupación.

## Campos de respuesta

<ResponseField name="success" type="boolean">
  Resultado de la consulta: `true` si tiene éxito, `false` si hay un error al consultar el uso.
</ResponseField>

<ResponseField name="data" type="object">
  Si tiene éxito, devuelve el ámbito, el total y los detalles agrupados.

  <Expandable title="Propiedades de data">
    <ResponseField name="scope" type="string">
      Ámbito: `key` o `account`.
    </ResponseField>

    <ResponseField name="start" type="integer">
      Inicio efectivo como timestamp Unix en segundos, incluido.
    </ResponseField>

    <ResponseField name="end" type="integer">
      Fin efectivo como timestamp Unix en segundos, excluido.
    </ResponseField>

    <ResponseField name="tz" type="string">
      Zona horaria para la agrupación por día natural.
    </ResponseField>

    <ResponseField name="group_by" type="string">
      Agrupación: `none`, `model`, `date` o `model,date`.
    </ResponseField>

    <ResponseField name="total" type="object">
      Total del intervalo consultado. Consulte los campos estadísticos en la tabla siguiente.
    </ResponseField>

    <ResponseField name="items" type="object[]">
      Detalles agrupados en orden descendente de `amount_usd`. Array vacío si `group_by=none`. Cada elemento contiene los campos estadísticos de la tabla siguiente.

      * Si `group_by` incluye `model`, el elemento contiene `model`
      * Si `group_by` incluye `date`, el elemento contiene `date` en formato `YYYY-MM-DD`; los días se delimitan según `tz`
    </ResponseField>
  </Expandable>
</ResponseField>

`data.total` y `data.items[]` comparten estos campos estadísticos:

| Campo               | Tipo    | Descripción                                                                                      |
| ------------------- | ------- | ------------------------------------------------------------------------------------------------ |
| `amount_usd`        | number  | Importe en USD, redondeado a 6 decimales                                                         |
| `credits`           | number  | Créditos del servicio: `amount_usd × 10`, la misma unidad que en el sitio web                    |
| `requests`          | integer | Número de llamadas facturadas correctamente                                                      |
| `prompt_tokens`     | integer | Tokens de entrada; normalmente 0 para modelos de imagen y vídeo facturados por llamada o segundo |
| `completion_tokens` | integer | Tokens de salida; normalmente 0 para modelos de imagen y vídeo facturados por llamada o segundo  |

<ResponseField name="error" type="object">
  En errores de consulta de uso, contiene `code`, `message` y `type`, donde `type` es `usage_query_error`. Los errores de autenticación 401 / 403 los devuelve la capa de autenticación.
</ResponseField>

## Límites y caché

* Máximo `60` consultas por minuto por API Key; también se aplican los límites globales de la API
* Los resultados con los mismos parámetros se almacenan en caché durante `60` segundos; la cabecera `X-Usage-Cache` es `hit` o `miss`
* Los gastos suelen estar disponibles en 1 segundo, pero el último minuto puede estar incompleto y la caché puede añadir retrasos
* Se recomienda un intervalo mínimo de 1 minuto; no usar como notificación de cobro en tiempo real

## Criterios de contabilización

* Basado en llamadas facturadas correctamente, con los mismos datos que el panel del sitio web
* Se excluyen llamadas fallidas y tareas reembolsadas tras un fallo; no es necesario compensarlas manualmente. Los lotes de imágenes parcialmente completados se cobran según las imágenes realmente entregadas
* Se usa el momento de contabilización del cobro. Las tareas asíncronas de imagen y vídeo se contabilizan al finalizar, no al enviarse; las que cruzan la medianoche pertenecen al día de finalización
* Una API Key recreada tras eliminarla es una clave nueva. Su consulta `scope=key` no incluye el historial de la anterior
* Los ajustes manuales de saldo no son gastos de llamadas y se excluyen
* Están disponibles los datos posteriores al 27 de abril de 2026

## Gestión de errores

| Estado HTTP | `error.code`                    | Descripción                                                        |
| ----------- | ------------------------------- | ------------------------------------------------------------------ |
| 400         | `invalid_start` / `invalid_end` | Formato de inicio o fin no válido                                  |
| 400         | `invalid_range`                 | `end` no es posterior a `start`                                    |
| 400         | `range_too_large`               | Más de 31 días; divida el período en varias consultas              |
| 400         | `invalid_tz`                    | Zona horaria IANA desconocida                                      |
| 400         | `invalid_group_by`              | Agrupación no válida                                               |
| 400         | `invalid_scope`                 | Ámbito no válido                                                   |
| 400         | `too_many_models`               | Más de 50 modelos                                                  |
| 401 / 403   | —                               | API Key no válida o caducada, IP no permitida o cuenta desactivada |
| 429         | —                               | Más de 60 consultas por clave por minuto o límite global de la API |
| 503         | `usage_unavailable`             | Datos temporalmente no disponibles; inténtelo más tarde            |

<Warning>
  `503 usage_unavailable` no devuelve importes. Significa que la consulta no está disponible, no que los gastos sean 0. No convierta respuestas fallidas en importes cero ni sobrescriba un resultado anterior correcto.
</Warning>

## Comparación con otros endpoints

| Endpoint                          | Función                                                                                 |
| --------------------------------- | --------------------------------------------------------------------------------------- |
| `GET /v1/dashboard/billing/usage` | Solo gastos acumulados; sin filtros por modelo o período                                |
| `POST /v1/logs/export`            | Exportación asíncrona de detalles de llamadas (CSV / XLSX); debe agregarlos usted       |
| `GET /v1/usage`                   | Consulta por período y modelo con devolución directa del total y los detalles agrupados |

Para el saldo restante, use [Consultar saldo del token](/es/api-reference/account/token-balance) o [Consultar saldo del usuario](/es/api-reference/account/user-balance).
