Se connecter Commencer l'essai gratuit

Récupérez vos articles.
Publiez-les à votre façon.

Chaque article que nous écrivons pour vous peut être lu via HTTP : le titre, les métadonnées, le Markdown, le HTML, l’image principale et la FAQ. Récupérez-les dans votre site Next.js, Astro ou personnalisé lors de l’exécution de votre build, mettez-les en ligne, puis indiquez-nous l’adresse finale de chacun.

Un jeton bearer. JSON en entrée, JSON en sortie. Aucun SDK à installer et rien à configurer au-delà d’une clé.

Le webhook envoie. L’API vous permet de récupérer.

Ils transportent le même article dans le même format, donc un parseur écrit pour l’un lit l’autre sans modification. La différence tient à qui lance l’échange.

Le webhook, lorsque votre site peut accepter une publication à toute heure

Nous appelons votre point de terminaison dès qu’un article est prêt, puis de nouveau lorsqu’il change. Rien à interroger, rien à planifier. WordPress, Shopify, Ghost, un déclencheur Zapier ou une route que vous avez écrite vous-même.

L’API, lorsque votre site est construit et déployé comme un tout

Un site statique ne peut pas accepter une publication à six heures et demie du matin ; il faut d’abord reconstruire quelque chose. Votre build demande donc ce qui est en attente, le récupère, puis nous indique l’adresse ensuite. Vous choisissez quand.

Les deux, si vous le souhaitez

Ce sont des connexions distinctes et aucune n’exclut l’autre. Un webhook qui alimente une newsletter et une API qui alimente le site web est une configuration normale.

Une clé, envoyée comme jeton bearer.

Créez une clé dans le tableau de bord sous Settings, puis Connections. Elle n’est affichée qu’une seule fois, lors de sa création, car seul son hash est stocké : si vous la perdez, révoquez-la et créez-en une autre. Une clé lit tous les sites du compte et se révoque depuis le même écran.

Chaque requête

Authorization: Bearer sns_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Accept: application/json

Vérifiez que cela fonctionne

curl https://seonis.ai/api/v1/me \
  -H "Authorization: Bearer $SEONIS_API_KEY"
{
  "organisation": { "id": 12, "name": "Peppervale", "country": "GB" },
  "key": {
    "name": "Production build",
    "prefix": "sns_live_ab",
    "created_at": "2026-09-06T09:12:44+00:00",
    "last_used_at": "2026-09-06T09:31:02+00:00"
  },
  "sites": 2
}

Limite de débit

120 requêtes par minute, comptées sur la clé plutôt que sur l’adresse d’où elles viennent, car les exécuteurs de build partagent des adresses. Au-delà, vous recevez une 429 avec les en-têtes standard Retry-After et X-RateLimit. Récupérer des articles pour un build représente une poignée de requêtes, donc ce n’est pas une limite que vous devriez atteindre par accident.

Gardez la clé hors de votre dépôt

Elle lit tout ce que nous avons écrit pour votre compte, y compris les articles qui ne sont pas encore publiés. Placez-la dans votre environnement de build, pas dans votre code source. Révoquez-la ici dès qu’elle se trouve là où elle ne devrait pas être, et tout ce qui l’utilise reçoit immédiatement une 401.

Il y en a cinq, et quatre sont en lecture seule.

Tout se trouve sous /api/v1/. La version est dans le chemin dès le premier jour, afin qu’une v2 puisse exister un jour sans casser ce que vous écrivez aujourd’hui.

GET /api/v1/me

Le compte auquel la clé appartient, ainsi que le nom et le préfixe de la clé. Cela sert avant tout à vous indiquer que la clé dans cet environnement est bien celle que vous pensez.

Exemple

curl https://seonis.ai/api/v1/me \
  -H "Authorization: Bearer $SEONIS_API_KEY"
GET /api/v1/sites

Chaque site du compte. L’id est ce sur quoi la liste des articles filtre, et le domaine est là pour qu’un script de build puisse faire la correspondance avec quelque chose qu’il connaît déjà plutôt que de transporter un id.

Exemple

