# Autenticación

Cada llamada que ejecuta un modelo o lee tus solicitudes necesita una clave de API. El catálogo (`GET /models`,
`GET /categories`), `POST /quote` y el documento OpenAPI son públicos.

## Claves de API

Crea y revoca claves en [https://doitong.com/developers/dashboard#keys](https://doitong.com/developers/dashboard#keys). Una clave se ve
como `doitong_` seguida de 64 caracteres hexadecimales y se muestra una sola vez, cuando la creas. Envíala en el
encabezado `Authorization`:

```bash
curl https://api.doitong.com/v1/account -H "Authorization: Bearer $DOITONG_API_KEY"
```

`X-API-Key: <key>` también funciona.

> [!WARNING]
> Conserva las claves en tu servidor: cualquiera que tenga una clave puede gastar los créditos de API que tiene permitidos. Si una clave se filtra,
> revócala y crea una nueva.

Una solicitud sin clave recibe `401` con el código `missing_api_key`; una clave desconocida, revocada o vencida también recibe `401`.

## Alcances

Cada clave tiene alcances. La API de modelos verifica estos:

| Acción | Alcance necesario |
|---|---|
| Ejecutar un modelo, cancelar una solicitud, eliminar los archivos de una solicitud, cambiar la configuración de almacenamiento | `models:run` (las claves con el antiguo `images:create` o `videos:create` también funcionan) |
| Crear una URL de carga | `models:run` o `media:upload` |
| Leer solicitudes y la cuenta | `models:read` (una clave que puede ejecutar modelos también puede leer) |

Las claves nuevas obtienen `models:read` y `models:run` de forma predeterminada. Una llamada sin el alcance correcto recibe `403` con el código
`insufficient_scope`.

## Presupuestos de créditos

Una clave puede tener su propio presupuesto en créditos de API (1,000 créditos de API = $1), establecido por el propietario de la cuenta: un presupuesto total, un
presupuesto diario (últimas 24 horas) o ambos. Antes de cobrar una ejecución, se verifica el costo comparándolo con lo que la clave ya ha
gastado mediante esta API (menos los reembolsos). Una ejecución que lo excedería se rechaza con `402 budget_exceeded` y no se cobra nada.

> [!IMPORTANT]
> El rechazo por presupuesto es definitivo: reintentar no ayudará hasta que el propietario aumente el presupuesto.

 Una clave sin presupuesto puede
gastar hasta el saldo de API. Por separado, una ejecución que el saldo de API no puede cubrir recibe `402 insufficient_credits`
con un `top_up_url`.

`GET https://api.doitong.com/v1/account` muestra el saldo de API y el presupuesto restante de la clave (ambos en créditos de API):

```json 200 OK · cuenta
{
  "object": "account",
  "credits": 125000,
  "balance": { "credits": 125000, "usd": "125.00" },
  "top_up_url": "https://doitong.com/developers/dashboard#balance",
  "key": {
    "name": "Production server",
    "prefix": "doitong_3fa9c1e...",
    "scopes": ["models:read", "models:run"],
    "budget_remaining": 50000,
    "rate_limit": 3600,
    "rate_limit_remaining": 3571
  },
  "webhook_signing_secret": "whsec_..."
}
```

`budget_remaining` es `null` cuando la clave no tiene un presupuesto propio.

## Límites de solicitudes

Cada clave puede realizar 3600 solicitudes por hora, a menos que su límite se haya establecido de otra manera. Cada respuesta autenticada incluye
el estado actual:

| Encabezado | Significado |
|---|---|
| `X-RateLimit-Limit` | Solicitudes permitidas en la ventana actual |
| `X-RateLimit-Remaining` | Solicitudes restantes en la ventana actual |
| `X-RateLimit-Reset` | Hora Unix en que se restablece la ventana |

Si superas el límite, recibes `429` con un encabezado `Retry-After` (segundos). La consulta prolongada con `?wait=` cuenta como una solicitud
por llamada, así que esperar es más económico que consultar rápidamente.

También hay un límite de 10 solicitudes en progreso (`queued` o `running`) por cuenta. Iniciar una más devuelve
`429 too_many_inflight`; iníciala de nuevo después de que termine una.
