---
title: Reference API
description: Liste des endpoints de l'API libreDecision
---

# Reference API

Tous les endpoints sont prefixes par `/api/v1`. L'API est auto-documentee via OpenAPI/Swagger a l'adresse `/docs` en mode debug.

## Authentification (`/api/v1/auth`)

| Methode | Endpoint      | Description                                           | Auth |
| ------- | ------------- | ----------------------------------------------------- | ---- |
| POST    | `/challenge`  | Generer un challenge Ed25519 pour une adresse Duniter | Non  |
| POST    | `/verify`     | Verifier la signature du challenge et obtenir un token | Non  |
| GET     | `/me`         | Retourner l'identite authentifiee courante            | Oui  |
| POST    | `/logout`     | Invalider la session courante                         | Oui  |

## Documents (`/api/v1/documents`)

| Methode | Endpoint                               | Description                              | Auth |
| ------- | -------------------------------------- | ---------------------------------------- | ---- |
| GET     | `/`                                    | Lister les documents (filtres: doc_type, status) | Non  |
| POST    | `/`                                    | Creer un nouveau document                | Oui  |
| GET     | `/{slug}`                              | Obtenir un document par son slug         | Non  |
| PUT     | `/{slug}`                              | Mettre a jour un document                | Oui  |
| POST    | `/{slug}/items`                        | Ajouter un item au document              | Oui  |
| GET     | `/{slug}/items`                        | Lister les items d'un document           | Non  |
| GET     | `/{slug}/items/{item_id}`              | Obtenir un item avec son historique      | Non  |
| PUT     | `/{slug}/items/{item_id}`              | Mettre a jour un item (titre, texte, position, type) | Oui  |
| DELETE  | `/{slug}/items/{item_id}`              | Supprimer un item du document            | Oui  |
| POST    | `/{slug}/items/{item_id}/versions`     | Proposer une nouvelle version d'un item  | Oui  |
| GET     | `/{slug}/items/{item_id}/versions`     | Lister les versions d'un item            | Non  |
| PUT     | `/{slug}/items/{item_id}/versions/{version_id}/accept` | Accepter une version proposee (applique le texte a l'item) | Oui |
| PUT     | `/{slug}/items/{item_id}/versions/{version_id}/reject` | Rejeter une version proposee             | Oui  |
| PUT     | `/{slug}/items/reorder`                | Reordonner les items d'un document       | Oui  |
| POST    | `/{slug}/archive`                      | Archiver le document dans le sanctuaire (hash SHA-256 + IPFS + on-chain) | Oui |

## Decisions (`/api/v1/decisions`)

| Methode | Endpoint         | Description                                      | Auth |
| ------- | ---------------- | ------------------------------------------------ | ---- |
| GET     | `/`              | Lister les decisions (filtres: decision_type, status) | Non  |
| POST    | `/`              | Creer une nouvelle decision                      | Oui  |
| GET     | `/{id}`          | Obtenir une decision avec ses etapes             | Non  |
| PUT     | `/{id}`          | Mettre a jour une decision                       | Oui  |
| DELETE  | `/{id}`          | Supprimer une decision (brouillon uniquement)    | Oui  |
| POST    | `/{id}/steps`    | Ajouter une etape a une decision                 | Oui  |
| POST    | `/{id}/advance`  | Avancer la decision a l'etape suivante           | Oui  |
| POST    | `/{id}/steps/{step_id}/create-vote-session` | Creer une session de vote pour une etape | Oui  |

## Votes (`/api/v1/votes`)

| Methode | Endpoint                        | Description                                  | Auth |
| ------- | ------------------------------- | -------------------------------------------- | ---- |
| POST    | `/sessions`                     | Creer une session de vote                    | Oui  |
| GET     | `/sessions`                     | Lister les sessions de vote (filtres: status, protocol_id, decision_id) | Non  |
| GET     | `/sessions/{id}`                | Obtenir une session de vote                  | Non  |
| POST    | `/sessions/{id}/vote`           | Soumettre un vote (signe)                    | Oui  |
| GET     | `/sessions/{id}/votes`          | Lister les votes d'une session               | Non  |
| GET     | `/sessions/{id}/result`         | Calculer et retourner le resultat courant    | Non  |
| POST    | `/sessions/{id}/close`          | Cloturer la session et calculer le resultat final | Oui  |
| GET     | `/sessions/{id}/threshold`      | Obtenir le detail du calcul de seuil (formule, parametres, valeurs intermediaires) | Non  |
| POST    | `/sessions/{id}/tally`          | Forcer un recomptage des votes et recalcul du seuil | Oui  |

## Mandats (`/api/v1/mandates`)

| Methode | Endpoint          | Description                                    | Auth |
| ------- | ----------------- | ---------------------------------------------- | ---- |
| GET     | `/`               | Lister les mandats (filtres: mandate_type, status) | Non  |
| POST    | `/`               | Creer un nouveau mandat                        | Oui  |
| GET     | `/{id}`           | Obtenir un mandat avec ses etapes              | Non  |
| PUT     | `/{id}`           | Mettre a jour un mandat                        | Oui  |
| DELETE  | `/{id}`           | Supprimer un mandat (brouillon uniquement)     | Oui  |
| POST    | `/{id}/steps`     | Ajouter une etape a un mandat                  | Oui  |
| GET     | `/{id}/steps`     | Lister les etapes d'un mandat                  | Non  |
| POST    | `/{id}/advance`   | Avancer le mandat a l'etape suivante           | Oui  |
| POST    | `/{id}/assign`    | Assigner un mandataire au mandat               | Oui  |
| POST    | `/{id}/revoke`    | Revoquer un mandat actif                       | Oui  |
| POST    | `/{id}/steps/{step_id}/create-vote-session` | Creer une session de vote pour une etape | Oui  |

## Protocoles (`/api/v1/protocols`)

| Methode | Endpoint            | Description                                        | Auth |
| ------- | ------------------- | -------------------------------------------------- | ---- |
| GET     | `/`                 | Lister les protocoles de vote                      | Non  |
| POST    | `/`                 | Creer un protocole de vote                         | Oui  |
| GET     | `/{id}`             | Obtenir un protocole avec sa configuration formule | Non  |
| PUT     | `/{id}`             | Mettre a jour un protocole (meta-gouvernance)      | Oui  |
| GET     | `/formulas`         | Lister les configurations de formules              | Non  |
| POST    | `/formulas`         | Creer une configuration de formule                 | Oui  |
| GET     | `/formulas/{id}`    | Obtenir une configuration de formule par son ID    | Non  |
| PUT     | `/formulas/{id}`    | Mettre a jour une configuration de formule (meta-gouvernance) | Oui  |
| POST    | `/simulate`         | Simuler le calcul d'une formule avec des parametres arbitraires | Non  |

## Sanctuaire (`/api/v1/sanctuary`)

| Methode | Endpoint                          | Description                                                | Auth |
| ------- | --------------------------------- | ---------------------------------------------------------- | ---- |
| GET     | `/`                               | Lister les entrees du sanctuaire (filtre: entry_type)      | Non  |
| GET     | `/{id}`                           | Obtenir une entree du sanctuaire                           | Non  |
| POST    | `/`                               | Creer une entree (hash SHA-256, CID IPFS, TX on-chain)    | Oui  |
| GET     | `/{id}/verify`                    | Verifier l'integrite d'une entree (recalcul SHA-256, verification IPFS et on-chain) | Non |
| GET     | `/by-reference/{reference_id}`    | Obtenir les entrees liees a une entite source par son UUID | Non  |

## WebSocket (`/api/v1/ws`)

| Endpoint  | Description                                              |
| --------- | -------------------------------------------------------- |
| `/ws`     | Connexion WebSocket pour notifications temps reel (votes, decisions) |

## Sante

| Methode | Endpoint       | Description                |
| ------- | -------------- | -------------------------- |
| GET     | `/api/health`  | Verification de sante (hors versionning) |

## Details des endpoints Sprint 2

### `PUT /api/v1/documents/{slug}/items/{item_id}` -- Mettre a jour un item

Met a jour les champs d'un item existant (titre, texte courant, position, type). Seuls les champs fournis sont mis a jour (mise a jour partielle).

**Corps de la requete** (tous les champs sont optionnels) :

```json
{
  "title": "Nouveau titre",
  "current_text": "Texte mis a jour...",
  "position": "2.1",
  "item_type": "rule"
}
```

**Reponse** : `200 OK` avec l'item mis a jour (`DocumentItemOut`).

---

### `DELETE /api/v1/documents/{slug}/items/{item_id}` -- Supprimer un item

Supprime un item d'un document. La suppression est en cascade : toutes les versions associees sont egalement supprimees.

**Reponse** : `204 No Content`.

---

### `GET /api/v1/documents/{slug}/items/{item_id}/versions` -- Lister les versions d'un item

Retourne l'historique complet des versions proposees pour un item, ordonne par date de creation decroissante.

**Parametres de requete** : `skip`, `limit` (pagination standard).

**Reponse** : `200 OK` avec une liste de `ItemVersionOut`.

---

### `PUT /api/v1/documents/{slug}/items/{item_id}/versions/{version_id}/accept` -- Accepter une version

Accepte une version proposee. Le texte propose remplace le texte courant de l'item. Toutes les autres versions en statut `proposed` ou `voting` pour cet item sont automatiquement rejetees.

**Reponse** : `200 OK` avec la version mise a jour (`ItemVersionOut`, statut `accepted`).

---

### `PUT /api/v1/documents/{slug}/items/{item_id}/versions/{version_id}/reject` -- Rejeter une version

Rejette une version proposee. Le texte courant de l'item reste inchange.

**Reponse** : `200 OK` avec la version mise a jour (`ItemVersionOut`, statut `rejected`).

---

### `PUT /api/v1/documents/{slug}/items/reorder` -- Reordonner les items

Modifie l'ordre d'affichage des items dans un document en mettant a jour le champ `sort_order` de chaque item.

**Corps de la requete** :

```json
{
  "items": [
    { "item_id": "uuid-1", "sort_order": 0 },
    { "item_id": "uuid-2", "sort_order": 1 },
    { "item_id": "uuid-3", "sort_order": 2 }
  ]
}
```

**Reponse** : `200 OK` avec la liste des items reordonnes.

---

### `POST /api/v1/documents/{slug}/archive` -- Archiver un document

Archive le document complet dans le sanctuaire. Le processus :

1. Le contenu integral du document (metadonnees + items) est serialise.
2. Un hash SHA-256 est calcule sur le contenu.
3. Le contenu est envoye sur IPFS (CID retourne).
4. Le hash est ancre on-chain via `system.remark` sur Duniter V2.
5. Une entree `sanctuary_entries` est creee avec les references.
6. Le statut du document passe a `archived` et les champs `ipfs_cid` et `chain_anchor` sont mis a jour.

**Reponse** : `200 OK` avec le document mis a jour incluant `ipfs_cid` et `chain_anchor`.

---

### `GET /api/v1/sanctuary/{id}/verify` -- Verifier l'integrite d'une entree

Verifie l'integrite d'une entree du sanctuaire en effectuant trois controles :

1. **Hash SHA-256** : recalcul du hash a partir du contenu source et comparaison avec `content_hash`.
2. **IPFS** : verification que le CID IPFS pointe vers un contenu valide (si disponible).
3. **On-chain** : verification que le hash est present dans le `system.remark` du bloc reference (si disponible).

**Reponse** :

```json
{
  "entry_id": "uuid",
  "hash_valid": true,
  "ipfs_valid": true,
  "chain_valid": true,
  "verified_at": "2026-02-28T12:00:00Z",
  "details": "Tous les controles sont valides."
}
```

---

### `GET /api/v1/sanctuary/by-reference/{reference_id}` -- Entrees par reference

Retourne toutes les entrees du sanctuaire liees a une entite source (document, decision ou session de vote) identifiee par son UUID.

**Parametres de requete** : `skip`, `limit` (pagination standard).

**Reponse** : `200 OK` avec une liste de `SanctuaryEntryOut`.

## Details des endpoints Sprint 3

### `GET /api/v1/votes/sessions` -- Lister les sessions de vote

Retourne la liste des sessions de vote avec pagination et filtres optionnels.

**Parametres de requete** :

| Parametre     | Type   | Description                                    |
| ------------- | ------ | ---------------------------------------------- |
| `status`      | string | Filtrer par statut (`open`, `closed`, `draft`)  |
| `protocol_id` | uuid  | Filtrer par protocole de vote                   |
| `decision_id` | uuid  | Filtrer par decision associee                   |
| `skip`        | int    | Offset de pagination (defaut 0)                 |
| `limit`       | int    | Nombre max de resultats (defaut 50, max 200)    |

**Reponse** : `200 OK` avec une liste de `VoteSessionOut`.

---

### `POST /api/v1/votes/sessions/{id}/close` -- Cloturer une session

Cloture une session de vote ouverte et calcule le resultat final. Le calcul inclut la formule WoT, les criteres Smith et TechComm le cas echeant. La session passe au statut `closed` et le resultat est fige.

**Preconditions** :
- La session doit etre au statut `open`.
- L'utilisateur doit etre le createur de la session ou un membre du Comite Technique.

**Reponse** :

```json
{
  "session_id": "uuid",
  "status": "closed",
  "closed_at": "2026-02-28T12:00:00Z",
  "result": {
    "votes_for": 97,
    "votes_against": 23,
    "total_votes": 120,
    "wot_size": 7224,
    "threshold": 94,
    "adopted": true,
    "smith_threshold": 2,
    "smith_votes_for": 5,
    "smith_met": true,
    "techcomm_threshold": null,
    "techcomm_votes_for": null,
    "techcomm_met": null
  }
}
```

---

### `GET /api/v1/votes/sessions/{id}/threshold` -- Detail du calcul de seuil

Retourne le detail complet du calcul de seuil pour une session de vote, incluant les valeurs intermediaires de la formule. Utile pour la transparence et le debug.

**Reponse** :

```json
{
  "session_id": "uuid",
  "formula_config_id": "uuid",
  "mode_params": "D30M50B.1G.2",
  "parameters": {
    "constant_base": 0.0,
    "base_exponent": 0.1,
    "majority_pct": 50,
    "gradient_exponent": 0.2,
    "smith_exponent": null,
    "techcomm_exponent": null
  },
  "inputs": {
    "wot_size": 7224,
    "total_votes": 120,
    "smith_wot_size": 20,
    "techcomm_size": 5
  },
  "computation": {
    "base_term": 7.943e-08,
    "participation_ratio": 0.0166,
    "participation_ratio_powered": 0.4217,
    "inertia_factor": 0.7892,
    "effective_threshold": 94.70,
    "threshold_ceiled": 95,
    "threshold_final": 94
  },
  "criteria": {
    "smith_threshold": null,
    "techcomm_threshold": null
  }
}
```

---

### `POST /api/v1/votes/sessions/{id}/tally` -- Forcer un recomptage

Force le recalcul du decompte des votes et du seuil pour une session. Utile si des votes ont ete invalides manuellement ou si la taille WoT a ete corrigee.

**Preconditions** :
- L'utilisateur doit etre le createur de la session ou un membre du Comite Technique.

**Corps de la requete** (optionnel) :

```json
{
  "wot_size_override": 7250,
  "smith_wot_size_override": null,
  "techcomm_size_override": null
}
```

Si aucun corps n'est fourni, les tailles sont reprises du snapshot initial.

**Reponse** : `200 OK` avec le meme format que le resultat de cloture.

---

### `PUT /api/v1/protocols/{id}` -- Mettre a jour un protocole

Met a jour un protocole de vote existant. Les modifications de protocoles actifs (utilises par des sessions ouvertes) sont soumises a **meta-gouvernance** : une session de vote doit d'abord valider la modification.

**Corps de la requete** (champs optionnels) :

```json
{
  "name": "Nouveau nom du protocole",
  "description": "Description mise a jour",
  "vote_type": "nuanced",
  "duration_days": 60,
  "formula_config_id": "uuid-de-la-nouvelle-formule"
}
```

**Reponse** : `200 OK` avec le protocole mis a jour (`ProtocolOut`).

**Code 409** : Si le protocole est utilise par une session ouverte et qu'aucune validation meta-gouvernance n'est fournie.

---

### `GET /api/v1/protocols/formulas/{id}` -- Obtenir une formule

Retourne une configuration de formule par son identifiant, incluant tous les parametres et le `mode_params` encode.

**Reponse** : `200 OK` avec un `FormulaConfigOut`.

---

### `PUT /api/v1/protocols/formulas/{id}` -- Mettre a jour une formule

Met a jour une configuration de formule existante. Comme pour les protocoles, les formules actives sont protegees par la meta-gouvernance.

**Corps de la requete** (champs optionnels) :

```json
{
  "name": "Configuration amendee",
  "majority_pct": 66,
  "base_exponent": 0.05,
  "gradient_exponent": 0.3,
  "constant_base": 0.0,
  "smith_exponent": 0.1,
  "techcomm_exponent": 0.1,
  "ratio_multiplier": null,
  "is_ratio_mode": false
}
```

Le champ `mode_params` est recalcule automatiquement a partir des valeurs fournies.

**Reponse** : `200 OK` avec la formule mise a jour (`FormulaConfigOut`).

**Code 409** : Si la formule est liee a un protocole actif sans validation meta-gouvernance.

---

### `POST /api/v1/protocols/simulate` -- Simuler une formule

Simule le calcul de seuil d'une formule avec des parametres arbitraires, sans creer ni modifier aucune donnee. Endpoint ouvert (pas d'authentification requise) pour permettre l'experimentation.

