ZestEchodocumentationRetour
Sommaire

API HTTP

API publique versionnée pour automatiser ZestEcho (scripts, CI, intégrations) avec les mêmes permissions, quotas et validations que l'interface.

Authentification

Crée un jeton dans Mon compte → Jetons d'API (lecture seule par défaut, révocable à tout moment). Le secret n'est affiché qu'une fois.

Requête authentifiée

curl https://zestecho.fr/api/v1/me \
  -H "Authorization: Bearer zc_pat_…"

{ "user": { "id": "…", "displayName": "…" },
  "token": { "id": "…", "scopes": ["read", "write"] },
  "limits": { … } }

L'API n'accepte jamais le cookie de session : uniquement l'en-tête Authorization: Bearer. Un jeton révoqué ou expiré répond immédiatement 401.

Portées cumulatives

  • read — lire le contenu et les métadonnées (arbre, sessions, onglets, historique, membres, demandes).
  • write — modifier contenu, historique, structure et partages.
  • files — qualificatif indispensable aux fichiers : télécharger exige read + files, envoyer, renommer ou supprimer exige write + files. files seul n'autorise rien.

Le débit est limité par jeton (600/min en lecture, 120/min en écriture, 60/min pour les fichiers) et par compte. Une réponse 429 indique de ralentir.

Erreurs stables

Toutes les erreurs partagent le même contrat, avec un code stable et un message lisible :

Réponse d'erreur

HTTP/1.1 403 Forbidden

{ "error": { "code": "forbidden",
             "message": "Portées requises : write + files." } }
  • unauthorized, forbidden, not_found, invalid_input, conflict, quota_exceeded, rate_limited, internal.
  • precondition_required (428) et precondition_failed (412) pour les écritures conditionnelles d'onglets.

Endpoints

Compte et recherche

GET    /api/v1/me
GET    /api/v1/tree
GET    /api/v1/slug-available?slug=…
GET    /api/v1/search?q=…&limit=…&types=…
GET    /api/v1/context?session=…&tabId=…&maxChars=…
GET    /api/v1/account/preferences
PUT    /api/v1/account/preferences
DELETE /api/v1/account/preferences
GET    /api/v1/account/export

Organisation et sessions

POST   /api/v1/projects
PATCH  /api/v1/projects/{id}
DELETE /api/v1/projects/{id}
POST   /api/v1/projects/{id}/share
GET    /api/v1/projects/{id}/members

POST   /api/v1/folders
PATCH  /api/v1/folders/{id}
DELETE /api/v1/folders/{id}

POST   /api/v1/sessions
PATCH  /api/v1/sessions/{slug}
DELETE /api/v1/sessions/{slug}
POST   /api/v1/sessions/{slug}/share
GET    /api/v1/sessions/{slug}/members
PATCH  /api/v1/sessions/{slug}/members/{memberId}
DELETE /api/v1/sessions/{slug}/members/{memberId}

Onglets Live et historique

GET    /api/v1/sessions/{slug}/tabs
POST   /api/v1/sessions/{slug}/tabs
GET    /api/v1/sessions/{slug}/tabs/{tabId}
PATCH  /api/v1/sessions/{slug}/tabs/{tabId}       # renommer
PUT    /api/v1/sessions/{slug}/tabs/{tabId}       # remplacer (If-Match requis)
DELETE /api/v1/sessions/{slug}/tabs/{tabId}
POST   /api/v1/sessions/{slug}/tabs/{tabId}/append

GET    /api/v1/sessions/{slug}/history?tabId=…
POST   /api/v1/sessions/{slug}/history
GET    /api/v1/sessions/{slug}/history/{entryId}?tabId=…
DELETE /api/v1/sessions/{slug}/history/{entryId}?tabId=…

Fichiers et demandes d'accès

GET    /api/v1/sessions/{slug}/files
POST   /api/v1/sessions/{slug}/files          # multipart, champ « file »
GET    /api/v1/sessions/{slug}/export?kind=files|clipboards
GET    /api/v1/files/{id}
PATCH  /api/v1/files/{id}
DELETE /api/v1/files/{id}

GET    /api/v1/requests
POST   /api/v1/requests/{id}/decide

# Public, sans jeton : un visiteur demande l'accès à une session
POST   /api/v1/sessions/{slug}/requests

Idempotence

Sur les POST JSON, l'en-tête optionnel Idempotency-Key (8 à 128 caractères[A-Za-z0-9._-]) mémorise la réponse pendant 24 h : un rejeu avec le même corps renvoie la réponse d'origine avec Idempotency-Replayed: true, sans recréer de ressource. Le même jeton qui réutilise la clé avec un corps ou un chemin différents reçoit 409. Les envois multipart en sont exclus.

Créer une fois, rejouer sans doublon

curl -X POST https://zestecho.fr/api/v1/projects \
  -H "Authorization: Bearer zc_pat_…" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: creation-projet-ci-2026-09-18" \
  -d '{"name": "Intégration CI"}'

Écrire dans un onglet sans écraser

GET …/tabs/{tabId} renvoie un ETag fort (en-tête et champ etag). PUT (remplacement) l'exige : sans lui, 428 ; s'il est périmé, 412. append l'accepte en option. La comparaison est faite sous le verrou du document, jamais sur un état lu plus tôt.

Remplacer le contenu d'un onglet

curl -X PUT https://zestecho.fr/api/v1/sessions/tp1/tabs/onglet-1 \
  -H "Authorization: Bearer zc_pat_…" \
  -H "Content-Type: application/json" \
  -H 'If-Match: "sha256-…"' \
  -d '{"content": "Nouveau contenu"}'

{ "tabId": "onglet-1", "length": 14, "etag": "\"sha256-…\"" }

Bon à savoir

  • Chaque écriture applique les mêmes règles que l'interface : permissions de session/projet, quotas, historique immuable et diffusion temps réel aux navigateurs connectés.
  • Les téléchargements exigent l'en-tête Bearer : aucune URL publique durable n'est créée.
  • L'API ne gère pas encore de clé d'idempotence : un POST de création rejoué crée un doublon.
  • Pas de CORS par défaut : l'API vise les appels serveur-à-serveur et les agents.
  • Les flux invités restent sur l'interface : un visiteur demande l'accès depuis le lien public ; l'API liste et décide ces demandes, et l'endpoint public POST /api/v1/sessions/{slug}/requests permet aussi de les créer sans jeton (limité par IP et par session, token remis une seule fois).
  • La recherche est insensible aux accents et à la casse (classes de lettres GLOB) : resume retrouve Résumé, et inversement.
  • CORS optionnel : renseigne API_CORS_ORIGINS (origines exactes, séparées par des virgules) pour autoriser un client navigateur sur /api/v1 et /mcp. Vide par défaut.
  • L'administration (stats, quotas, observatoire) reste sur l'authentification Gitea du navigateur.