Admin API Ghost : Créer/Modifier/Supprimer Posts, Membres, Tiers par Code

L'Admin API de Ghost permet d'automatiser la gestion de votre site. Vous pouvez créer, lire, modifier et supprimer des ressources comme les posts, les membres ou les tiers directement via du code. C'est utile pour les PME et startups qui veulent intégrer Ghost à d'autres outils, comme un CRM ou un système de facturation. Dans ce guide, nous couvrons les bases pour débutants, avec des exemples en cURL et JavaScript. Nous nous basons sur la documentation officielle de Ghost, mise à jour pour 2025.

Qu'est-ce que l'Admin API ?

L'Admin API est une interface RESTful en JSON pour gérer le contenu de Ghost de manière programmatique. Elle utilise des verbes HTTP standards (GET, POST, PUT, DELETE) et des URLs cohérentes. Toutes les requêtes passent par https://votre-site.com/ghost/api/admin/. Les réponses sont toujours des objets JSON avec un tableau de ressources et un objet meta pour la pagination ou les relations.

En 2025, l'API reste en version v6.0 pour la plupart des endpoints, avec des améliorations sur le support Lexical pour le contenu des posts. Elle est stable et adaptée aux workflows automatisés, comme importer des articles depuis un flux RSS ou synchroniser des abonnés avec Stripe.

Authentification : Obtenir une clé et générer un token

Pour utiliser l'API, vous avez besoin d'une clé d'API Admin. Allez dans l'admin Ghost > Paramètres > Intégrations > Ajouter une intégration personnalisée. Copiez la clé au format id:secret. Gardez-la secrète, car elle sert à générer des tokens JWT courts (5 minutes max).

Méthodes d'authentification

  • Token d'intégration : Pour les scripts serveur. Générez un JWT avec votre clé.
  • Token staff : Pour authentifier un utilisateur spécifique.
  • Session utilisateur : Pour les apps client, mais moins sécurisé.

Exemple de génération de token en Bash (pour cURL) :

KEY="votre_id:votre_secret"
IFS=':' read ID SECRET <<< "$KEY"
NOW=$(date +%s)
FIVE_MINS=$((NOW + 300))

HEADER='{"alg":"HS256","typ":"JWT","kid":"'$ID'"}'
PAYLOAD='{"iat":'$NOW',"exp":'$FIVE_MINS',"aud":"/admin/"}'

base64_url_encode() { echo "$1" | base64 | tr -d '=' | tr '+' '-' | tr '/' '_'; }

header_b64=$(base64_url_encode "$HEADER")
payload_b64=$(base64_url_encode "$PAYLOAD")
header_payload="$header_b64.$payload_b64"
signature=$(echo -n "$header_payload" | openssl dgst -binary -sha256 -hmac "$SECRET" | base64_url_encode)
TOKEN="$header_payload.$signature"

Utilisez ce token dans l'en-tête : Authorization: Ghost $TOKEN. Ajoutez aussi Accept-Version: v6.0 et Content-Type: application/json pour les POST/PUT.

En JavaScript, utilisez la bibliothèque @tryghost/admin-api (installez via npm install @tryghost/admin-api). Elle gère l'authentification automatiquement :

const GhostAdminAPI = require('@tryghost/admin-api');
const api = new GhostAdminAPI({
  url: 'https://votre-site.com',
  key: 'votre_id:votre_secret',
  version: 'v6.0'
});

Gérer les posts : CRUD complet

Les posts sont au cœur de Ghost. L'endpoint est /posts/. Par défaut, les réponses incluent le contenu en format Lexical (JSON). Ajoutez ?formats=html,lexical pour avoir aussi le HTML.

Lire des posts (GET)

Listez tous les posts : GET /admin/posts/?limit=5. Pour un post spécifique : GET /admin/posts/{id}/.

Exemple cURL :

curl -H "Authorization: Ghost $TOKEN" \
     -H "Accept-Version: v6.0" \
     "https://votre-site.com/ghost/api/admin/posts/"

En JS :

api.posts.browse({ limit: '5' }).then(console.log).catch(console.error);