**Corps de la requete** :

```json
{
  "wot_size": 7224,
  "total_votes": 120,
  "majority_pct": 50,
  "base_exponent": 0.1,
  "gradient_exponent": 0.2,
  "constant_base": 0.0,
  "smith_wot_size": 20,
  "smith_exponent": 0.1,
  "techcomm_size": 5,
  "techcomm_exponent": 0.1,
  "votes_for": 97
}
```

**Reponse** :

```json
{
  "threshold": 94,
  "inertia_factor": 0.7892,
  "participation_ratio": 0.0166,
  "base_term": 7.943e-08,
  "smith_threshold": 2,
  "techcomm_threshold": 2,
  "adopted": true,
  "details": {
    "wot_threshold_met": true,
    "smith_met": true,
    "techcomm_met": true
  }
}
```

## Details des endpoints Sprint 4

### `POST /api/v1/decisions/{id}/advance` -- Avancer une decision

Avance une decision a l'etape suivante de son workflow. Complete l'etape active courante et active la prochaine etape en attente. Si toutes les etapes sont terminees, le statut global de la decision avance au statut suivant dans le cycle de vie (`draft` -> `qualification` -> `review` -> `voting` -> `executed` -> `closed`).

**Comportement** :

- S'il y a une etape `active` : elle passe a `completed`, la prochaine etape `pending` est activee.
- S'il n'y a pas d'etape active : la premiere etape `pending` est activee. Si la decision est en `draft`, elle passe a `qualification`.
- Si toutes les etapes sont terminees : le statut global avance.