curl https://seonis.ai/api/v1/sites \
  -H "Authorization: Bearer $SEONIS_API_KEY"
{
  "sites": [
    {
      "id": 5,
      "name": "Peppervale",
      "domain": "peppervale.co.uk",
      "url": "https://peppervale.co.uk",
      "language": "en",
      "country": "GB",
      "market": "en-GB",
      "status": "active",
      "articles_published": 34,
      "created_at": "2026-06-02T11:04:19+00:00"
    }
  ]
}
GET /api/v1/articles

Une page d’articles, changement le plus récent d’abord, sans le contenu. Triée selon la date de dernière modification de chaque article plutôt que selon sa date d’écriture, ce qui donne son intérêt à updated_since : un article déjà en ligne peut être modifié plus tard, lorsqu’un lien y est ajouté ou retiré.

Paramètres de requête

Nom Ce que cela fait
site_id Un site, depuis /sites. Un id qui n’est pas sur votre compte renvoie 404.
status L’un de draft, qa, needs_repair, review, ready, published, failed. Toute autre valeur renvoie une 422 plutôt qu’une page vide. "ready" est ce qu’un build veut : écrit, vérifié et encore publié nulle part.
updated_since ISO 8601, par exemple 2026-09-06T00:00:00Z. Conservez l’horodatage de votre dernière exécution et renvoyez-le lors de la suivante.
per_page Jusqu’à 100. La valeur par défaut est 25.
page À partir de 1. meta.has_more indique s’il faut en demander une autre.

Exemple

curl -G https://seonis.ai/api/v1/articles \
  -H "Authorization: Bearer $SEONIS_API_KEY" \
  -d site_id=5 \
  -d status=ready \
  -d updated_since=2026-09-01T00:00:00Z \
  -d per_page=50
{
  "articles": [
    {
      "id": 918,
      "site_id": 5,
      "language": "en",
      "status": "ready",
      "title": "How to choose a pepper grinder",
      "slug": "how-to-choose-a-pepper-grinder",
      "meta_title": "How to choose a pepper grinder | Peppervale",
      "meta_description": "Burr or blade, ceramic or steel: what matters in a grinder.",
      "meta_keywords": ["pepper grinder", "burr grinder"],
      "tags": ["Kitchen"],
      "excerpt": "A burr grinder gives an even grind; a blade one does not.",
      "key_takeaways": ["A burr grinder gives an even grind; a blade one does not."],
      "faq": [{ "question": "Ceramic or steel?", "answer": "Steel for pepper, ceramic for salt." }],
      "hero_image": { "url": "https://seonis.ai/storage/images/5/918.jpg", "alt": "A pepper grinder" },
      "infographic_url": null,
      "word_count": 1812,
      "published_url": null,
      "published_at": null,
      "updated_at": "2026-09-06T06:31:12+00:00",
      "created_at": "2026-09-05T02:14:55+00:00",
      "quality": { "seo_score": 88, "language_score": 96, "language_findings": [] }
    }
  ],
  "meta": { "page": 1, "per_page": 50, "total": 1, "last_page": 1, "has_more": false }
}
GET /api/v1/articles/{id}

Un article, avec tout ce que la liste laisse de côté : content_markdown, content_html, la FAQ en schema.org JSON-LD prête à être insérée dans la page, et tous les liens d’échange que l’article contient.

Les noms de champs sont ceux que notre webhook envoie, volontairement. Si vous avez déjà un récepteur de webhook, le même parseur lit ceci.

Exemple

