List released blogs
GET /api/consumer/blogs Returns released blogs from the workspace bound to the API key, ordered by most recently released first. Drafts, queued, in-review, and cancelled content is never returned.
Query parameters
| Name | Type | Default | Description |
|---|---|---|---|
limit | integer | 20 | Max number of items to return. Capped at 100. Values ≤ 0 or non-numeric fall back to the default. |
search | string | — | Case-insensitive substring match against renderedTitle, metaTitle, metaDescription, and renderedSlug. |
slug | string | — | Exact match on renderedSlug. Useful when you store the slug in your CMS and want to fetch on demand. |
search and slug can be combined; the response is the intersection.
Headers
| Header | Required | Description |
|---|---|---|
x-api-key | yes¹ | Your workspace API key. |
Authorization: Bearer | yes¹ | Alternative form of the same key. |
¹ Either header satisfies the requirement; both are not needed.
Response
200 OK with an items array of released blog summaries.
The list is empty ({ "items": [] }) when nothing matches — never 404.
Response shape
type ListReleasedBlogsResponse = {
items: Array<{
id: string; // stable blog identifier; use this in subsequent calls
releasedAt: string; // ISO 8601 timestamp
version: {
id: string;
versionNumber: number;
renderedTitle: string;
renderedSlug: string;
metaTitle: string | null;
metaDescription: string | null;
reviewSummary: string | null;
updatedAt: string; // ISO 8601 timestamp
assets: Array<{
id: string;
assetRole: "cover_image" | "inline_image" | "diagram" | "illustration";
publicUrl: string | null;
signedUrl: string | null;
altText: string | null;
caption: string | null;
width: number | null;
height: number | null;
}>;
};
}>;
}; The id field is the blog ID you pass to GET /api/consumer/blogs/{blogId} for the full payload.
Examples
Fetch the latest 20 blogs
curl -sS https://api.contentpilot.uixlabs.co/api/consumer/blogs
-H "x-api-key: $CONTENT_PILOT_API_KEY" Search by title fragment
curl -sS "https://api.contentpilot.uixlabs.co/api/consumer/blogs?search=resume&limit=5"
-H "x-api-key: $CONTENT_PILOT_API_KEY" Resolve a blog from its slug
curl -sS "https://api.contentpilot.uixlabs.co/api/consumer/blogs?slug=ats-optimisation-2026"
-H "x-api-key: $CONTENT_PILOT_API_KEY" {
"items": [
{
"id": "ck1234567890",
"releasedAt": "2026-05-08T09:14:00.000Z",
"version": {
"id": "cv0987654321",
"versionNumber": 1,
"renderedTitle": "How ATS optimisation actually works in 2026",
"renderedSlug": "ats-optimisation-2026",
"metaTitle": "ATS optimisation in 2026",
"metaDescription": "What today's ATS systems really score, and the practical levers that move the needle.",
"reviewSummary": "Quality recommendation: ship.",
"updatedAt": "2026-05-08T09:13:42.000Z",
"assets": [
{
"id": "ca555",
"assetRole": "cover_image",
"publicUrl": "https://content-pilot.s3.ap-south-1.amazonaws.com/ck1234567890/cover.png",
"signedUrl": null,
"altText": "Recruiter screen showing ATS scoring",
"caption": null,
"width": 1600,
"height": 900
}
]
}
}
]
} Node fetch
const response = await fetch(
"https://api.contentpilot.uixlabs.co/api/consumer/blogs?limit=10",
{ headers: { "x-api-key": process.env.CONTENT_PILOT_API_KEY! } },
);
if (!response.ok) {
throw new Error(`Failed: ${response.status}`);
}
const { items } = await response.json(); Pagination
The API currently exposes a hard cap of limit=100. If you need to mirror an
entire workspace, walk forwards by releasedAt from your last sync timestamp
client-side — every item carries releasedAt so you can dedupe locally.
A cursor-based pagination upgrade is planned; until then, treat limit as a
“give me the most recent N” tool, not a way to page deep into history.
Errors
See Errors. The two you’ll see in practice on this endpoint:
401 Unauthorized— missing or invalid API key.500 Internal Server Error— fall back and retry with backoff.