**Preconditions** :
- La decision ne doit pas etre au statut `closed`.
- L'utilisateur doit etre authentifie.

**Reponse** : `200 OK` avec un `DecisionAdvanceOut` :

```json
{
  "id": "uuid",
  "title": "Runtime upgrade v3.2.0",
  "description": "...",
  "context": "...",
  "decision_type": "runtime_upgrade",
  "status": "review",
  "voting_protocol_id": "uuid",
  "created_by_id": "uuid",
  "created_at": "2026-02-28T10:00:00Z",
  "updated_at": "2026-02-28T12:00:00Z",
  "steps": [
    {"id": "uuid", "step_order": 0, "step_type": "qualification", "status": "completed", "...": "..."},
    {"id": "uuid", "step_order": 1, "step_type": "review", "status": "active", "...": "..."},
    {"id": "uuid", "step_order": 2, "step_type": "vote", "status": "pending", "...": "..."}
  ],
  "message": "Etape 'Qualification' completee. Etape 'Examen' activee."
}
```

**Code 400** : Si la decision est deja cloturee ou qu'aucun avancement n'est possible.

---

### `DELETE /api/v1/decisions/{id}` -- Supprimer une decision

Supprime une decision. La suppression n'est autorisee que si la decision est au statut `draft`. Les etapes associees sont supprimees en cascade.

