# Authentification et scopes

> Comment un jeton d’API s’authentifie, ce que ses scopes permettent, et comment l’offre et le rôle s’y ajoutent.

## Le jeton

Chaque requête porte le jeton dans l’en-tête `Authorization`, sous la forme `Bearer` suivie du jeton :

```bash
curl "https://api.nessflow.com/v1/me" \
  -H "Authorization: Bearer $NESSFLOW_TOKEN"
```

Un jeton appartient à un membre et agit pour **une** équipe. Il expire (90 jours par défaut, 365 au plus), et il cesse de fonctionner dès que son porteur quitte l’équipe. Aucun cookie, aucune session : l’API se parle de serveur à serveur.

Un jeton absent, invalide ou expiré répond `401` avec le code `unauthenticated` :

```bash expect=401
curl "https://api.nessflow.com/v1/me" \
  -H "Authorization: Bearer jeton-invalide"
```

## Les scopes

Un scope combine un **domaine** et un **verbe** : `projects:read`, `crawls:write`, `positions:write`, `webhooks:read`… Un scope `write` n’inclut pas le `read` du même domaine. Donnez à chaque intégration les seuls scopes dont elle a besoin.

Un appel sans le scope requis répond `403` avec le code `token.missing_scope` et la liste `required_scopes`.

## Trois autorisations, toujours

Un appel doit être permis par les trois à la fois :

1. **l’offre** de l’équipe ouvre le verbe (`api.not_in_plan`, `api.write_not_in_plan`) ;
2. **le rôle** du membre permet le geste (gérer les webhooks est réservé aux owners et admins) ;
3. **le jeton** porte le scope.

Les refus de palier nomment l’offre qui les lèverait (`upgrade_to`) : réessayer n’y changera rien.

## Langue

Les titres des erreurs et les textes traduits suivent l’en-tête `Accept-Language` (`fr` ou `en`, `fr` par défaut). Les codes, eux, ne se traduisent jamais.
