API
PrestaBlog ofrece una API REST que permite a herramientas externas - scripts, software de terceros o agentes de IA - crear y gestionar artículos y categorías del blog sin pasar por el back office. Esta funcionalidad, disponible a partir de PrestaShop 8, está pensada tanto para no desarrolladores mediante un agente de IA, como para desarrolladores que quieran una integración directa.
Configuración de la API
Antes de nada, la API debe estar activada y configurada en el back office.
Abrir la configuración:
Módulos > PrestaBlog > Configuración > Herramientas > API
Parámetros disponibles:
- Activar API: interruptor principal. La API no responderá a ninguna petición mientras esté desactivada.
- Clave API: haz clic en “Generar una nueva clave”. La clave se muestra una sola vez: cópiala inmediatamente, ya que no volverá a ser accesible. Solo se almacena su huella criptográfica (SHA-256). Si pierdes la clave, genera una nueva.
- Activar automáticamente nuevos artículos: define si los artículos creados vía API se publican inmediatamente o se guardan como borradores cuando la petición no especifica este parámetro.
- Límite de solicitudes: número máximo de solicitudes por minuto y por dirección IP (por defecto: 60).
- Seguridad de imágenes: bloquea la descarga de imágenes desde rangos de IP privadas/internas. Recomendado para instalaciones expuestas a Internet.
- Detrás de un proxy: activar si tu tienda está detrás de Cloudflare, un reverse proxy o un CDN, para gestionar correctamente la IP del cliente.
- Nivel de log: Ninguno desactiva los logs. Seguridad registra intentos fallidos de autenticación y bloqueos. Debug registra todas las peticiones (úsalo temporalmente para diagnóstico).
- Orígenes CORS permitidos: solo si una aplicación web alojada en otro dominio debe llamar a la API desde un navegador. Déjalo vacío en la mayoría de los casos.
Permisos de la API
La sección Permisos de la API permite restringir con precisión lo que la clave API está autorizada a hacer. Cada operación puede activarse o desactivarse de forma independiente, tanto para artículos como para categorías.
- Permitir la creación de artículos / categorías: autoriza las solicitudes
POSTpara crear nuevo contenido. - Permitir la modificación de artículos / categorías: autoriza las solicitudes
PUTpara actualizar contenido existente. - Permitir la eliminación de artículos / categorías: autoriza las solicitudes
DELETE. Desactívalo si quieres evitar eliminaciones accidentales desde un agente de IA o un script de terceros.
La API requiere HTTPS. En HTTP, todas las peticiones se rechazan (excepto desde localhost para pruebas en desarrollo).
No compartas nunca tu clave API.
Uso con un agente de IA (recomendado)
¿No eres desarrollador o no quieres escribir código? El método más sencillo es usar un agente de IA como Claude mediante el protocolo MCP (Model Context Protocol). El agente sabe exactamente qué llamadas realizar, gestiona la autenticación y entiende tus instrucciones en lenguaje natural.
Nota: Claude y Windsurf son ejemplos de integraciones MCP. Existen muchos otros programas y entornos compatibles, pero no es posible revisarlos todos aquí.
1. Activar la API y generar tu clave
En el back office de PrestaBlog: Herramientas > API. Activa la API, haz clic en “Generar una nueva clave” y copia la clave mostrada; no volverá a estar accesible.
2. Construir tu URL de conexión MCP
La URL de conexión sigue este formato:
https://prestablog-mcp.prestablog.workers.dev/mcp?key=YOUR_KEY&shop=https://your-shop.com
Sustituye YOUR_KEY por la clave que generaste y https://your-shop.com por la URL de tu tienda.
No lo confundas con la “URL de la API”, que es otra URL utilizada para llamadas directas.
La URL contiene tu clave API. Trátala como una contraseña: no la compartas ni la publiques.
3. Configurar con Claude
En Claude, haz clic en Customize arriba a la izquierda, luego en Connectors,
en la parte superior de la columna que aparece haz clic en el botón + y luego en Add a custom connector.
Rellena:
- Name: lo que quieras (por ejemplo: PrestaBlog API)
- URL: la URL de conexión MCP construida en el paso 2
Confirma. Claude ahora puede acceder a tu blog y crear, modificar y eliminar tus artículos y categorías directamente.
Ejemplos de lo que puedes pedirle a Claude:
- “Crea un artículo sobre zapatos de verano en la categoría Moda”
- “Lista los 10 últimos artículos publicados”
- “Modifica el título del artículo 42”
- “Crea una nueva categoría llamada Noticias con esta descripción”
- “Elimina la categoría 5”
Documentación integrada
La documentación completa está integrada en el conector MCP. Claude la consulta automáticamente; no tienes nada más que configurar.
4. Configurar con Windsurf
En Windsurf, abre el panel Cascade, haz clic en ... en la esquina superior derecha del panel, luego en el icono MCPs (el último icono en la parte inferior derecha del menú). Se abre una ventana de edición. Añade la siguiente configuración tras generar correctamente la URL (ver paso 2):
{
"mcpServers": {
"prestablog": {
"serverUrl": "https://prestablog-mcp.prestablog.workers.dev/mcp?key=YOUR_KEY&shop=https://your-shop.com"
}
}
}
Guarda. Cascade muestra 1 MCP en la parte inferior del panel, confirmando que la conexión está activa.
Ejemplos de lo que puedes pedirle a Cascade:
- “Crea un artículo sobre zapatos de verano en la categoría Moda”
- “Lista los 10 últimos artículos publicados”
- “Modifica el título del artículo 42”
- “Crea una nueva categoría llamada Noticias con esta descripción”
- “Elimina la categoría 5”
Documentación integrada
La documentación completa está integrada en el conector MCP. Cascade la consulta automáticamente; no tienes nada más que configurar.
Autenticación (REST)
Cada petición debe incluir la clave API en un header HTTP. Se aceptan dos formatos:
Authorization: Bearer YOUR_API_KEY
o
X-Api-Key: YOUR_API_KEY
Buena práctica
La clave nunca debe enviarse como parámetro de URL, para evitar que aparezca en los logs del servidor.
Bloqueo automático: tras 5 intentos fallidos de autenticación desde la misma IP, se bloquea durante 1 hora. Este plazo es configurable en los ajustes de la API.
Artículos
Listar artículos
GET /prestablog-api/articles
Devuelve la lista paginada de artículos.
Parámetros disponibles: lang (ID de idioma), page,
per_page (máx. 100), active (1 = solo publicados),
category (ID de categoría), search (búsqueda en el título),
sort (date, title, id), order (asc, desc).
curl -X GET "https://your-shop.com/prestablog-api/articles?lang=1&page=1&per_page=10" \
-H "Authorization: Bearer YOUR_KEY"
Detalle de un artículo
GET /prestablog-api/articles/{id}
Devuelve todos los datos de un artículo: campos multilingües, categorías, productos asociados, artículos relacionados y tabla de contenidos.
curl -X GET "https://your-shop.com/prestablog-api/articles/18" \
-H "Authorization: Bearer YOUR_KEY"
Crear un artículo
POST /prestablog-api/articles
Ejemplo mínimo:
curl -X POST "https://your-shop.com/prestablog-api/articles" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"languages": {
"1": {
"title": "My article",
"content": "<h2>Introduction</h2><p>Article content.</p>"
}
},
"categories": [1],
"active": true
}'
Ejemplo completo con imagen, contenido multilingüe y metadatos:
{
"languages": {
"1": {
"title": "My article",
"introduction": "Short text displayed in listings",
"content": "<h2>Section</h2><p>Full HTML content.</p>",
"meta_title": "My article - SEO Title",
"meta_description": "Search engine description",
"meta_keywords": "word1, word2",
"link_rewrite": "my-article"
},
"2": {
"title": "My article",
"introduction": "Short text displayed in listings",
"content": "<h2>Section</h2><p>Full HTML content.</p>"
}
},
"categories": [2, 5],
"active": true,
"date": "2026-06-15 09:00:00",
"enable_toc": true,
"author_id": 1,
"image": {
"url": "https://example.com/image.jpg"
}
}
Campos disponibles:
| Campo | Tipo | Descripción |
|---|---|---|
languages | object | Contenido por idioma, indexado por ID de idioma de PrestaShop. Obligatorio al crear |
languages.{id}.title | text | Título del artículo. Obligatorio para cada idioma |
languages.{id}.introduction | HTML | Texto corto mostrado en listados y al inicio del artículo |
languages.{id}.content | HTML | Cuerpo del artículo |
languages.{id}.meta_title | text | Etiqueta title SEO (máx. 500 caracteres) |
languages.{id}.meta_description | text | Meta description (máx. 500 caracteres) |
languages.{id}.meta_keywords | text | Palabras clave SEO |
languages.{id}.link_rewrite | text | Slug URL. Se genera automáticamente desde el título si falta |
categories | array of IDs | Categorías de PrestaBlog a asociar |
products | array of IDs | Productos de PrestaShop asociados |
related_articles | array of IDs | Artículos relacionados |
active | boolean | Publicación inmediata. Si falta, usa el ajuste “Activar automáticamente” |
date | datetime | Fecha de publicación en YYYY-MM-DD HH:MM:SS. Una fecha futura programa la publicación |
enable_toc | boolean | Activa la tabla de contenidos generada a partir de etiquetas h2/h3 |
author_id | integer | ID del autor de PrestaBlog |
image.url | URL | Imagen principal a descargar desde una URL remota |
id_shop | integer | ID de tienda (solo multitienda). Por defecto: tienda actual |
Modificar un artículo
PUT /prestablog-api/articles/{id}
Actualización parcial: solo se modifican los campos presentes en la petición. Los campos no enviados conservan su valor actual. Para los idiomas, solo se actualizan los incluidos en el payload.
curl -X PUT "https://your-shop.com/prestablog-api/articles/18" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"active": false,
"languages": {
"1": {
"title": "New title"
}
}
}'
Eliminar un artículo
DELETE /prestablog-api/articles/{id}
Elimina el artículo y todos los datos asociados: imágenes (todas las variantes), categorías, productos vinculados y artículos relacionados.
curl -X DELETE "https://your-shop.com/prestablog-api/articles/18" \
-H "Authorization: Bearer YOUR_KEY"
Imagen de un artículo
POST /prestablog-api/articles/{id}/image
Tres métodos disponibles según tu contexto:
URL remota (la imagen está alojada en línea):
curl -X POST "https://your-shop.com/prestablog-api/articles/18/image" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/image.jpg"}'
Archivo local (subida multipart):
curl -X POST "https://your-shop.com/prestablog-api/articles/18/image" \
-H "Authorization: Bearer YOUR_KEY" \
-F "file=@/path/to/image.jpg"
Base64 (alternativa):
Nota: base64 es muy pesado y puede resultar difícil de manejar para imágenes complejas. Cuando sea posible, prioriza la subida mediante URL remota.
curl -X POST "https://your-shop.com/prestablog-api/articles/18/image" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"base64": "/9j/4AAQSkZJRg...", "filename": "photo.jpg"}'
Via MCP (Claude)
Solo están disponibles los métodos URL y base64 a través de MCP. Para enviar un archivo local con Claude, conviértelo primero a base64.
Categorías
La API permite crear, consultar, modificar y eliminar categorías, igual que con los artículos.
Listar categorías
GET /prestablog-api/categories
Devuelve las categorías en forma de árbol por defecto.
Usa flat=1 para una lista plana,
active=1 para solo activas,
lang para el idioma.
curl -X GET "https://your-shop.com/prestablog-api/categories?lang=1" \
-H "Authorization: Bearer YOUR_KEY"
Detalle de una categoría
GET /prestablog-api/categories/{id}
Devuelve todos los datos de una categoría: campos multilingües, número de artículos y grupos de clientes asociados.
Crear una categoría
POST /prestablog-api/categories
Ejemplo mínimo:
curl -X POST "https://your-shop.com/prestablog-api/categories" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"languages": {
"1": {
"title": "News"
}
},
"active": true
}'
Ejemplo completo:
{
"languages": {
"1": {
"title": "News",
"description": "<p>All news from our shop.</p>",
"meta_title": "News - SEO Title",
"meta_description": "SEO description of the category",
"meta_keywords": "news",
"link_rewrite": "news"
},
"2": {
"title": "News",
"description": "<p>All the latest news from our shop.</p>",
"link_rewrite": "news"
}
},
"parent": 0,
"position": 1,
"active": true,
"image": {
"url": "https://example.com/category.jpg"
}
}
Campos disponibles:
| Campo | Tipo | Descripción |
|---|---|---|
languages | object | Contenido por idioma. Obligatorio al crear |
languages.{id}.title | text | Título de la categoría. Obligatorio para cada idioma |
languages.{id}.description | HTML | Descripción de la categoría |
languages.{id}.meta_title | text | Etiqueta title SEO (máx. 500 caracteres) |
languages.{id}.meta_description | text | Meta description (máx. 500 caracteres) |
languages.{id}.meta_keywords | text | Palabras clave SEO |
languages.{id}.link_rewrite | text | Slug URL. Se genera automáticamente desde el título si falta |
parent | integer | ID de la categoría padre. 0 = raíz |
position | integer | Orden de visualización |
active | boolean | Categoría visible en el front |
image.url | URL | Imagen de la categoría a descargar desde una URL remota |
Modificar una categoría
PUT /prestablog-api/categories/{id}
Actualización parcial: solo se modifican los campos presentes en la petición.
curl -X PUT "https://your-shop.com/prestablog-api/categories/1" \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"languages": {
"1": {
"title": "New category name",
"description": "<p>New description.</p>"
}
}
}'
Eliminar una categoría
DELETE /prestablog-api/categories/{id}
Elimina la categoría y todos los datos asociados: imagen, vínculos con artículos y grupos de clientes.
Los artículos asociados a esta categoría no se eliminan, pero pierden este vínculo de categoría.
curl -X DELETE "https://your-shop.com/prestablog-api/categories/1" \
-H "Authorization: Bearer YOUR_KEY"
Imagen de una categoría
POST /prestablog-api/categories/{id}/image
Los mismos tres métodos que para artículos: URL remota, archivo local (multipart) o base64.
Nota: base64 es muy pesado y puede resultar difícil de manejar para imágenes complejas. Cuando sea posible, prioriza la subida mediante URL remota.
curl -X POST "https://your-shop.com/prestablog-api/categories/1/image" \
-H "Authorization: Bearer YOUR_KEY" \
-F "file=@/path/to/category.jpg"
Autores
Los autores son de solo lectura vía API. Deben crearse en el back office de PrestaBlog.
GET /prestablog-api/authors- listar todos los autoresGET /prestablog-api/authors/{id}- detalle de un autor con biografías multilingües
curl -X GET "https://your-shop.com/prestablog-api/authors?lang=1" \
-H "Authorization: Bearer YOUR_KEY"
Códigos de error
Todas las respuestas de error siguen este formato:
{
"success": false,
"error": {
"code": "validation_error",
"message": "Mensaje de error legible",
"details": { "field": "languages.1.title" }
}
}
| Código | HTTP | Significado |
|---|---|---|
unauthorized | 401 | Clave API ausente o inválida |
api_disabled | 503 | API desactivada en la configuración |
https_required | 426 | La petición debe realizarse en HTTPS |
rate_limited | 429 | Límite de solicitudes excedido, o IP bloqueada tras fallos de autenticación |
invalid_json | 400 | Cuerpo JSON inválido o ausente |
validation_error | 422 | Valor de campo inválido (detalles en error.details) |
conflict | 409 | Conflicto de slug: ya existe un artículo o categoría con este enlace |
not_found | 404 | Recurso no encontrado |
method_not_allowed | 405 | Método HTTP no soportado para este endpoint |
payload_too_large | 413 | Cuerpo de la petición demasiado grande (límite: 10 MB) |
internal_error | 500 | Error interno del servidor |
Límite de solicitudes: en caso de superarse, la respuesta 429 incluye el header
Retry-After indicando cuántos segundos esperar antes de reintentar.
Cada respuesta también incluye los headers X-RateLimit-Limit y X-RateLimit-Remaining.
Integración Python
Para desarrolladores Python, la librería requests permite interactuar con la API en pocas líneas.
pip install requests
import requests
BASE = "https://your-shop.com/prestablog-api"
KEY = "YOUR_KEY"
headers = {"Authorization": f"Bearer {KEY}"}
# Listar artículos
r = requests.get(f"{BASE}/articles", headers=headers, params={"lang": 1, "per_page": 10})
print(r.json())
# Crear un artículo
r = requests.post(f"{BASE}/articles", headers=headers, json={
"languages": {"1": {"title": "My article", "content": "<p>Content</p>"}},
"categories": [1],
"active": True
})
print(r.json())
# Subir una imagen desde un archivo local
with open("image.jpg", "rb") as f:
r = requests.post(f"{BASE}/articles/18/image", headers=headers, files={"file": f})
print(r.json())