# Authentification

Tout appel qui exécute un modèle ou lit vos requêtes nécessite une clé API. Le catalogue (`GET /models`,
`GET /categories`), `POST /quote` et le document OpenAPI sont publics.

## Clés API

Créez et révoquez des clés à l’adresse [https://doitong.com/developers/dashboard#keys](https://doitong.com/developers/dashboard#keys). Une clé ressemble
à `doitong_` suivi de 64 caractères hexadécimaux et ne s’affiche qu’une seule fois, lors de sa création. Envoyez-la dans l’en-tête
`Authorization` :

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

`X-API-Key: <key>` fonctionne également.

> [!WARNING]
> Conservez les clés sur votre serveur : toute personne possédant une clé peut dépenser les crédits API qu’elle est autorisée à utiliser. Si une clé fuit,
> révoquez-la et créez-en une nouvelle.

Une requête sans clé reçoit `401` avec le code `missing_api_key` ; une clé inconnue, révoquée ou expirée reçoit également `401`.

## Périmètres

Chaque clé possède des périmètres. L’API des modèles vérifie les suivants :

| Action | Périmètre requis |
|---|---|
| Exécuter un modèle, annuler une requête, supprimer les fichiers d’une requête, modifier le paramètre de stockage | `models:run` (les clés avec l’ancien `images:create` ou `videos:create` fonctionnent également) |
| Créer une URL d’envoi | `models:run` ou `media:upload` |
| Lire les requêtes et le compte | `models:read` (une clé autorisée à exécuter des modèles peut également les lire) |

Les nouvelles clés reçoivent `models:read` et `models:run` par défaut. Un appel sans le périmètre approprié reçoit `403` avec le code
`insufficient_scope`.

## Budgets de crédits

Une clé peut avoir son propre budget en crédits API (1 000 crédits API = 1 $), défini par le propriétaire du compte : un budget total, un
budget quotidien (24 dernières heures), ou les deux. Avant de facturer une exécution, le coût est comparé à ce que la clé a déjà
dépensé via cette API (remboursements déduits). Une exécution qui le dépasserait est refusée avec `402 budget_exceeded` et rien
n’est facturé.

> [!IMPORTANT]
> Un refus lié au budget est définitif : réessayer ne servira à rien tant que le propriétaire n’aura pas augmenté le budget.

 Une clé sans budget peut
dépenser jusqu’au solde API. Par ailleurs, une exécution que le solde API ne peut pas couvrir reçoit `402 insufficient_credits`
avec un `top_up_url`.

`GET https://api.doitong.com/v1/account` affiche le solde API et le budget restant de la clé (tous deux en crédits API) :

```json 200 OK · account
{
  "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` vaut `null` lorsque la clé ne possède pas son propre budget.

## Limites de débit

Chaque clé peut effectuer 3600 requêtes par heure, sauf si sa limite a été configurée différemment. Chaque réponse authentifiée contient
l’état actuel :

| En-tête | Signification |
|---|---|
| `X-RateLimit-Limit` | Requêtes autorisées dans la fenêtre actuelle |
| `X-RateLimit-Remaining` | Requêtes restantes dans la fenêtre actuelle |
| `X-RateLimit-Reset` | Heure Unix de réinitialisation de la fenêtre |

Au-delà de la limite, vous recevez `429` avec un en-tête `Retry-After` (secondes). L’interrogation longue avec `?wait=` compte comme une requête
par appel ; attendre coûte donc moins cher qu’interroger rapidement.

Il existe également une limite de 10 requêtes en cours (`queued` ou `running`) par compte. Le démarrage d’une requête supplémentaire renvoie
`429 too_many_inflight` ; relancez-la lorsqu’une requête est terminée.