curl https://seonis.ai/api/v1/articles/918 \
  -H "Authorization: Bearer $SEONIS_API_KEY"
{
  "article": {
    "id": 918,
    "site_id": 5,
    "language": "en",
    "status": "ready",
    "title": "How to choose a pepper grinder",
    "slug": "how-to-choose-a-pepper-grinder",
    "meta_description": "Burr or blade, ceramic or steel: what matters in a grinder.",
    "content_markdown": "Grinders differ.\n\n## Burr or blade\n\nA **burr** grinder ...",
    "content_html": "<p>Grinders differ.</p>\n<h2>Burr or blade</h2> ...",
    "faq_schema": { "@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [] },
    "hero_image": { "url": "https://seonis.ai/storage/images/5/918.jpg", "alt": "A pepper grinder" },
    "word_count": 1812,
    "published_url": null,
    "updated_at": "2026-09-06T06:31:12+00:00",
    "quality": { "seo_score": 88, "language_score": 96, "language_findings": [] },
    "exchange_links": []
  }
}
POST /api/v1/articles/{id}/published

Vous mettez l’article en ligne ; c’est ici que vous nous indiquez l’adresse. C’est le seul point de terminaison qui modifie quoi que ce soit.

Cela fait exactement ce qu’une livraison effectuée par nous-mêmes fait : l’article est marqué comme publié, il est compté dans votre quota mensuel, l’élément du plan est clôturé, tous les liens d’échange qu’il contient reçoivent l’adresse que le vérificateur attendait, et votre Page Facebook est informée si vous en avez connecté une. Sans cet appel, l’article reste prêt pour toujours et rien de tout cela ne se produit.

Exemple

curl -X POST https://seonis.ai/api/v1/articles/918/published \
  -H "Authorization: Bearer $SEONIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://peppervale.co.uk/blog/how-to-choose-a-pepper-grinder"}'

Réponses

200 Enregistré. L’article revient avec son nouveau statut, published_at et published_url.
422 L’url est manquante ou n’est pas une adresse complète en http:// ou https://.
409 L’article n’est pas prêt à être publié, ou est déjà enregistré comme publié. L’article revient avec le refus, afin que vous puissiez voir lequel des deux cas s’applique.

Connectez "REST API" comme moteur de publication.

Sous Settings, puis Publishing, il existe un moteur appelé "REST API: you fetch and publish". Il ne demande rien, car nous n’avons rien à envoyer. Ce qu’il change, c’est ce qui se passe chaque matin : un article terminé reste prêt sans adresse, et l’écran de publication indique qu’il attend que vous veniez le récupérer au lieu d’afficher un envoi qui a échoué.

Vous pouvez utiliser l’API sans la connecter : les points de terminaison fonctionnent pour tout compte disposant d’une clé. La connecter permet au reste du produit de savoir qu’il ne doit plus attendre une adresse de sa part, et c’est ce qui empêche qu’un article que vous publiez vous-même soit compté comme un échec.

Chaque échec est du JSON avec un message.

Une seule forme partout, que le refus vienne de la vérification de la clé ou du validateur, afin que rien n’ait à en analyser deux.

{ "message": "That API key is not valid, or it has been revoked." }
Statut Ce que cela signifie
401 Aucune clé, une clé qui n’est pas la nôtre, ou une clé qui a été révoquée.
404 Aucun article ou site de ce type sur ce compte. L’article d’un autre compte renvoie 404 plutôt que 403 : une API qui dit "ce n’est pas à vous" a confirmé que la chose existe.
409 La requête était correcte, mais l’article n’est pas dans un état qui le permet.
422 Un paramètre est manquant ou incorrect. La réponse contient un objet errors indiquant le champ, ainsi que le message.
429 Limite de débit dépassée. Retry-After indique combien de temps attendre.

Ce qu’une étape de build fait réellement.

#!/usr/bin/env bash
set -euo pipefail

# 1. What is finished and not yet on the site?
ready=$(curl -sG https://seonis.ai/api/v1/articles \
  -H "Authorization: Bearer $SEONIS_API_KEY" \
  -d site_id=5 -d status=ready -d per_page=100)

for id in $(echo "$ready" | jq -r '.articles[].id'); do
  # 2. Take the article, body and all.
  curl -s https://seonis.ai/api/v1/articles/$id \
    -H "Authorization: Bearer $SEONIS_API_KEY" \
    | jq -r '.article.content_markdown' > "content/posts/$id.md"

  # 3. Your build puts it live, and you know where it landed.
  slug=$(echo "$ready" | jq -r ".articles[] | select(.id==$id) | .slug")

  curl -s -X POST https://seonis.ai/api/v1/articles/$id/published \
    -H "Authorization: Bearer $SEONIS_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"url\": \"https://peppervale.co.uk/blog/$slug\"}"
done

Créez une clé et essayez-la.

L’essai suffit pour utiliser l’API : les articles rédigés pendant cette période sont de vrais articles, et ils reviennent par ces points de terminaison comme les autres.

Commencer l'essai gratuit