API rewriter.io
Récupérez les articles publiés de votre projet via une API en lecture seule simple et bien documentée - directement sur votre propre blog. REST, JSON, clé d'API, filtrage, tri et pagination.
Introduction
L'URL de base de l'API est https://public-api.rewriter.io/v1. Toutes les réponses sont renvoyées au format JSON (clés au format snake_case), et le corps de l'article est disponible sous forme de markdown et html. Chaque requête nécessite une clé d'API. L'API ne prend en charge que l'accès en lecture au contenu publié.
Dans l'environnement de test, utilisez l'adresse https://dev-hooks.rewriter.io/v1.
Pour les agents IA et les LLM, nous publions un index lisible par machine de cette documentation à l'adresse llms.txt.
Authentification
Transmettez la clé dans l'en-tête Authorization sous forme de jeton Bearer. La clé est liée à un seul projet.
# Vérifier à quel projet appartient la clé curl https://public-api.rewriter.io/v1/me \ -H "Authorization: Bearer rw_live_3f8a…"
Limites et versionnage
L'API est versionnée dans le chemin (/v1). La limite de requêtes dépend du forfait et est comptée séparément pour chaque clé API.
| Forfait | Limite / min |
|---|---|
| Start | 60 |
| Solo | 150 |
| Pro | 300 |
| Max | 1 000 |
Les réponses des forfaits limités incluent les en-têtes X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset. Avec un forfait illimité, les en-têtes X-RateLimit-* ne sont pas envoyés.
- Les requêtes GET sont accessibles depuis le navigateur (CORS).
- Tous les horodatages au format ISO 8601 (UTC).
Erreurs
Nous renvoyons les erreurs avec le code HTTP approprié et une structure uniforme :
{
"error": {
"code": "not_found",
"message": "Article not found."
}
}400- paramètres de requête non valides401- clé d'API manquante ou non valide403- votre forfait n'inclut pas l'accès à l'API404- introuvable (article non publié ou hors du projet)429- limite de requêtes dépassée500- erreur du serveur
Pagination et tri
Nous renvoyons les listes dans une enveloppe avec des champs de données et des métadonnées de page :
{
"data": [
"…"
],
"page": 1,
"per_page": 10,
"total": 42
}Vous contrôlez la pagination avec les paramètres page (à partir de 1) et limit (par défaut 10, max. 100). Vous définissez le tri avec le paramètre sort - le préfixe “-” indique un ordre décroissant. Valeurs autorisées : published_at, -published_at, title, -title, updated_at, -updated_at.
Projet
Renvoie des informations sur le projet lié à la clé ainsi que les langues disponibles. Utile pour vérifier la clé.
{
"id": "k17a9c…",
"name": "Kawiarnia Pod Lipą",
"primary_language": "pl",
"available_languages": [
"pl",
"en"
],
"plan": "Pro",
"rate_limit_per_minute": 300
}Sujets
Renvoie la liste des sujets du projet. Utilisez le champ id comme valeur du filtre topic_id dans la liste des articles.
{
"data": [
{
"id": "j57b2…",
"title": "Lokalne SEO"
},
{
"id": "j58c1…",
"title": "Porady baristów"
}
]
}Catégories
Renvoie la liste des catégories du projet. Utilisez le champ id comme valeur du filtre category_id dans la liste des articles. Les noms suivent le paramètre language (par défaut, la langue principale).
{
"data": [
{
"id": "k20a1…",
"name": "Pielęgnacja ogrodu",
"slug": "pielegnacja-ogrodu"
},
{
"id": "k20a2…",
"name": "Porady",
"slug": "porady"
}
]
}Lister les articles
Renvoie une liste paginée d'articles publiés (champs de résumé, sans le corps).
Paramètres de requête
topic_id- string, facultatif. Filtrer par identifiant de sujet.category_id- string, facultatif. Filtrer par identifiant de catégorie.language- string, facultatif. Code de langue ; par défaut, la langue principale du projet. Un autre code renvoie les traductions publiées.q- string, facultatif. Recherche par titre (sans distinction de casse).published_after- date ISO 8601, facultative. Uniquement les articles publiés à partir de cette date.published_before- date ISO 8601, facultative. Uniquement les articles publiés jusqu'à cette date.sort- string, par défaut -published_at. Voir la section Pagination et tri.page- nombre, par défaut 1.limit- nombre, par défaut 10, max. 100.
Omettez simplement un paramètre que vous n'utilisez pas : une valeur vide (par exemple sort=) est traitée comme un paramètre absent.
{
"data": [
{
"id": "m93f7…",
"title": "10 sposobów na lokalne SEO",
"slug": "10-sposobow-na-lokalne-seo",
"language": "pl",
"topic_id": "j57b2…",
"category": {
"id": "k20a1…",
"name": "Pielęgnacja ogrodu",
"slug": "pielegnacja-ogrodu"
},
"status": "published",
"seo_score": 96,
"readability_score": 72,
"fact_check_status": "passed",
"cover_image": "https://cdn.example.com/articles/m93f7/cover.png",
"published_at": "2026-05-21T09:12:00.000Z",
"updated_at": "2026-05-22T10:00:00.000Z"
}
],
"page": 1,
"per_page": 10,
"total": 42
}Obtenir un article
Renvoie le corps complet d'un article publié avec ses métadonnées SEO. Le corps est disponible en Markdown et en fragment HTML. Le paramètre :id accepte l'id complet de l'article ; le blog rewriter.io accepte aussi une référence slug-8 caractères.
Paramètres de requête
language- string, facultatif. Code de langue pour obtenir une traduction publiée au lieu de la version dans la langue principale.format- markdown ou html, facultatif. Par défaut, nous renvoyons les deux champs de corps.
{
"id": "m93f7…",
"title": "10 sposobów na lokalne SEO",
"slug": "10-sposobow-na-lokalne-seo",
"topic_id": "j57b2…",
"category": {
"id": "k20a1…",
"name": "Pielęgnacja ogrodu",
"slug": "pielegnacja-ogrodu"
},
"language": "pl",
"status": "published",
"body_markdown": "## Wstęp\n\nLokalne SEO to…",
"body_html": "<h2>Wstęp</h2>\n<p>Lokalne SEO to…</p>",
"cover_image": "https://cdn.example.com/articles/m93f7/cover.png",
"meta_title": "Lokalne SEO dla kawiarni",
"meta_description": "Praktyczny przewodnik po lokalnym SEO.",
"seo_score": 96,
"readability_score": 72,
"readability_label": "łatwy",
"fact_check_status": "passed",
"uniqueness_score": 98,
"alternate_slugs": [
{
"language": "pl",
"slug": "10-sposobow-na-lokalne-seo"
},
{
"language": "en",
"slug": "10-ways-to-improve-local-seo"
}
],
"json_ld": {
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "10 sposobów na lokalne SEO",
"inLanguage": "pl",
"wordCount": 1240,
"…": "…"
},
"published_at": "2026-05-21T09:12:00.000Z",
"updated_at": "2026-05-22T10:00:00.000Z"
}Article dans un modèle HTML
Renvoie une page HTML prête de l'article publié, enveloppée dans le modèle du projet (text/html au lieu de JSON). Prend en charge le paramètre language. Idéal pour une intégration directe sur un site.
curl https://public-api.rewriter.io/v1/articles/m93f7…/html \
-H "Authorization: Bearer rw_live_3f8a…"Webhooks
Les webhooks envoient des requêtes POST signées vers votre URL lorsque des événements de contenu se produisent dans votre projet. Configurez-les dans le tableau de bord, dans la section Compte → API et intégrations.
Vous pouvez aussi les enregistrer par programmation, avec la seule clé API et sans passer par le tableau de bord. Voir Abonnements webhook.
Événements disponibles
article.published- un article a été publié.article.scheduled- la publication d'un article a été planifiée.article.unpublished- la publication d'un article a été annulée.article.archived- un article a été archivé.article.restored- un article a été restauré depuis l'archive.article.translated- une traduction d'article a été publiée.topic.created- un nouveau sujet a été créé.headline.created- de nouvelles suggestions d'articles (titres) ont été générées.
Corps de la requête
Chaque requête contient une enveloppe JSON avec id (l'identifiant de livraison - utilisez-le pour la déduplication), event, created_at, project_id et data avec les détails de l'événement :
{
"id": "whd_4f2a…",
"event": "article.published",
"created_at": "2026-05-21T09:12:00.000Z",
"project_id": "k17a9c…",
"data": {
"id": "m93f7…",
"title": "10 sposobów na lokalne SEO",
"slug": "10-sposobow-na-lokalne-seo",
"language": "pl",
"status": "published",
"topic_id": "j57b2…",
"category": {
"id": "k20a1…",
"name": "Pielęgnacja ogrodu",
"slug": "pielegnacja-ogrodu"
},
"seo_score": 96,
"readability_score": 72,
"fact_check_status": "passed",
"published_at": "2026-05-21T09:12:00.000Z",
"updated_at": "2026-05-21T09:12:00.000Z"
}
}Vérification de la signature
Chaque requête contient l'en-tête X-Rewriter-Webhook-Signature avec une signature HMAC-SHA256 calculée sur l'horodatage (en-tête X-Rewriter-Webhook-Timestamp), un point et le corps de la requête, au format sha256=<hex>. Recalculez-la avec votre secret et comparez en temps constant.
const ts = req.headers["x-rewriter-webhook-timestamp"];
const sig = req.headers["x-rewriter-webhook-signature"];
const expected = "sha256=" + crypto
.createHmac("sha256", WEBHOOK_SECRET)
.update(ts + "." + rawBody)
.digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));Nouvelles tentatives et désactivation automatique
Les livraisons échouées sont réessayées avec un intervalle croissant (jusqu'à 5 tentatives), en envoyant le même identifiant de livraison à chaque tentative. Après de nombreux échecs consécutifs, le webhook est désactivé automatiquement - réactivez-le dans le tableau de bord.
Abonnements webhook
Vous pouvez enregistrer et supprimer des callbacks webhook par programmation, avec la seule clé API et sans passer par le tableau de bord. Ces points de terminaison alimentent les déclencheurs instantanés de nos applications Zapier et Make.com, et vous pouvez aussi les utiliser dans votre propre intégration.
POST et GET exigent en plus une offre incluant les webhooks, sinon ils renvoient 403 forbidden. DELETE est autorisé par la seule clé API, la suppression d'un abonnement continue donc de fonctionner après un changement d'offre.
Créer un abonnement
Enregistre une URL de callback pour exactement un événement et renvoie l'objet d'abonnement avec le statut 201 (sans enveloppe data). Conservez l'id renvoyé : vous le transmettez pour supprimer l'abonnement.
Corps de la requête
target_url- obligatoire. Une URL de callback HTTPS sur l'un des hôtes autorisés.event- obligatoire. Un événement de la liste ci-dessus.
curl -X POST https://public-api.rewriter.io/v1/webhooks \ -H "Authorization: Bearer rw_live_3f8a…" \ -H "Content-Type: application/json" \ -d '{"target_url":"https://hook.eu2.make.com/abc123","event":"article.published"}'
{
"id": "n41c8…",
"event": "article.published",
"target_url": "https://hook.eu2.make.com/abc123",
"status": "enabled"
}Objet abonnement
id- l'identifiant de l'abonnement : transmettez-le à DELETE.event- l'événement pour lequel l'abonnement est enregistré.target_url- l'URL de callback enregistrée.status- enabled ou disabled : un abonnement est désactivé automatiquement après plusieurs livraisons en échec.
Hôtes autorisés pour target_url
target_url doit être une URL de hook HTTPS d'une plateforme d'automatisation sur l'un de ces hôtes :
hooks.zapier.com- URLs catch hook de Zapier.hook.make.com, hook.<zone>.make.com- webhooks Make.com, par exemple hook.eu2.make.com.
Tout autre hôte, une URL non HTTPS, une URL avec identifiants ou une adresse privée, de bouclage ou de métadonnées est rejetée avec 400 bad_request.
Renvoyer le même couple target_url et event ne crée pas de doublon : l'abonnement existant est réactivé et renvoyé avec le même id. Un projet peut contenir jusqu'à 20 abonnements par plateforme.
Lister les abonnements
Renvoie les abonnements créés avec cette clé API dans ce projet. Les abonnements créés avec une autre clé et les webhooks configurés dans le tableau de bord ne sont jamais renvoyés.
{
"data": [
{
"id": "n41c8…",
"event": "article.published",
"target_url": "https://hook.eu2.make.com/abc123",
"status": "enabled"
}
]
}Supprimer un abonnement
Supprime l'abonnement portant l'id indiqué. Idempotent : un id inconnu, déjà supprimé ou appartenant à un autre projet renvoie 200 avec deleted: false au lieu de 404, la suppression n'échoue donc jamais.
{
"id": "n41c8…",
"deleted": true
}Erreurs
400 bad_request- target_url ou event manquant, événement inconnu ou target_url hors des hôtes autorisés.401 unauthorized- clé API absente ou invalide.403 forbidden- l'offre n'inclut pas les webhooks ou la limite de 20 abonnements est atteinte.
Ces réponses portent les mêmes en-têtes X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset que les points de terminaison de lecture.