**Preconditions** :
- La decision doit etre au statut `draft`.
- L'utilisateur doit etre authentifie.

**Reponse** : `204 No Content`.

**Code 400** : Si la decision n'est pas au statut `draft`.

---

### `POST /api/v1/decisions/{id}/steps/{step_id}/create-vote-session` -- Creer une session de vote pour une etape de decision

Cree une session de vote liee a une etape specifique d'une decision. La session est configuree automatiquement a partir du protocole de vote de la decision.

**Comportement** :

1. Verifie que la decision et l'etape existent.
2. Verifie que l'etape est de type `vote` et au statut `active`.
3. Cree une session de vote avec le protocole de la decision.
4. Fait un snapshot des tailles WoT, Smith et TechComm.
5. Calcule la date de fin a partir de la duree de la formule.
6. Rattache la session a l'etape via `vote_session_id`.

**Reponse** : `201 Created` avec un `VoteSessionOut`.

**Code 400** : Si l'etape n'est pas de type `vote`, n'est pas `active`, ou si une session est deja liee.

---

### `POST /api/v1/mandates/{id}/advance` -- Avancer un mandat

Avance un mandat a l'etape suivante de son workflow. Fonctionne de maniere identique a l'avancement des decisions, avec le cycle de vie specifique aux mandats (`draft` -> `candidacy` -> `voting` -> `active` -> `reporting` -> `completed`).

