# Artículos (todos los estados)

> Lista y resumen de los artículos de un blog de Blogenia en cualquier estado (borrador, programado, publicado…) con el permiso account:read.

Versión web: https://blogelia.com/docs/articulos-todos

La ruta [Artículos](https://blogelia.com/docs/articulos) solo devuelve lo publicado. Estas dos rutas muestran los artículos de un blog en **cualquier estado**, sin el contenido.

> **Aviso:** Exigen una clave con el permiso `account:read`. Úsalas solo desde tu servidor. Ver [Permisos](https://blogelia.com/docs/autenticacion#scopes).

## Listar artículos de cualquier estado

**`GET /blogs/{blogId}/articles/all`**: Lista paginada de los artículos de un blog, del más reciente al más antiguo por fecha de creación.

**Parámetros**

| Nombre | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `blogId` | string | Sí | Identificador del blog (en la ruta). |
| `estado` | string | No | `draft`, `pending_approval`, `scheduled`, `published`, `unpublished` o `rejected`. |
| `q` | string | No | Texto contenido en el título (hasta 80 caracteres, sin distinguir mayúsculas). |
| `desde` | string | No | Día `YYYY-MM-DD` (Europe/Madrid), incluido: solo elementos creados desde ese día. |
| `hasta` | string | No | Día `YYYY-MM-DD` (Europe/Madrid), incluido: solo elementos creados hasta ese día. No puede ser anterior a `desde`. |
| `page` | integer | No | Página, desde 1 (por defecto 1, máximo 10000). |
| `limit` | integer | No | Elementos por página, de 1 a 50 (por defecto 20). |

**Campos de la respuesta**

| Campo | Tipo | Descripción |
| --- | --- | --- |
| `data` | array | Elementos de la página. |
| `page` | integer | Página devuelta. |
| `limit` | integer | Tamaño de página aplicado. |
| `total` | integer | Total de elementos que cumplen el filtro, en todas las páginas. |
| `data[].id` | string | Identificador del artículo. |
| `data[].title` | string | Título. |
| `data[].slug` | string | Último segmento de la URL pública. |
| `data[].status` | string | Estado, uno de los valores de `estado`. |
| `data[].source` | string | `manual`, `generated` (generado a petición) o `autopilot`. |
| `data[].createdAt` | string | Fecha de creación, ISO 8601 en UTC. |
| `data[].scheduledAt` | string | Fecha programada. Solo si la tiene. |
| `data[].publishedAt` | string | Fecha de publicación. Solo si la tiene. |
| `data[].wordCount` | integer | Número de palabras. |
| `data[].requiresHumanReview` | boolean | `true` si el artículo necesita revisión humana antes de publicarse. |
| `data[].url` | string | URL pública. Solo en artículos publicados. |

> **Nota:** La lista no incluye el contenido. El texto de un artículo **publicado** se pide con `GET /articles/{id}` ([Artículos](https://blogelia.com/docs/articulos)), con un permiso `content:read`.

**Petición**

*curl*

```bash
curl "https://api.blogelia.com/v1/blogs/66f1c0a2b3c4d5e6f7a8b9c0/articles/all?estado=scheduled&limit=10" \
  -H "Authorization: Bearer $BLOGENIA_API_KEY"
```

*Node.js*

```js
const res = await fetch('https://api.blogelia.com/v1/blogs/66f1c0a2b3c4d5e6f7a8b9c0/articles/all?estado=scheduled&limit=10', {
  headers: { Authorization: 'Bearer ' + process.env.BLOGENIA_API_KEY },
});
if (!res.ok) throw new Error('HTTP ' + res.status);
const body = await res.json();
console.log(body);
```

*Python*

```python
import os
import requests

res = requests.get(
    "https://api.blogelia.com/v1/blogs/66f1c0a2b3c4d5e6f7a8b9c0/articles/all",
    params={"estado": "scheduled", "limit": 10},
    headers={"Authorization": "Bearer " + os.environ["BLOGENIA_API_KEY"]},
    timeout=10,
)
res.raise_for_status()
print(res.json())
```

**Respuesta**

```json
{
  "data": [
    {
      "id": "66f1c0a2b3c4d5e6f7a8b9c1",
      "title": "Cinco errores al reformar un baño",
      "slug": "cinco-errores-al-reformar-un-bano",
      "status": "scheduled",
      "source": "autopilot",
      "createdAt": "2026-11-02T09:00:12.000Z",
      "scheduledAt": "2026-11-05T08:00:00.000Z",
      "wordCount": 1280,
      "requiresHumanReview": false
    }
  ],
  "page": 1,
  "limit": 10,
  "total": 1
}
```

**Respuestas**

| Código | Cuándo |
| --- | --- |
| `200` | Respuesta devuelta. |
| `400` | Parámetro no válido (estado desconocido, fechas con `code` `invalid_date` o `invalid_range`, `q` demasiado largo) o parámetro desconocido. |
| `404` | El blog no existe o es de otra organización. |
| `401` | Clave ausente, no válida o revocada. |
| `403` | La clave no tiene el permiso `account:read` (`code: "insufficient_scope"`), tu plan es Free (`plan_required`) o la organización está suspendida (`ORGANIZATION_SUSPENDED`). |
| `429` | Límite del plan superado. Ver [Límites de uso](https://blogelia.com/docs/limites). |

## Resumen de artículos

**`GET /blogs/{blogId}/articles/summary`**: Recuento por estado y listas de lo que viene.

Permiso necesario: `account:read`. Solo lleva el parámetro de ruta `blogId`.

**Campos de la respuesta**

| Campo | Tipo | Descripción |
| --- | --- | --- |
| `counts` | object | Número de artículos por estado. Siempre trae los seis estados, con `0` si no hay ninguno. |
| `period` | string | Mes natural en curso (`YYYY-MM`, Europe/Madrid). |
| `publishedThisMonth` | integer | Artículos publicados en `period`. |
| `publishedPreviousMonth` | integer | Artículos publicados el mes anterior. |
| `upcomingScheduled` | array | Hasta 10 artículos programados, el más próximo primero: `[{ id, title, scheduledAt }]`. |
| `pendingApproval` | array | Hasta 10 artículos pendientes de aprobar: `[{ id, title, scheduledAt? }]`. |

**Petición**

*curl*

```bash
curl "https://api.blogelia.com/v1/blogs/66f1c0a2b3c4d5e6f7a8b9c0/articles/summary" \
  -H "Authorization: Bearer $BLOGENIA_API_KEY"
```

*Node.js*

```js
const res = await fetch('https://api.blogelia.com/v1/blogs/66f1c0a2b3c4d5e6f7a8b9c0/articles/summary', {
  headers: { Authorization: 'Bearer ' + process.env.BLOGENIA_API_KEY },
});
if (!res.ok) throw new Error('HTTP ' + res.status);
const body = await res.json();
console.log(body);
```

*Python*

```python
import os
import requests

res = requests.get(
    "https://api.blogelia.com/v1/blogs/66f1c0a2b3c4d5e6f7a8b9c0/articles/summary",
    headers={"Authorization": "Bearer " + os.environ["BLOGENIA_API_KEY"]},
    timeout=10,
)
res.raise_for_status()
print(res.json())
```

**Respuesta**

```json
{
  "counts": {
    "draft": 2,
    "pending_approval": 1,
    "scheduled": 3,
    "published": 20,
    "unpublished": 0,
    "rejected": 1
  },
  "period": "2026-11",
  "publishedThisMonth": 4,
  "publishedPreviousMonth": 8,
  "upcomingScheduled": [
    { "id": "66f1c0a2b3c4d5e6f7a8b9c1", "title": "Cinco errores al reformar un baño", "scheduledAt": "2026-11-05T08:00:00.000Z" }
  ],
  "pendingApproval": [
    { "id": "66f1c0a2b3c4d5e6f7a8b9c2", "title": "Cuándo conviene cambiar las ventanas" }
  ]
}
```

**Respuestas**

| Código | Cuándo |
| --- | --- |
| `200` | Respuesta devuelta. |
| `404` | El blog no existe o es de otra organización. |
| `401` | Clave ausente, no válida o revocada. |
| `403` | La clave no tiene el permiso `account:read` (`code: "insufficient_scope"`), tu plan es Free (`plan_required`) o la organización está suspendida (`ORGANIZATION_SUSPENDED`). |
| `429` | Límite del plan superado. Ver [Límites de uso](https://blogelia.com/docs/limites). |
