Documentación

Blog y catálogo

Contenido editorial

API de blog: artículos, autores, categorías y comentarios

Consume el contenido de tu blog desde un sitio headless o cualquier integración, y deja que tus visitantes comenten, valoren con estrellas y voten tus artículos. Autentícate con el token de tu workspace en el encabezado Authorization: Bearery recibe JSON listo para pintar. Crea y edita el contenido desde el panel de Be CMS.

  • Contenido (GET)
  • Comentarios (GET + POST)
  • Auth Bearer
  • JSON

Autenticación

Cómo autenticar

Crea un token en el panel de tu workspace (ver Tokens de acceso) y envíalo en cada solicitud como Authorization: Bearer <token>. El token ya identifica tu workspace, así que no se envía ningún id de página por header ni query.

Estados de publicación

  • published: Publicado y visible en la API pública.
  • Programado: published + isScheduled con scheduledFor futuro; la API lo oculta hasta su fecha.
  • draft: Borrador: no aparece en la API pública.
  • archived / hidden: Fuera del canal público; conserva el contenido.

Endpoints

Recursos disponibles

Tres recursos de lectura. Todos aceptan ?slug= (el identificador de la URL de cada uno) para traer uno específico y ?limit= para acotar la lista.

GET/api/blog/articles

Listar artículos publicados

Devuelve los artículos publicados del workspace. Admite ?limit= y ?slug= para traer uno solo. Los artículos programados con fecha futura se ocultan automáticamente.

javascript
const res = await fetch('https://cms.begraffic.com/api/blog/articles?limit=10', {
  headers: { Authorization: `Bearer ${process.env.BECMS_API_TOKEN}` },
})
const { articles } = await res.json()
console.log(articles)
  • Responde { articles: [...] }. Cada artículo trae slug, title, excerpt, status, coverImage, content ({ html, htmlPreview }) y sus fechas (createdAt, updatedAt, publishedAt) en ISO 8601.
  • Cada artículo trae también comments: { count, ratingCount, ratingAverage }: cuántos comentarios visibles tiene y su media de estrellas (null si nadie valoró). Si no se pudieron leer, llega null.
  • Usa ?slug=mi-articulo para obtener uno específico (debe estar publicado).
GET/api/blog/authors

Listar autores

Lista los autores publicados. Admite ?slug= para uno específico y ?limit=.

javascript
const res = await fetch('https://cms.begraffic.com/api/blog/authors', {
  headers: { Authorization: `Bearer ${process.env.BECMS_API_TOKEN}` },
})
const { authors } = await res.json()
  • Campos típicos: name, slug, bio, avatarUrl, status y fechas en ISO 8601.
GET/api/blog/categories

Listar categorías

Lista las categorías publicadas. Admite ?slug= y ?limit=.

javascript
const res = await fetch('https://cms.begraffic.com/api/blog/categories', {
  headers: { Authorization: `Bearer ${process.env.BECMS_API_TOKEN}` },
})
const { categories } = await res.json()
  • Campos típicos: name, slug, description, status.

Comentarios

Comentarios, estrellas y votos

Tus visitantes pueden comentar un artículo, valorarlo con estrellas, responder a un comentario y votar comentarios. Para leer basta el permiso read; para publicar y votar, el token necesita «Comentarios del blog» (blog_comments), que se marca al crearlo en API & Tokens.

Cómo funciona

  • Publicación inmediata: Un comentario se ve al instante. El negocio puede ocultarlo, volver a mostrarlo o borrarlo desde su panel (Blog → Comentarios); oculto, desaparece de la API.
  • Un nivel de respuestas: Comentario → respuestas. No se responde a una respuesta.
  • Estrellas opcionales: De 1 a 5, solo en el comentario principal. La media del artículo solo cuenta a quien valoró.
  • Respuestas oficiales: El negocio responde desde el panel; esas respuestas llegan con official: true.
  • Privacidad: El correo de quien comenta nunca sale por la API: solo lo ve el negocio.
  • Solo artículos publicados: Un borrador, un artículo oculto o uno programado a futuro responde 404 al leer y al comentar.
GET/api/blog/comments?article=<slug>

Leer los comentarios de un artículo

Devuelve los comentarios visibles de un artículo publicado, del más reciente al más antiguo, con sus respuestas dentro de cada uno. Permiso: read.

