Be CMS · Docs
← Toda la documentación

Manual de uso del API de Portafolio (solo lectura)

El API de portafolio expone un endpoint de solo lectura para consultar los trabajos publicados (casos de estudio) de tu workspace. Vive en /api/portfolio y devuelve JSON.

Autenticación

  • Incluye Authorization: Bearer <token> en cada solicitud.
  • El token debe estar activo y tener permisos sobre el recurso que consultas.
  • El workspace se determina siempre desde el token; nunca lo envías en la solicitud.

Permisos

  • read: permite ejecutar peticiones GET.

Si el token está vencido, inactivo o carece del permiso read, la respuesta será 401 o 403.

Códigos de respuesta comunes

  • 200 OK: respuesta exitosa.
  • 400 Bad Request: parámetros inválidos.
  • 401 / 403: token ausente, inválido o sin permisos.
  • 404 Not Found: trabajo inexistente o no publicado.
  • 405 Method Not Allowed: se intentó un método distinto de GET.
  • 500 Internal Server Error: error no controlado en el servidor.

Operaciones — /api/portfolio

OperaciónMétodo y rutaDescripción
ListadoGET /api/portfolioTrabajos publicados, ordenados por fecha de publicación descendente. No incluye content.
DetalleGET /api/portfolio?slug=<slug>Un trabajo publicado, con content (html y htmlPreview). Cada consulta suma una vista a viewCount.

GET listado

Query params

  • category (string, opcional): devuelve solo trabajos de esa categoría. La comparación no distingue mayúsculas de minúsculas (Branding y branding son equivalentes).
  • limit (número, opcional): máximo de resultados (1–100). Por defecto 50.

Ejemplo listado básico

bash
curl "https://cms.begraffic.com/api/portfolio" \
  -H "Authorization: Bearer TU_TOKEN"

Ejemplo con filtros

bash
curl "https://cms.begraffic.com/api/portfolio?category=branding&limit=10" \
  -H "Authorization: Bearer TU_TOKEN"

Respuesta

json
{
  "count": 1,
  "items": [
    {
      "id": "rebranding-acme",
      "title": "Rebranding Acme",
      "slug": "rebranding-acme",
      "status": "published",
      "client": "Acme Corp",
      "category": "Branding",
      "projectDate": "2024-03-01T00:00:00.000Z",
      "projectUrl": "https://acme.com",
      "services": ["Identidad visual", "Diseño web"],
      "excerpt": "Renovación completa de la identidad de Acme.",
      "coverImage": {
        "previewUrl": "https://cdn.example.com/portadas/acme.jpg",
        "url": "https://cdn.example.com/portadas/acme.jpg",
        "variants": {
          "original": { "url": "https://cdn.example.com/portadas/acme.jpg", "width": 1920, "height": 1080 },
          "medium": { "url": "https://cdn.example.com/portadas/acme-md.jpg", "width": 960, "height": 540 },
          "small": { "url": "https://cdn.example.com/portadas/acme-sm.jpg", "width": 480, "height": 270 },
          "thumbnail": { "url": "https://cdn.example.com/portadas/acme-th.jpg", "width": 160, "height": 90 }
        }
      },
      "viewCount": 42,
      "publishedAt": "2024-05-01T10:00:00.000Z",
      "createdAt": "2024-04-20T09:00:00.000Z",
      "updatedAt": "2024-05-02T12:30:00.000Z"
    }
  ]
}

Notas del listado:

  • Solo se incluyen trabajos con status: published.
  • El campo content se omite en el listado para reducir el tamaño de la respuesta; solo está disponible en el endpoint de detalle.
  • coverImage siempre llega con previewUrl, url y las cuatro variantes (original, medium, small, thumbnail), cada una con su url garantizado; si el trabajo no tiene portada, es null.

GET detalle

GET /api/portfolio?slug=<slug>

Devuelve un trabajo publicado que coincida con el slug. Si existe pero no está en estado published, la respuesta será 404. Este endpoint incluye el campo content y suma una vista al contador viewCount.

Ejemplo

bash
curl "https://cms.begraffic.com/api/portfolio?slug=rebranding-acme" \
  -H "Authorization: Bearer TU_TOKEN"

Respuesta

json
{
  "item": {
    "id": "rebranding-acme",
    "title": "Rebranding Acme",
    "slug": "rebranding-acme",
    "status": "published",
    "client": "Acme Corp",
    "category": "Branding",
    "projectDate": "2024-03-01T00:00:00.000Z",
    "projectUrl": "https://acme.com",
    "services": ["Identidad visual", "Diseño web"],
    "excerpt": "Renovación completa de la identidad de Acme.",
    "coverImage": {
      "previewUrl": "https://cdn.example.com/portadas/acme.jpg",
      "url": "https://cdn.example.com/portadas/acme.jpg",
      "variants": {
        "original": { "url": "https://cdn.example.com/portadas/acme.jpg", "width": 2400, "height": 1350 },
        "medium": { "url": "https://cdn.example.com/portadas/acme-md.jpg", "width": 1200, "height": 675 },
        "small": { "url": "https://cdn.example.com/portadas/acme-sm.jpg", "width": 600, "height": 338 },
        "thumbnail": { "url": "https://cdn.example.com/portadas/acme-th.jpg", "width": 300, "height": 169 }
      }
    },
    "content": {
      "html": "<h1>Rebranding Acme</h1><p>El reto...</p>",
      "htmlPreview": "<h1>Rebranding Acme</h1>"
    },
    "viewCount": 43,
    "publishedAt": "2024-05-01T10:00:00.000Z",
    "createdAt": "2024-04-20T09:00:00.000Z",
    "updatedAt": "2024-05-02T12:30:00.000Z"
  }
}

El endpoint de detalle devuelve el contenido en content, con los campos html (la página completa del caso de estudio) y htmlPreview (un extracto para vistas previas).


Buenas prácticas

  • Normaliza slugs a minúsculas antes de consultarlos.
  • Maneja específicamente los códigos 404 (trabajo no publicado) y 405 (método no permitido) en tus integraciones.
  • Usa las variantes de coverImage según el contexto (thumbnail para listados, medium u original para la página del caso de estudio).
  • Si llegas a necesitar operaciones de escritura, deberás coordinar con el equipo para habilitar endpoints adicionales.