Créer un post (POST)

Endpoint : POST /admin/posts/. Le payload est un objet avec un tableau posts. Champs requis : title. Optionnels : lexical (contenu JSON), status (draft ou published), tags (tableau de noms ou objets), authors (par email ou ID).

Exemple cURL pour un post publié :

curl -X POST "https://votre-site.com/ghost/api/admin/posts/" \
  -H "Authorization: Ghost $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept-Version: v6.0" \
  -d '{
    "posts": [{
      "title": "Mon premier post API",
      "lexical": "{\"root\":{\"children\":[{\"children\":[{\"text\":\"Bonjour le monde !\",\"type\":\"extended-text\"}],\"type\":\"paragraph\"}],\"type\":\"root\"}}",
      "status": "published",
      "tags": ["api", "ghost"]
    }]
  }'

En JS :

api.posts.add({
  title: 'Mon premier post API',
  lexical: '{"root":{"children":[{"children":[{"text":"Bonjour le monde !","type":"extended-text"}],"type":"paragraph"}],"type":"root"}}',
  status: 'published'
}).then(console.log);

Pour du HTML, ajoutez ?source=html et utilisez html au lieu de lexical. Note : La conversion HTML vers Lexical peut être lossy ; testez avec du HTML bien formé.

Modifier un post (PUT)

Endpoint : PUT /admin/posts/{id}/. Incluez updated_at du post original pour éviter les collisions (récupérez-le via GET d'abord).

Exemple cURL :

curl -X PUT "https://votre-site.com/ghost/api/admin/posts/{id}/" \
  -H "Authorization: Ghost $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept-Version: v6.0" \
  -d '{
    "posts": [{
      "title": "Titre mis à jour",
      "updated_at": "2025-11-29T10:00:00.000Z"
    }]
  }'

En JS :

const post = await api.posts.read({ id: '{id}' });
await api.posts.edit({
  id: '{id}',
  title: 'Titre mis à jour',
  updated_at: post.posts[0].updated_at
});

Les relations comme tags ou authors sont remplacées, pas mergées. Récupérez toujours la version actuelle.

Supprimer un post (DELETE)

Endpoint : DELETE /admin/posts/{id}/. Réponse : 204 No Content.

Exemple cURL :

curl -X DELETE "https://votre-site.com/ghost/api/admin/posts/{id}/" \
  -H "Authorization: Ghost $TOKEN" \
  -H "Accept-Version: v6.0"

En JS :

api.posts.delete({ id: '{id}' });

Gérer les membres : Ajouter et mettre à jour des abonnés

L'endpoint /members/ gère les abonnés (free ou paid). Par défaut, liste les 15 derniers. Utile pour importer des leads depuis un formulaire externe.

Lire des membres

GET /admin/members/?limit=10. Inclut email, nom, labels, subscriptions (avec détails Stripe si paid).

Créer un membre (POST)

Endpoint : POST /admin/members/. Minimum : email. Ajoutez name, note, labels (tableau d'objets {name, slug}), newsletters (IDs).

Exemple cURL :

curl -X POST "https://votre-site.com/ghost/api/admin/members/" \
  -H "Authorization: Ghost $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept-Version: v6.0" \
  -d '{
    "members": [{
      "email": "[email protected]",
      "name": "Jean Dupont",
      "labels": [{"name": "VIP", "slug": "vip"}],
      "note": "Lead depuis le site"
    }]
  }'

En JS (la lib supporte members via endpoints généraux, mais pour simplicité, utilisez fetch ou étendez) :

fetch('https://votre-site.com/ghost/api/admin/members/', {
  method: 'POST',
  headers: { 'Authorization': `Ghost ${token}`, 'Content-Type': 'application/json', 'Accept-Version': 'v6.0' },
  body: JSON.stringify({
    members: [{ email: '[email protected]', name: 'Jean Dupont' }]
  })
}).then(res => res.json());

Mettre à jour un membre (PUT)

Endpoint : PUT /admin/members/{id}/. Mettez à jour email, name, subscription, etc. Récupérez d'abord via GET.

