Empieza gratis
Documentación de la API · v1

API rewriter.io

Recupera los artículos publicados de tu proyecto mediante una API de solo lectura sencilla y bien documentada, directamente a tu propio blog. REST, JSON, clave de API, filtrado, ordenación y paginación.

Introducción

La URL base de la API es https://public-api.rewriter.io/v1. Todas las respuestas se devuelven en formato JSON (claves en estilo snake_case) y el cuerpo del artículo está disponible como markdown y html. Cada solicitud requiere una clave de API. La API admite únicamente el acceso de lectura a contenido publicado.

Sugerencia: puedes generar una clave de API en el panel, en la sección Cuenta → API e integraciones. Guárdala en el lado del servidor: no la incluyas en el código del front-end.

En el entorno de pruebas, usa la dirección https://dev-hooks.rewriter.io/v1.

Para agentes de IA y LLM publicamos un índice legible por máquina de esta documentación en llms.txt.

Autenticación

Pasa la clave en el encabezado Authorization como token Bearer. La clave está vinculada a un único proyecto.

terminal
# Comprueba a qué proyecto pertenece la clave
curl https://public-api.rewriter.io/v1/me \
  -H "Authorization: Bearer rw_live_3f8a…"

Límites y versionado

La API está versionada en la ruta (/v1). El límite de solicitudes depende del plan y se cuenta por separado para cada clave de API.

PlanLímite / min
Start60
Solo150
Pro300
Max1000

Las respuestas de planes con límite incluyen los encabezados X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset. En un plan sin límite no se envían encabezados X-RateLimit-*.

  • Las solicitudes GET son accesibles desde el navegador (CORS).
  • Todas las marcas de tiempo en formato ISO 8601 (UTC).

Errores

Devolvemos los errores con el código HTTP correspondiente y una estructura uniforme:

error
{
  "error": {
    "code": "not_found",
    "message": "Article not found."
  }
}
  • 400 - parámetros de consulta no válidos
  • 401 - clave de API ausente o no válida
  • 403 - tu plan no incluye acceso a la API
  • 404 - no encontrado (artículo no publicado o fuera del proyecto)
  • 429 - límite de solicitudes superado
  • 500 - error del servidor

Paginación y ordenación

Devolvemos las listas en un sobre con campos de datos y metadatos de página:

GET /v1/articles
{
  "data": [
    "…"
  ],
  "page": 1,
  "per_page": 10,
  "total": 42
}

La paginación se controla con los parámetros page (desde 1) y limit (predeterminado 10, máx. 100). La ordenación se establece con el parámetro sort: el prefijo “-” indica orden descendente. Valores permitidos: published_at, -published_at, title, -title, updated_at, -updated_at.

Proyecto

GET/v1/me

Devuelve información sobre el proyecto vinculado a la clave y los idiomas disponibles. Útil para verificar la clave.

GET /v1/me
{
  "id": "k17a9c…",
  "name": "Kawiarnia Pod Lipą",
  "primary_language": "pl",
  "available_languages": [
    "pl",
    "en"
  ],
  "plan": "Pro",
  "rate_limit_per_minute": 300
}

Temas

GET/v1/topics

Devuelve la lista de temas del proyecto. Usa el campo id como valor del filtro topic_id en la lista de artículos.

GET /v1/topics
{
  "data": [
    {
      "id": "j57b2…",
      "title": "Lokalne SEO"
    },
    {
      "id": "j58c1…",
      "title": "Porady baristów"
    }
  ]
}

Categorías

GET/v1/categories

Devuelve la lista de categorías del proyecto. Usa el campo id como valor del filtro category_id en la lista de artículos. Los nombres siguen el parámetro language (por defecto, el idioma principal).

GET /v1/categories
{
  "data": [
    {
      "id": "k20a1…",
      "name": "Pielęgnacja ogrodu",
      "slug": "pielegnacja-ogrodu"
    },
    {
      "id": "k20a2…",
      "name": "Porady",
      "slug": "porady"
    }
  ]
}

Listar artículos

GET/v1/articles

Devuelve una lista paginada de artículos publicados (campos de resumen, sin el cuerpo).

Parámetros de consulta

  • topic_id - string, opcional. Filtrar por identificador de tema.
  • category_id - string, opcional. Filtrar por identificador de categoría.
  • language - string, opcional. Código de idioma; por defecto, el idioma principal del proyecto. Otro código devuelve las traducciones publicadas.
  • q - string, opcional. Búsqueda por título (sin distinguir mayúsculas y minúsculas).
  • published_after - fecha ISO 8601, opcional. Solo artículos publicados a partir de esta fecha.
  • published_before - fecha ISO 8601, opcional. Solo artículos publicados hasta esta fecha.
  • sort - string, predeterminado -published_at. Consulta la sección Paginación y ordenación.
  • page - número, predeterminado 1.
  • limit - número, predeterminado 10, máx. 100.

Omite el parámetro que no utilices: un valor vacío (por ejemplo sort=) se trata igual que un parámetro ausente.

GET /v1/articles?sort=-published_at&limit=10
{
  "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
}

Obtener artículo

GET/v1/articles/:id

Devuelve el cuerpo completo de un artículo publicado junto con los metadatos SEO. El cuerpo está disponible como Markdown y como fragmento HTML. El parámetro :id acepta el id completo del artículo; el blog propio de rewriter.io también acepta una referencia slug-8 caracteres.

Parámetros de consulta

  • language - string, opcional. Código de idioma para obtener una traducción publicada en lugar de la versión en el idioma principal.
  • format - markdown o html, opcional. Por defecto devolvemos ambos campos del cuerpo.
