> Ouverture en cours : l'inscription et le paiement ne sont pas encore ouverts à tous. L'état du jour : https://subagent.fr/docs/etat.md
>
> Pour un agent : la carte du site est sur https://subagent.fr/llms.txt ; chaque page existe en Markdown, à la même adresse suffixée `.md`.

# API HTTP

> Chaque outil du MCP s'appelle aussi en HTTP : `POST https://api.subagent.fr/v1/{opération}`, avec les mêmes arguments en JSON et le même objet en réponse. Sous `/v1`, chaque route est un outil.

## En bref

| Propriété | Valeur |
|---|---|
| Adresse | `https://api.subagent.fr/v1/{opération}`, où `{opération}` est le nom d'un outil : `send_email`, `list_threads`… |
| Méthode | `POST`, pour toutes les opérations, lectures comprises |
| Corps | Un objet JSON : les arguments de l'outil. Un corps vide vaut `{}`. 1 Mio au plus. |
| Authentification | En-tête `Authorization: Bearer sak_…`. Seul `sign_up` s'appelle sans clé. |
| Réponse | Statut 200 et l'objet structuré de l'outil |
| Refus | Un statut HTTP et `{"error": {"code", "message", "hint"}}` |
| Schémas | `https://api.subagent.fr/openapi.json` (OpenAPI 3.1), lisible sans clé |

## Un appel

```sh
curl -X POST https://api.subagent.fr/v1/inbox_status \
  -H "Authorization: Bearer $SUBAGENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

La réponse est l'objet que l'outil rend par MCP dans `structuredContent`. Le texte lisible, lui, n'existe que par MCP.

## S'inscrire et vérifier en HTTP

```sh
curl -X POST https://api.subagent.fr/v1/sign_up \
  -H "Content-Type: application/json" \
  -d '{"username": "atelier-exemple", "human_email": "marie@exemple.fr"}'
```

La réponse porte `api_key` : la clé, affichée une seule fois. Les appels suivants la présentent.

```sh
curl -X POST https://api.subagent.fr/v1/verify \
  -H "Authorization: Bearer $SUBAGENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"otp_code": "482913"}'
```

## Les refus

```json
{
  "error": {
    "code": "space_unverified",
    "message": "…",
    "hint": "…"
  }
}
```

- **`code`** : stable. C'est lui qu'un programme teste.
- **`message`** : une phrase en français.
- **`hint`** : la piste, quand il y en a une. Elle dit quoi faire.

| Statut | Sens |
|---|---|
| 400 | Un argument manque, est inconnu ou mal formé : `invalid_argument`. |
| 401 | La clé est absente, inconnue ou révoquée : `unauthorized`. |
| 402 | L'espace n'a pas de forfait en cours : `payment_required`. |
| 403 | La clé ne porte pas la permission (`forbidden`), l'espace n'est pas vérifié (`space_unverified`), ou l'appel vient d'une page web (`origin_refused`). |
| 404 | L'objet ou l'opération n'existe pas : `not_found`, `unknown_operation`. |
| 409 | L'état ne permet pas l'action : `duplicate_recipient`, `not_draft`, `inbox_suspended`… |
| 413 | Le corps dépasse 1 Mio : `payload_too_large`. |
| 422 | La demande est comprise mais refusée : `recipient_suppressed`, `own_domain_required`, `unresolved_placeholder`… |
| 429 | Une limite est atteinte : `rate_limited`, `key_daily_cap`, `queue_full`… |
| 500, 502, 503 | Le service, ou un service dont il dépend, n'a pas répondu : `internal`, `provisioning_failed`, `dns_unavailable`, `billing_unavailable`… |

Chaque code, avec ce qu'il faut faire : [Erreurs](https://subagent.fr/docs/erreurs.md).

Un message retenu n'est pas un refus. Quota du jour atteint, envoi hors des heures ouvrées, volume du mois atteint : la réponse est un succès (200), et le message est en file (`queued`). `estimated_send_at` donne son départ au plus tôt, d'après le créneau et le quota du jour.

## Parcourir une liste

Les listes rendent `items` et `next_cursor`.

- `limit` va de 1 à 100. 20 par défaut.
- Tant que `next_cursor` n'est pas `null`, repassez-le tel quel dans `cursor` pour la page suivante.
- Un curseur ne se fabrique pas : un curseur illisible est refusé avec le code `invalid_argument`.

```sh
curl -X POST https://api.subagent.fr/v1/list_threads \
  -H "Authorization: Bearer $SUBAGENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"unanswered": true, "limit": 50}'
```

`get_thread` suit la même règle pour les messages d'un fil : 50 par appel, puis `next_cursor`. `list_domains` rend tous les domaines de l'espace en une fois.

## Réessayer sans doublon

`send_email` et `reply_to_thread` acceptent une `idempotency_key`, de 1 à 255 caractères. En HTTP, l'en-tête `Idempotency-Key` vaut le paramètre.

- **Même clé, même contenu** : le serveur rend le message déjà créé, avec `replayed` = `true`.
- **Même clé, contenu différent** : refus `idempotency_conflict`. Rien n'est envoyé.

Après une erreur 500 ou une coupure réseau, réessayez avec la même `idempotency_key`.

## Les formes

- **Identifiants** : `inb_…` (boîte), `thr_…` (fil), `msg_…` (message), `dom_…` (domaine), suivis de 32 caractères hexadécimaux. Passez-les tels que les outils les rendent.
- **Dates** : ISO 8601 avec fuseau, à l'heure de Paris : `2026-10-13T09:00:00+02:00`. En entrée, une heure de Paris sans fuseau est acceptée : `2026-10-13T09:00`.
- **Arguments** : un argument inconnu est refusé, avec la liste des arguments acceptés dans la piste.

## Débit

60 requêtes par minute sans clé, 600 avec une clé, par adresse du client. Au-delà : statut 429, code `rate_limited`, et l'en-tête `Retry-After` donne le nombre de secondes à attendre. Voir [Limites et quotas](https://subagent.fr/docs/limites.md#debit).

## Depuis un navigateur

L'API ne s'appelle pas depuis la page web d'un autre site : une requête qui porte un en-tête `Origin` étranger est refusée avec le code `origin_refused`. Appelez-la depuis votre agent ou votre serveur.

## La référence du serveur

- `https://api.subagent.fr/openapi.json` : chaque opération, ses schémas d'entrée et de sortie, ses permissions (`x-subagent-permissions`).
- `https://api.subagent.fr/llms.txt` : les règles et la liste des outils, en texte.
- Les pages du service qui ne sont pas des outils : la connexion d'un assistant (`/oauth/…`, voir [Connecteur](https://subagent.fr/docs/connecteur.md)), la page de paiement et les factures (voir [Prix et paiement](https://subagent.fr/docs/prix.md)), la page de désinscription.
- [Référence des outils](https://subagent.fr/docs/reference/index.md) : une page par outil, produite depuis ce registre.
