Un blog editorial embebible para tu sitio, publicando desde un panel simple y consumiendo una API JSON privada desde tu propio servidor.
redacta + te da un blog que vive en tu dominio, con SEO real y datos estructurados, sin que tengas que montar un CMS. El contenido se administra en el panel de Axobit y se publica en tu sitio mediante una API REST de solo lectura, protegida por una llave privada por proyecto que se consume en servidor (nunca llega al navegador).
Esta documentación cubre la integración actual (server-side), la referencia completa de la API y el roadmap del widget por script tag que está en camino.
¿Qué necesitas para empezar?
Un proyecto activo en Axobit con el producto redacta +, una llave de API generada en el panel (sección redacta +) y un servidor capaz de ejecutar PHP para hacer las llamadas server-side.
Conceptos clave
Antes de integrar, conviene conocer estas piezas:
Concepto
Qué es
Proyecto (blog)
Un blog configurado en el panel: título, descripción, idioma, URL base y categorías.
Llave de API
Token privado rda_… por proyecto. Solo se guarda su hash en el servidor de Axobit.
Artículo publicado
Solo los artículos en estado publicado aparecen en la API.
Bloques de cuerpo
El campo cuerpo del detalle es una lista tipada de párrafos (p) e imágenes (img).
Render server-side
Tu servidor arma la interfaz con la API. El navegador nunca ve la llave.
La llave privada de cada blog se genera en el panel y solo se almacena su hash SHA-256 — ni siquiera el panel puede volver a mostrarla después de crearla.
Autenticación
Todos los endpoints requieren una llave de API válida. Se envía en el encabezado Authorization con esquema Bearer:
Cada proyecto tiene su propio blog y su propia llave.
Genera / copia la llave
Se muestra una sola vez al crearla. Guárdala en un lugar seguro: tu servidor o variables de entorno.
Nunca expongas tu llave
La API es server-to-server (sin CORS). Consume los endpoints desde tu backend con cURL, no desde el navegador. Si una llave se filtra, revócala y regenera otra desde el panel.
Tu cliente es responsable de mantener la llave en un solo archivo de configuración del lado del servidor (ver Kit de cliente).
Inicio rápido
Este ejemplo hace una llamada completa y muestra la portada del blog en tu página. Sustituye TU_LLAVE por tu llave privada.
Hoy la vía recomendada y disponible es la API server-side (esta página). El widget por script tag (embed.js) es parte del roadmap — ver Embed por script tag.
Kit de cliente reutilizable
Para no reinventar la rueda, proveemos un kit base con la portada y la vista de artículo listas para copiar. Vive en axobit.mx/redacta-kit/ y se replica por proyecto (cliente de referencia: creditoautosnuevosyseminuevos.com).
Archivos del kit
Archivo
Rol
index.php
Portada del blog (hero + grid de tarjetas + categorías + JSON-LD).
articulo.php
Vista de artículo por slug, con SEO + datos estructurados y banners publicitarios.
redacta-cliente.php
Único archivo con la config y la llave (constantes REDACTA_* + helpers cURL).
uii.css
Diseño editorial (tokens CSS en :root).
.htaccess
Enrutado limpio (portada en /, artículo en /<slug>) y bloqueo de la API.
Configuración en un solo archivo
redacta-cliente.php
// Al inicio del archivo -- única fuente de verdaddefine('REDACTA_BLOG_URL', 'https://tusitio.com'); // portada (raíz)define('REDACTA_SITIO_URL', 'https://tusitio.com'); // marca / schemadefine('REDACTA_TITULAR', 'Tu Marca');
define('REDACTA_API_URL', 'https://axobit.mx/bknd/archivosPHP/redactaApi.php');
define('REDACTA_LLAVE', 'rda_tu_llave'); // secreto
Los helpers (r_api(), r_esc(), r_head(), r_footer(), r_hojaEstilo(), r_cuerpo(), r_espacioPublicidad()) centralizan el cURL y el render, de modo que index.php y articulo.php solo arman HTML.
Rutas de despliegue
El blog vive en la raíz del dominio (/ = portada, /<slug> = artículo). No lo despliegues bajo /blog/ salvo que lo ajustes en el kit. El .htaccess bloquea ^api/redacta\.php$.
Referencia
Resumen de la API
URL base (server-to-server, en Axobit):
¡Solo GET!Base
https://axobit.mx/bknd/archivosPHP/redactaApi.php
Cada endpoint usa el parámetro de query endpoint (alias resource). Todos son solo lectura GET. La API es sin CORS y debe consumirse en servidor.
Endpoint
Método
Descripción
Query
config
GET
Configuración del blog + categorías
—
categorias
GET
Solo las categorías activas
—
listado
GET
Artículos publicados paginados
categoria, pagina, porPagina, destacado
detalle
GET
Un artículo por slug (con cuerpo)
slugobligatorio
Respuesta estándar de éxito:
200 OK
{ "ok" : true, "data": { // … según el endpoint } }
Devuelve la configuración general del blog y sus categorías activas. Es el primer endpoint a llamar para obtener urlBase, urlImagenes y el mapa de rutas.
Cada artículo del listado usa el molde de artículo (sin el campo cuerpo).
detalle
Devuelve un artículo completo por slug. Es el único endpoint que incluye el cuerpo tipado y las imágenes de cuerpo. Además registra una vista (dedupe diario por IP + UA + fecha).
El campo cuerpo es una lista tipada de bloques que tu plantilla debe recorrer: renderiza html para los de tipo p y <img> para los de tipo img. Es ideal para insertar banners publicitarios entre párrafos (el kit lo hace con r_espacioPublicidad()).
Objetos de la API
Artículo (molde)
Campo
Tipo
Descripción
idArticulo
int
Identificador único.
titulo
string
Título del artículo.
slug
string
Slug ASCII usado en la URL.
url
string
URL absoluta de publicación (urlBase + slug).
resumen
string
Resumen / descripción SEO.
etiquetas
array
Etiquetas opcionales (array de strings).
categoria
objeto|null
{ id, nombre, slug } o null.
autor
objeto
{ id, nombre }.
minLectura
int
Minutos de lectura estimados.
destacado
bool
Si el artículo está destacado.
publicadoEn
string
Fecha/hora de publicación (datetime).
actualizadoEn
string
Fecha/hora de última actualización.
portada
objeto|null
Imagen de portada: { url, alt, ancho, alto } o null.
contenido
string
HTML sin estructurar (por compatibilidad).
Bloque de cuerpo
Campo
Tipo
Descripción
tipo
"p"|"img"
Párrafo o imagen.
html
string
Solo para p: HTML del párrafo.
url
string
Solo para img: URL de la imagen.
alt
string
Solo para img: texto alternativo.
Imagen (portada / cuerpo)
Campo
Tipo
Descripción
url
string
URL absoluta del recurso (WebP optimizado).
alt
string
Texto alternativo.
ancho/alto
int
Dimensiones en píxeles (útil para evitar CLS).
Paginación
Campo
Tipo
Descripción
pagina
int
Página actual.
porPagina
int
Tamaño de página solicitado.
total
int
Total de artículos que coinciden.
paginas
int
Total de páginas (ceil(total/porPagina)).
Operaciones
Códigos de error
Los errores siempre devuelven el mismo contenedor JSON y un código estable para que tu cliente pueda reaccionar de forma programática.
HTTP
Código
Cuándo ocurre
401
unauthorized
Falta el encabezado Authorization o la llave no es válida.
403
service_unavailable
El blog no está activo, está en pausa, el proyecto no está activo o no hay suscripción vigente.
404
not_found
El slug del artículo no existe (o no está publicado).
404
unknown
El endpoint solicitado no existe.
405
method_not_allowed
Se usó un método distinto a GET (POST, PUT, etc.).
422
slug_required
Se llamó a detalle sin el slug.
429
rate_limited
Se superó el límite de peticiones por minuto.
Ejemplo de respuesta de error
401 · unauthorized
{
"ok": false,
"error": {
"code": "unauthorized",
"message": "Se requiere una llave de proyecto."
}
}
Manejo recomendado
Revisa ok antes de usar data. Si ok === false, lee error.code y muestra un mensaje amigable. Implementa re-intentos con backoff en 429, respetando Retry-After.
Rate limits
Cada llave puede hacer hasta 180 peticiones por minuto, contadas por llave + IP de origen.
Si superas el límite, la API responde 429 con código rate_limited y la cabecera Retry-After: 60.
La ventana se reinicia cada minuto (por hora UTC + minuto).
180/min es holgado para un uso típico de blog. Aplica cache del lado del cliente para evitar llamadas repetidas en cada visita.
Mejora práctica: cache
Como la API está pensada para render server-side, conviene cachear listado y detalle durante unos minutos (p. ej. en archivo o memoria) para reducir latencia y llamadas. El kit base ya lo facilita por diseño (los helpers son idempotentes).
Seguridad
Sin CORS: la API solo responde GET y no habilita CORS, así que no puede consumirse desde el navegador de un cliente. Se usa desde tu backend.
Llaves con hash: solo se almacena el hash SHA-256 de cada llave. La llave real se muestra una vez al crearla.
Bloqueo de la API: en el despliegue del cliente, el .htaccess bloquea ^api/redacta\.php$ para que la API pública nunca se exponga en el dominio del cliente.
HTTPS forzado: el dominio sirve solo por HTTPS; redirige www y HTTP a la versión canónica.
Sanitización: todo el HTML de contenido se escapa/limpia en servidor antes de devolverse al cliente.
Rendimiento
Render en servidor: arma el HTML en tu backend; el navegador recibe HTML listo e indexable. Este es el enfoque recomendado y el actual.
Imágenes WebP optimizadas: el panel optimiza las subidas a WebP y devuelve dimensiones (ancho/alto) para evitar cambios de layout (CLS).
Tipografía variable: Fraunces + Inter con display=swap, sin bloqueo de render.
Datos estructurados: la portada y el artículo emiten JSON-LD (Blog, BlogPosting, BreadcrumbList) para SEO.
Roadmap
Widget por script tag (próximamente)
Estamos preparando un embed por script tag para quienes quieren blog sin tocar backend. Con una sola etiqueta puedes montar la portada en tu HTML; la versión actual y recomendada sigue siendo la API server-side.
index.html (vista previa de la idea)
<!-- 1. El contenedor donde quieres el blog --><div id="redacta-blog"></div><!-- 2. El widget --><script src="https://axobit.mx/redacta+/embed.js"
data-project="pk_live_xxxxx"
data-mount="#redacta-blog"></script>
Estado
El widget aún no está disponible. Los endpoints públicos que hoy existen son solo lectura server-to-server. Las llaves de producción siguen el formato rda_…; las llaves públicas del widget (pk_live_…) son una idea de diseño.
Más
Changelog
v1.0
API pública inicial
Endpoints config, categorias, listado y detalle; autenticación Bearer por llave privada; rate limit de 180/min; cuerpo tipado por bloques; registro de visitas con dedupe.
ago-2026
Simplificación del kit de cliente
El blog se instala en la raíz del dominio. Config centralizada en constantes REDACTA_* en redacta-cliente.php (ya no existe redacta.config.php); hoja de estilos uii.css. Kit base en redacta-kit/.
próximamente
Widget por script tag
Embed de la portada sin backend. Detalles al liberarse.
Soporte
¿Necesitas ayuda para integrar o hay algo que no cuadra con la documentación?
Panel de Axobit: crea o configura tu blog en la sección redacta +.
Cliente de referencia:creditoautosnuevosyseminuevos.com (kit en redacta-kit/).
Guía interna:redacta-plus.md / documentacion.md del proyecto Axobit.