Exemple : Changer le nom :

curl -X PUT "https://votre-site.com/ghost/api/admin/members/{id}/" \
  -H "Authorization: Ghost $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept-Version: v6.0" \
  -d '{
    "members": [{
      "name": "Jean Dupont II"
    }]
  }'

Suppression : DELETE /admin/members/{id}/.

Gérer les tiers et offres : Monétisation automatisée

Les tiers sont les niveaux d'abonnement (free/paid). Endpoint : /tiers/. Offres : /offers/ pour promotions.

Tiers

Lire : GET /admin/tiers/?filter=type:paid. Créer : POST /admin/tiers/, requis name, optionnels monthly_price (en centimes), yearly_price, currency, benefits (tableau).

Exemple création :

curl -X POST "https://votre-site.com/ghost/api/admin/tiers/" \
  -H "Authorization: Ghost $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept-Version: v6.0" \
  -d '{
    "tiers": [{
      "name": "Premium",
      "monthly_price": 1000,
      "yearly_price": 10000,
      "currency": "eur",
      "benefits": ["Accès exclusif", "Newsletter hebdo"]
    }]
  }'

Mettre à jour : PUT /admin/tiers/{id}/, par ex. changer nom ou archiver (active: false).

Offres

Créer : POST /admin/offers/, liez à un tier via tier: {id: '...', name: '...'}, ajoutez code, display_title.

Exemple :

curl -X POST "https://votre-site.com/ghost/api/admin/offers/" \
  -H "Authorization: Ghost $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept-Version: v6.0" \
  -d '{
    "offers": [{
      "name": "Offre lancement",
      "code": "LANCIEMENT50",
      "display_title": "50% off premier mois",
      "tier": {"id": "{tier_id}", "name": "Premium"}
    }]
  }'

Mettre à jour : PUT /admin/offers/{id}/, éditez name, code, display_title.

Autres ressources : Images, thèmes, newsletters, webhooks, users

Images

Upload : POST /admin/images/upload/ en multipart/form-data. Champs : file (fichier), ref (optionnel).

Exemple JS :

api.images.upload({ file: '/chemin/image.jpg' }).then(console.log);

Thèmes

Upload ZIP : POST /admin/themes/upload/ en multipart. Activez : PUT /admin/themes/{name}/activate.

Newsletters

Créer : POST /admin/newsletters/, champs comme name, sender_name, status: active. Mettre à jour : PUT /admin/newsletters/{id}/.

Webhooks

Pour notifier des événements (ex. post publié). Créer : POST /admin/webhooks/, requis event (ex. "post.published"), target_url.

Exemple :

curl -X POST "https://votre-site.com/ghost/api/admin/webhooks/" \
  -H "Authorization: Ghost $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept-Version: v6.0" \
  -d '{
    "webhooks": [{
      "event": "member.created",
      "target_url": "https://votre-app.com/hook"
    }]
  }'

Mettre à jour/supprimer : PUT/DELETE /admin/webhooks/{id}/.

Users (staff)

Gérer l'équipe : GET /admin/users/, PUT /admin/users/{id}/ pour éditer, DELETE /admin/users/{id}/. Invites : POST /admin/invites/, avec role_id et email.

Bonnes pratiques pour PME et startups

  • Pagination et filtres : Utilisez ?page=1&limit=15&filter=status:published pour éviter les timeouts.
  • Erreurs : Vérifiez les codes HTTP (200 OK, 400 Bad Request). L'API renvoie des messages clairs.
  • Sécurité : Utilisez des tokens courts ; stockez les clés en variables d'environnement.
  • Intégrations : Pour Zapier ou Node.js, commencez par la lib JS. Testez en local avec Ghost CLI.
  • Limites : Pas de rate limits stricts, mais évitez les abus (ex. 100 req/min).

Avec l'Admin API, vous automatisez 80 % des tâches manuelles. Pour plus, consultez docs.ghost.org/admin-api. Si vous intégrez avec Stripe ou un frontend Next.js, commencez par les posts et membres.