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 exigeread + files, envoyer, renommer ou supprimer exigewrite + files.filesseul 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) etprecondition_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}/requestsIdempotence
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}/requestspermet 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) :resumeretrouveRésumé, et inversement. - CORS optionnel : renseigne
API_CORS_ORIGINS(origines exactes, séparées par des virgules) pour autoriser un client navigateur sur/api/v1et/mcp. Vide par défaut. - L'administration (stats, quotas, observatoire) reste sur l'authentification Gitea du navigateur.