javascript
const qs = new URLSearchParams({ article: 'mi-articulo', limit: '10', visitorId })
const res = await fetch(`https://cms.begraffic.com/api/blog/comments?${qs}`, {
  headers: { Authorization: `Bearer ${process.env.BECMS_API_TOKEN}` },
})
const { stats, comments, nextCursor } = await res.json()
// stats: { count, ratingCount, ratingAverage }
// comments[i]: { id, authorName, body, rating, official, likes, dislikes, replyCount, createdAt, myVote, replies: [...] }
  • Parámetros: article (obligatorio: el slug del artículo), limit (1–30, por defecto 10), order (newest | oldest), cursor (el nextCursor de la página anterior) y visitorId (opcional: añade myVote a cada comentario).
  • Cada comentario trae hasta 50 respuestas en replies, de la más antigua a la más reciente; replyCount tiene siempre el total real.
  • official: true marca las respuestas que el negocio escribe desde su panel. Píntalas distinto.
POST/api/blog/comments

Publicar un comentario o una respuesta

Publica al instante un comentario (con estrellas opcionales) o una respuesta a un comentario principal. Permiso: blog_comments.

javascript
const res = await fetch('https://cms.begraffic.com/api/blog/comments', {
  method: 'POST',
  headers: { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    article: 'mi-articulo',
    authorName: 'Ana García',
    authorEmail: 'ana@correo.com', // opcional, nunca se publica
    body: 'Muy útil, gracias.',
    rating: 5,          // opcional, 1–5, solo en comentarios principales
    parentId: null,     // el id de un comentario principal para responderle
  }),
})
const data = await res.json()
if (!res.ok) throw new Error(data.error) // mensaje listo para enseñar
const { comment } = data
  • Un solo nivel: se responde a un comentario principal; responder a una respuesta devuelve 400.
  • Una respuesta no lleva estrellas (400). authorName admite hasta 80 caracteres y body hasta 2000.
  • El texto se guarda sin etiquetas HTML. Aun así, píntalo SIEMPRE como texto (textContent), nunca con innerHTML.
POST/api/blog/comments/vote

Votar un comentario

Me gusta / no me gusta de un comentario o una respuesta. Un voto por visitante y comentario: repetirlo no suma, cambiarlo lo mueve y "none" lo quita. Permiso: blog_comments.

javascript
// Un id estable por visitante: el de tu usuario si hay login; si no, uno aleatorio guardado.
let visitorId = localStorage.getItem('becms_visitor')
if (!visitorId) { visitorId = crypto.randomUUID(); localStorage.setItem('becms_visitor', visitorId) }

const res = await fetch('https://cms.begraffic.com/api/blog/comments/vote', {
  method: 'POST',
  headers: { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ commentId, visitorId, vote: 'like' }), // 'like' | 'dislike' | 'none'
})
const { likes, dislikes, myVote } = await res.json()
  • visitorId: de 8 a 200 caracteres. Guardamos solo su hash.
  • Quien borre los datos de su navegador puede volver a votar: sirve para evitar el voto repetido, no como identificación.

¿Desde el servidor o desde el navegador?

Lo más seguro es llamar desde el servidor de tu web: el token no sale nunca al navegador (todas tus visitas comparten entonces el límite de 10 comentarios y 60 votos por minuto de su IP). Si prefieres llamar desde el navegador, usa un token dedicado con solo read y blog_comments: cualquiera puede copiarlo, y así lo único que podría hacer es leer y comentar como un visitante más.

Notas

Bueno saber

Lectura y comentarios

Artículos, autores y categorías son de solo lectura (se crean desde el panel). Lo único que se escribe por la API son los comentarios y votos de tus visitantes, con el permiso blog_comments.

Códigos de estado

400 datos inválidos (con un mensaje listo para enseñar) · 401 token ausente o inválido · 403 sin permiso o workspace suspendido · 404 recurso no encontrado · 429 demasiadas solicitudes (más de 10 comentarios o 60 votos por minuto desde la misma IP).

Consumo

Cada llamada cuenta contra el consumo (llamadas y ancho de banda) del plan de tu workspace. Las URLs de imágenes se reescriben para servirse por el proxy de assets.

Referencia completa

Este es un ejemplo del recurso Blog. La referencia de todos los recursos (Podcast, Cursos, Galería, Calendario, FAQs, Testimonios, Aportes y Reservas) está en la documentación de la API.