**Comportement** :

- S'il y a une etape `active` : elle passe a `completed`, la prochaine etape `pending` est activee.
- S'il n'y a pas d'etape active : la premiere etape `pending` est activee. Si le mandat est en `draft`, il passe a `candidacy`.
- Si toutes les etapes sont terminees : le statut global avance.

**Preconditions** :
- Le mandat ne doit pas etre au statut `completed` ou `revoked`.
- L'utilisateur doit etre authentifie.

**Reponse** : `200 OK` avec un `MandateAdvanceOut` :

```json
{
  "id": "uuid",
  "title": "Membre Comite Technique 2026",
  "description": "...",
  "mandate_type": "techcomm",
  "status": "candidacy",
  "mandatee_id": null,
  "decision_id": null,
  "starts_at": null,
  "ends_at": null,
  "created_at": "2026-02-28T10:00:00Z",
  "updated_at": "2026-02-28T12:00:00Z",
  "steps": [
    {"id": "uuid", "step_order": 0, "step_type": "formulation", "status": "completed", "...": "..."},
    {"id": "uuid", "step_order": 1, "step_type": "candidacy", "status": "active", "...": "..."}
  ],
  "message": "Etape 'Formulation' completee. Etape 'Candidature' activee."
}
```

**Code 400** : Si le mandat est deja en statut terminal (`completed` ou `revoked`).

