Référence de l’API REST
L’API REST de Page Lemon se trouve à https://api.pagelemon.com/v1. Les agents de code avec un shell l’utilisent pour publier un dossier en une seule commande ; les agents IA devraient commencer par le guide de publication pour les IA (Markdown).
Dernière mise à jour le · Voir en Markdown
Sur cette page
Démarrage rapide
Publiez un dossier sans compte (il reste en ligne 72 heures, sauf si vous le conservez) :
tar -czf - -C dist . | curl -sS --data-binary @- https://api.pagelemon.com/v1/deployAvec un jeton d’API, le site arrive directement dans votre compte :
tar -czf - -C dist . | curl -sS -H "Authorization: Bearer $PAGELEMON_TOKEN" --data-binary @- https://api.pagelemon.com/v1/deployHôtes
| Hôte | Sert |
|---|---|
https://pagelemon.com | Ce site, /agents, /llms.txt, /docs/* |
https://api.pagelemon.com | API REST sous /v1 |
https://mcp.pagelemon.com | Serveur MCP distant (streamable HTTP) à / (alias /mcp) |
https://app.pagelemon.com | Votre compte : sites, personnes, jetons, facturation |
https://<name>.pagelemon.dev | Vos sites |
Authentification
Envoyez les identifiants sous la forme Authorization: Bearer <token>.
| Identifiant | Format | Provenance | Ce qu’il permet |
|---|---|---|---|
| Jeton de site | st_… | Renvoyé une seule fois par un déploiement anonyme | Mettre à jour, relire, revenir en arrière et consulter ce site uniquement, jusqu’à sa récupération. Après la récupération, il ne fait que signaler celle-ci (GET /v1/sites/:name) |
| Lien de récupération | https://app.pagelemon.com/claim/ct_… | Renvoyé une seule fois par un déploiement anonyme | Une personne connectée récupère le site |
| Jeton API | pl_… | app.pagelemon.com/account/tokens (Paramètres du compte → Jetons API ; voir Jetons API) | Tout ce que vous pouvez faire dans votre compte, via REST et MCP |
| Jeton d’accès OAuth | pla_… | Délivré à une application MCP (Claude.ai, ChatGPT, Claude Code…) après que vous vous êtes connecté et l’avez autorisée | Identique à un jeton API, mais MCP uniquement (REST répond 401). Valable 1 heure et se renouvelle automatiquement |
Nous ne stockons que des hachages des jetons : un jeton perdu ne peut pas être réaffiché. Créez-en un nouveau.
Erreurs
{ "error": { "code": "conflict", "message": "…" }, "agent_message": "…" }agent_message est présent quand l'IA doit dire quelque chose à l'utilisateur. Transmettez-le dans la langue de l'utilisateur, en gardant exacts chaque lien, code, nombre, date et domaine ; les heures sont en UTC, et les champs *_at les donnent au format ISO.
| Code | Statut | Signification |
|---|---|---|
bad_request | 400 | Archive, corps ou paramètre incorrect |
unauthorized | 401 | Jeton manquant ou invalide |
forbidden | 403 | Le jeton ou le rôle ne permet pas cette action |
not_found | 404 | Site ou fichier introuvable |
conflict | 409 | X-Base-Revision / base_revision obsolète |
gone | 410 | Le site a expiré |
too_large | 413 | Limite de taille dépassée |
blocked_secret | 422 | La protection contre les fuites a trouvé une clé secrète |
limit | 429 | Limite du forfait ou de débit |
Déploiement
POST /v1/deploy : une archive
Le corps de la requête est l’archive : .tar.gz, .tgz, .tar ou .zip. Le serveur détecte le format à partir des octets, donc Content-Type est facultatif.
tar -czf - -C <dir> . | curl -sS --data-binary @- https://api.pagelemon.com/v1/deploy| Requête | Résultat |
|---|---|
Pas de ?site, pas de jeton | Création anonyme. Un nom aléatoire comme brave-otter-4821, qui expire après 72 heures s’il n’est pas récupéré |
Pas de ?site, jeton API | Création dans votre compte. Pas d’expiration |
?site=<name> + X-Base-Revision: <revision id> + jeton de site ou jeton API | Mise à jour. Si la révision en ligne n’est pas X-Base-Revision, vous recevez 409 conflict et rien n’est publié |
Chaque déploiement remplace tout le site : les fichiers que vous omettez sont retirés du site en ligne. Si tous les fichiers se trouvent dans un même dossier de premier niveau (dist/index.html, …), ce dossier est retiré.
Réponse 201 :
{
"site": { "name": "brave-otter-4821", "url": "https://brave-otter-4821.pagelemon.dev", "claimed": false, "expires_at": "2026-10-14T14:40:00Z" },
"revision": { "id": "rev_…", "number": 1, "files": 12, "bytes": 48213 },
"site_token": "st_…",
"claim_url": "https://app.pagelemon.com/claim/ct_…",
"skipped": [".env", "node_modules/…"],
"agent_message": "Your site is live at …"
}site_token et claim_url n’apparaissent que lors d’une création anonyme.
POST /v1/deploy avec JSON : fichiers en ligne
Pour les clients MCP et les petits sites : envoyez Content-Type: application/json au même endpoint.
{ "site": "brave-otter-4821", "base_revision": "rev_…", "files": [ { "path": "index.html", "content": "<h1>Hi</h1>", "encoding": "utf8" } ] }encoding vaut utf8 ou base64. Omettez site et base_revision pour créer un nouveau site. La réponse est la même que ci-dessus.
Patch : ajoutez "patch": true pour n’envoyer que les files modifiés plus "deleted": ["old.html"] par-dessus base_revision ; tout le reste est conservé. Mêmes limites et vérifications ; un base_revision obsolète donne un 409 conflict.
Règles d’envoi
| Fichiers | Par fichier | Par site | Expiration | |
|---|---|---|---|---|
| Sans compte | 100 | 1 MB | 1 MB | 72 heures sauf récupération |
| Gratuit | 500 | 5 MB | 5 MB | aucune |
| Prompter | 1,000 | 50 MB | 5 Go (tout son stockage) | aucune |
| Builder | 2,000 | 50 MB | 25 Go (tout son stockage) | aucune |
| Team | 3,000 | 50 MB | 50 Go (tout son stockage) | aucune |
| Company | 5,000 | 50 MB | 150 Go (tout son stockage) | aucune |
« Par site » désigne l’ensemble du site en ligne après un déploiement ; un patch compte le site complet obtenu. Avec les forfaits payants, un site peut utiliser tout l’espace de stockage de le forfait, mais une requête ne peut transporter que 90 Mo au maximum (40 Mo via MCP) : envoyez un site plus gros en premier déploiement, puis le reste en déploiements patch. En cas de dépassement : 413 too_large avec un agent_message à afficher.
- Rejetés : liens symboliques, liens physiques, périphériques, chemins absolus,
.., et chemins en double ne différant que par la casse. - Ignorés et listés dans
skipped:.git/,node_modules/,.env*,*.map,*.pem,*.key; fichiers cachés sauf.well-known/;.DS_Store,Thumbs.db. - Protection contre les fuites : les fichiers texte sont analysés pour détecter les types connus de clés secrètes et de clés privées. Une détection renvoie
422 blocked_secretavec{file, line, kind}. La clé elle-même n’est jamais renvoyée. - Obligatoire :
index.htmlà la racine. - Anonyme uniquement : les exécutables et les installateurs sont bloqués, et chaque réseau dispose d’un petit nombre de sites et de déploiements anonymes. Récupérez le site ou connectez-vous pour en avoir plus.
Sites
| Méthode | Chemin | Authentification | Remarques |
|---|---|---|---|
| GET | /v1/sites | Jeton API | Sites dont vous êtes membre |
| GET | /v1/sites/:name | jeton de site, membre | {name, url, claimed, expires_at, plan, role, live_revision: {id, number, created_at, created_by}, badge}. Avec le jeton de site, interrogez-le après que l’utilisateur a ouvert le lien de récupération : {claimed: false, …} ou {claimed: true, account_token?} ; c’est le seul appel qu’un jeton de site peut encore faire une fois son site récupéré |
| GET | /v1/sites/:name/files | jeton de site, membre | {revision, files: [{path, size, sha256}]} pour la version en ligne |
| GET | /v1/sites/:name/files/<path> | jeton de site, membre | Contenu brut du fichier (la relecture), avec un en-tête X-Revision |
| GET | /v1/sites/:name/revisions | jeton de site, membre | Les plus récentes d’abord. Anonyme : version actuelle uniquement. Gratuit : 7 jours. Prompter : 90 jours. Builder et Team : 1 an. Company : 2 ans |
| POST | /v1/sites/:name/rollback | jeton de site, éditeur ou propriétaire | {revision} remet cette version en ligne, sous un nouveau numéro de version |
| POST | /v1/sites/:name/rename | éditeur ou propriétaire (compte uniquement) | {name} : 4 à 63 caractères parmi a-z, 0-9 et -. Ne peut pas ressembler à un nom aléatoire (word-word-1234), être réservé ou avoir déjà été utilisé |
| DELETE | /v1/sites/:name | propriétaire | Définitif. Avec un jeton d'API, il renvoie 202 avec approve_url : une page où la personne saisit l'adresse du site et clique sur Supprimer définitivement. GET /v1/approvals/<token> indique ensuite si le site a été supprimé |
| GET | /v1/sites/:name/members | membre | {members: [{email, role}], invites: [{email, role}]} |
| POST | /v1/sites/:name/members | propriétaire | {email, role: "editor" or "viewer"} envoie un e-mail d’invitation |
| DELETE | /v1/sites/:name/members/:email | propriétaire | En deux étapes : le premier appel renvoie {confirm_token} ; répétez avec ?confirm=<token> dans les 5 minutes |
Rôles : les lecteurs peuvent consulter le site et son historique. Les éditeurs peuvent aussi déployer et revenir en arrière. Les propriétaires peuvent aussi inviter, renommer et supprimer.
Compte
| Méthode | Chemin | Authentification | Remarques |
|---|---|---|---|
| GET | /v1/me | Jeton API | {email, plan, sites_used, sites_limit} |
La récupération des sites, l’acceptation des invitations, les jetons et la facturation se gèrent sur app.pagelemon.com.
Diffusion sur pagelemon.dev
/sertindex.html./aboutsertabout.htmlouabout/index.html.- Les fichiers manquants reçoivent la page
404.htmldu site si elle existe, sinon la nôtre. - Repli pour application monopage : si le site n’a pas de
404.htmlet que le chemin n’a pas d’extension de fichier,index.htmlest servi. - En-têtes :
X-Content-Type-Options: nosniff,Referrer-Policy: strict-origin-when-cross-origin,Cache-Control: public, max-age=60pour le HTML etmax-age=300pour les autres fichiers. Les types de contenu proviennent d’une liste autorisée ; les types inconnus sont servis enapplication/octet-stream. - Les sites anonymes et Gratuit affichent un petit badge "Live on Page Lemon" avant
</body>. C’est du HTML et du CSS simples, sans script, avec un lien pour signaler le site. - Les sites expirés ou supprimés renvoient
410. Les sites retirés pour abus renvoient451.
.pagelemon.json
Après le déploiement, les agents écrivent ce fichier dans le dossier du projet et l’ajoutent à .gitignore, pour que la session suivante puisse mettre à jour le même site :
{ "site": "brave-otter-4821", "url": "https://brave-otter-4821.pagelemon.dev", "revision": "rev_…", "site_token": "st_…" }