Categorías

Las categorías permiten organizar los posts en grupos temáticos con estructura jerárquica. Una categoría puede contener subcategorías, y estas a su vez más subcategorías. Úsalas para construir menús de navegación del blog, páginas de categoría con sus posts filtrados, o secciones temáticas en tu sitio. La API devuelve el árbol completo en una sola petición.

GET /categories — Árbol de categorías

Devuelve todas las categorías de una web organizadas en árbol. No hay paginación: la respuesta siempre incluye el árbol completo. Esto es intencional — los árboles de categorías suelen ser pequeños (decenas de nodos como máximo) y tenerlos todos de una vez simplifica enormemente la lógica del frontend para construir menús y navegación. Las categorías raíz tienen parent_id: null; sus hijas se anidan en el campo children.

Parámetro Tipo Requerido Descripción
web_id string ID de la web
lang string No Código de idioma
curl "https://tu-panel.com/api/v1/categories?web_id=abc-123&lang=es" \
  -H "X-API-Key: tu-api-key"
Respuesta esperada 200 OK
{
  "data": [
    {
      "id": "cat-001",
      "nombre": "Tecnología",
      "slug": "tecnologia",
      "description": null,
      "parent_id": null,
      "children": [
        {
          "id": "cat-002",
          "nombre": "APIs",
          "slug": "apis",
          "description": "Todo sobre APIs REST y GraphQL",
          "parent_id": "cat-001",
          "children": []
        }
      ]
    },
    {
      "id": "cat-003",
      "nombre": "Diseño",
      "slug": "diseno",
      "description": null,
      "parent_id": null,
      "children": []
    }
  ]
}

Campos de respuesta

Campo Tipo Descripción
idUUIDIdentificador único
nombrestringNombre de la categoría
slugstringURL amigable
descriptionstring | nullDescripción opcional
parent_idUUID | nullID del padre. null si es categoría raíz
childrenarraySubcategorías hijas (misma estructura, recursiva)

La estructura de children es recursiva: cada elemento tiene exactamente los mismos campos que la categoría padre, incluyendo su propio children. Para recorrer el árbol completo usa una función recursiva:

// Aplanar el árbol en un array plano de categorías
function flattenCategories(categories, depth = 0) {
  return categories.reduce((acc, cat) => {
    acc.push({ ...cat, depth, children: undefined })
    if (cat.children && cat.children.length > 0) {
      acc.push(...flattenCategories(cat.children, depth + 1))
    }
    return acc
  }, [])
}

// Renderizar como menú anidado (ejemplo con HTML)
function renderMenu(categories) {
  if (!categories || categories.length === 0) return ''
  const items = categories.map(cat => {
    const sub = cat.children?.length > 0
      ? `<ul>${renderMenu(cat.children)}</ul>`
      : ''
    return `<li><a href="/blog/categoria/${cat.slug}">${cat.nombre}</a>${sub}</li>`
  })
  return items.join('')
}

Casos de uso

Menú de navegación del blog. Llama a este endpoint una vez en el build (o en un componente de servidor) y usa el resultado para renderizar un menú con soporte de desplegables para subcategorías. Con el árbol ya estructurado no necesitas ninguna lógica adicional de agrupación.

Página /categoria/[slug]. Genera una ruta estática por cada categoría usando sus slugs. En la ruta, usa el parámetro category del endpoint de posts para obtener los posts filtrados: /api/v1/posts?web_id=...&category=tecnologia. Combina ambas llamadas para tener el nombre de la categoría y sus posts en la misma página.

Sección "Ver más en [categoría]". Al final de cada post, muestra posts relacionados de la misma categoría. Tienes el slug de la categoría en el campo categories del post — úsalo directamente en el filtro.

Breadcrumbs dinámicos. Con el campo parent_id puedes reconstruir la ruta de migas de pan desde cualquier categoría hasta la raíz recorriendo el árbol hacia arriba.

Consejos y buenas prácticas

  • Cachea el árbol de categorías agresivamente — cambia muy poco comparado con los posts. Un TTL de varias horas o invalidación manual cuando se modifica una categoría es suficiente.
  • Usa siempre el slug para construir las URLs de categoría, nunca el id. El slug está pensado para aparecer en URLs y es legible para el usuario y los buscadores.
  • Verifica que children existe y tiene elementos antes de iterar sobre él. Aunque la API siempre devuelve el campo, puede ser un array vacío [].
  • Si usas Astro con generación estática, llama a este endpoint dentro de getStaticPaths para generar todas las páginas de categoría en tiempo de build sin peticiones en runtime.

Errores frecuentes

Código Causa probable Solución
401 API Key no incluida o incorrecta Verifica el header X-API-Key y que la clave está activa en el panel
400 Falta el parámetro web_id Incluye web_id en la query string
200 con data: [] La web no tiene categorías creadas Crea al menos una categoría desde el panel antes de llamar al endpoint

Ver también

  • Posts — filtra posts por categoría con el parámetro category
  • Etiquetas — alternativa plana para organizar contenido transversalmente