---

### `POST /api/v1/mandates/{id}/assign` -- Assigner un mandataire

Assigne un mandataire (membre elu) a un mandat apres un vote reussi.

**Corps de la requete** :

```json
{
  "mandatee_id": "uuid-de-l-identite-duniter"
}
```

**Comportement** :

1. Verifie que le mandat existe et qu'il est dans un statut permettant l'assignation.
2. Definit le `mandatee_id` du mandat.
3. Le mandat peut ensuite etre avance vers le statut `active`.

**Preconditions** :
- L'utilisateur doit etre authentifie.
- Le `mandatee_id` doit correspondre a une identite Duniter existante.

**Reponse** : `200 OK` avec un `MandateOut` mis a jour.

**Code 404** : Si le mandat ou l'identite Duniter n'existe pas.

---

### `POST /api/v1/mandates/{id}/revoke` -- Revoquer un mandat

Revoque un mandat actif de maniere anticipee. Le statut du mandat passe directement a `revoked`, mettant fin aux responsabilites du mandataire.

**Preconditions** :
- Le mandat doit etre au statut `active` ou `reporting`.
- L'utilisateur doit etre authentifie.

**Reponse** : `200 OK` avec un `MandateOut` mis a jour (statut `revoked`).

**Code 400** : Si le mandat n'est pas dans un statut permettant la revocation.

---

### `POST /api/v1/mandates/{id}/steps/{step_id}/create-vote-session` -- Creer une session de vote pour une etape de mandat

Cree une session de vote liee a une etape specifique d'un mandat. Fonctionne de maniere identique a la creation de session pour les decisions.

**Comportement** :

1. Verifie que le mandat et l'etape existent.
2. Verifie que l'etape est de type `vote` et au statut `active`.
3. Cree une session de vote avec le protocole associe.
4. Fait un snapshot des tailles WoT, Smith et TechComm.
5. Calcule la date de fin a partir de la duree de la formule.
6. Rattache la session a l'etape via `vote_session_id`.

**Reponse** : `201 Created` avec un `VoteSessionOut`.

**Code 400** : Si l'etape n'est pas de type `vote`, n'est pas `active`, ou si une session est deja liee.

---

## Pagination

Les endpoints de liste acceptent les parametres `skip` (offset, defaut 0) et `limit` (max 200, defaut 50).

## Authentification

Les endpoints marques "Oui" dans la colonne Auth requierent un header :

```
Authorization: Bearer <token>
```

Le token est obtenu via le flux challenge-response (`/auth/challenge` puis `/auth/verify`).