GET /v1/articles/m93f7…
{
  "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"
}

Artículo en una plantilla HTML

GET/v1/articles/:id/html

Devuelve una página HTML lista del artículo publicado, envuelta en la plantilla del proyecto (text/html en lugar de JSON). Admite el parámetro language. Ideal para incrustar directamente en un sitio.

terminal
curl https://public-api.rewriter.io/v1/articles/m93f7…/html \
  -H "Authorization: Bearer rw_live_3f8a…"

Webhooks

Los webhooks envían solicitudes POST firmadas a tu URL cuando ocurren eventos de contenido en tu proyecto. Configúralos en el panel, en la sección Cuenta → API e integraciones.

También puedes registrarlos mediante la API, solo con una clave API y sin pasar por el panel. Consulta Suscripciones de webhooks.

Eventos disponibles

  • article.published - se publicó un artículo.
  • article.scheduled - se programó la publicación de un artículo.
  • article.unpublished - se retiró de la publicación un artículo.
  • article.archived - se archivó un artículo.
  • article.restored - se restauró un artículo desde el archivo.
  • article.translated - se publicó una traducción de un artículo.
  • topic.created - se creó un tema nuevo.
  • headline.created - se generaron nuevas sugerencias de artículos (titulares).

Cuerpo de la solicitud

Cada solicitud lleva un sobre JSON con id (el identificador de entrega - úsalo para deduplicar), event, created_at, project_id y data con los detalles del evento:

POST (webhook)
{
  "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"
  }
}

Verificación de la firma

Cada solicitud incluye el encabezado X-Rewriter-Webhook-Signature con una firma HMAC-SHA256 de la marca de tiempo (encabezado X-Rewriter-Webhook-Timestamp), un punto y el cuerpo de la solicitud, en el formato sha256=<hex>. Vuelve a calcularla con tu secreto y compárala en tiempo constante.

verify (node)
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));

Reintentos y desactivación automática

Las entregas fallidas se reintentan con un intervalo creciente (hasta 5 intentos), enviando el mismo identificador de entrega en cada intento. Tras muchos fallos consecutivos, el webhook se desactiva automáticamente: vuelve a activarlo en el panel.

Suscripciones de webhooks

Puedes registrar y eliminar callbacks de webhook mediante la API, solo con una clave API y sin pasar por el panel. Estos endpoints alimentan los disparadores instantáneos de nuestras apps de Zapier y Make.com, y también puedes usarlos en tu propia integración.

POST y GET requieren además un plan que incluya webhooks; de lo contrario devuelven 403 forbidden. DELETE se autoriza solo con la clave API, así que eliminar una suscripción sigue funcionando tras un cambio de plan.

Crear una suscripción

POST/v1/webhooks

Registra una URL de callback para exactamente un evento y devuelve el objeto de suscripción con estado 201 (sin envoltorio data). Guarda el id devuelto: lo necesitas para eliminar la suscripción.

Cuerpo de la solicitud

  • target_url - obligatorio. Una URL de callback HTTPS en uno de los hosts permitidos.
  • event - obligatorio. Un evento de la lista anterior.
terminal
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"}'
201 Created
{
  "id": "n41c8…",
  "event": "article.published",
  "target_url": "https://hook.eu2.make.com/abc123",
  "status": "enabled"
}

Objeto de suscripción

  • id - el identificador de la suscripción: pásalo a DELETE.
  • event - el evento para el que está registrada la suscripción.
  • target_url - la URL de callback registrada.
  • status - enabled o disabled: una suscripción se desactiva automáticamente tras varias entregas fallidas.

Hosts permitidos en target_url

target_url debe ser una URL HTTPS de hook de una plataforma de automatización en uno de estos hosts:

  • hooks.zapier.com - URLs de catch hook de Zapier.
  • hook.make.com, hook.<zona>.make.com - webhooks de Make.com, por ejemplo hook.eu2.make.com.

Cualquier otro host, una URL sin HTTPS, una URL con credenciales o una dirección privada, de bucle local o de metadatos se rechaza con 400 bad_request.

Enviar de nuevo el mismo par target_url y event no crea un duplicado: la suscripción existente se reactiva y se devuelve con el mismo id. Un proyecto admite hasta 20 suscripciones por plataforma.

Listar suscripciones

GET/v1/webhooks

Devuelve las suscripciones creadas con esta clave API en este proyecto. Las suscripciones creadas con otra clave y los webhooks configurados en el panel nunca se devuelven.

GET /v1/webhooks
{
  "data": [
    {
      "id": "n41c8…",
      "event": "article.published",
      "target_url": "https://hook.eu2.make.com/abc123",
      "status": "enabled"
    }
  ]
}

Eliminar una suscripción

DELETE/v1/webhooks/:id

Elimina la suscripción con el id indicado. Es idempotente: un id desconocido, ya eliminado o ajeno devuelve 200 con deleted: false en lugar de 404, así que la limpieza nunca falla.

DELETE /v1/webhooks/n41c8…
{
  "id": "n41c8…",
  "deleted": true
}

Errores

  • 400 bad_request - falta target_url o event, evento desconocido o una target_url fuera de los hosts permitidos.
  • 401 unauthorized - clave API ausente o no válida.
  • 403 forbidden - el plan no incluye webhooks o se alcanzó el límite de 20 suscripciones.

Estas respuestas incluyen las mismas cabeceras X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset que los endpoints de lectura.