Start free. Scale as your blog grows.Get started

API reference

Posts API

Retrieve published blog posts from your ContioReach workspace.

This is the endpoint behind your blog listing, article routes, category pages, and search.

Endpoint

GEThttps://cms-api.contioreach.com/v1/blogs
curl
curl "https://cms-api.contioreach.com/v1/blogs?limit=10&minimal=true" \
  -H "X-API-Key: YOUR_API_KEY"

Query parameters

ParameterTypeDescription
pagenumberPage of results to return. Starts at 1.
limitnumberPosts per page. Defaults to 10, maximum 100.
slugstringReturn the single post matching this slug.
categorystringFilter by category slug.
authorstringFilter by author slug.
tagsstringFilter by tag slug, or several separated by commas.
searchstringFull-text search. Results are ordered by relevance instead of publish date.
minimalbooleanDefaults to true, which omits the article body. Set to false to include content.

minimal defaults to true, so a request that leaves it out gets no content field. Pass minimal=false on article pages.

Listing response

Without slug, data is an array and meta carries the pagination state.

GET /v1/blogs?limit=1&minimal=true
{
  "success": true,
  "data": [
    {
      "id": "18c366b1-cd1f-45c3-b7cf-6ebb44172177",
      "title": "How to turn off AI Overviews in Google Search?",
      "slug": "turn-off-ai-overviews-google-search",
      "excerpt": "Google won't let you disable AI Overviews outright…",
      "description": "Google won't let you disable AI Overviews outright…",
      "metaTitle": "How to Turn Off AI Overviews in Google Search (2026)",
      "coverImage": "https://contiocdn.com/…/cover.webp",
      "coverImageAlt": "Google search results page with an AI Overview panel",
      "publishedAt": "2026-08-21T06:23:29.009Z",
      "createdAt": "2026-08-21T06:19:01.152Z",
      "updatedAt": "2026-08-21T06:26:48.423Z",
      "primaryKeyword": "turn off AI Overviews in Google",
      "secondaryKeywords": ["disable AI Overviews", "Google AI Overview settings"],
      "readingTime": null,
      "authors": [ { "id": "…", "name": "Team Contioreach", "slug": "team-contioreach", "bio": "…", "image": "…", "twitter": null, "website": null } ],
      "tags": [],
      "categories": [ { "id": "…", "name": "Headless CMS", "slug": "headless-cms" } ]
    }
  ],
  "meta": {
    "page": 1,
    "limit": 1,
    "total": 64,
    "totalPages": 64,
    "hasNextPage": true,
    "hasPrevPage": false
  }
}

Single post response

When you pass slug, data is a single object rather than an array, and the response carries no meta. Handle both shapes if the same helper serves listings and article pages.

GET /v1/blogs?slug=…&minimal=false
{
  "success": true,
  "data": {
    "id": "18c366b1-cd1f-45c3-b7cf-6ebb44172177",
    "title": "How to turn off AI Overviews in Google Search?",
    "slug": "turn-off-ai-overviews-google-search",
    "excerpt": "…",
    "description": "…",
    "metaTitle": "How to Turn Off AI Overviews in Google Search (2026)",
    "coverImage": "https://contiocdn.com/…/cover.webp",
    "coverImageAlt": "Google search results page with an AI Overview panel",
    "publishedAt": "2026-08-21T06:23:29.009Z",
    "createdAt": "2026-08-21T06:19:01.152Z",
    "updatedAt": "2026-08-21T06:26:48.423Z",
    "primaryKeyword": "turn off AI Overviews in Google",
    "secondaryKeywords": ["disable AI Overviews", "Google AI Overview settings"],
    "readingTime": 13,
    "authors": [ … ],
    "tags": [ … ],
    "categories": [ … ],
    "content": "<p><strong>Quick answer:</strong> You cannot fully…</p>"
  }
}

content holds the full article body as HTML and is included only when you pass minimal=false. readingTime is calculated from content, so it is a number here and null in listing responses.

Post fields

FieldTypeDescription
idstringUnique identifier.
titlestringArticle title.
slugstringURL-safe identifier for your article route.
excerptstringShort summary for cards and listings.
descriptionstringMeta description for the article.
metaTitlestringSEO title for the page <title> and og:title. Falls back to title when not set.
coverImagestringAbsolute URL of the cover image.
coverImageAltstringAlt text for the cover image. Falls back to title when not set.
publishedAtstringISO 8601 publication timestamp.
createdAtstringISO 8601 creation timestamp.
updatedAtstringISO 8601 last-modified timestamp.
primaryKeywordstringTarget keyword for the article.
secondaryKeywordsstring[]Supporting keywords for the article. Empty array when none are set.
readingTimenumber | nullEstimated reading time in minutes. null unless minimal=false.
authorsarrayAuthor objects. See the Authors API for the field list.
categoriesarrayCategory objects with id, name, and slug.
tagsarrayTag objects with id, name, and slug.
contentstringArticle body as HTML. Only present when minimal=false.

Examples

Paginated listing

JavaScript
const params = new URLSearchParams({
  page: "1",
  limit: "12",
  minimal: "true"
});

const res = await fetch(
  `https://cms-api.contioreach.com/v1/blogs?${params}`,
  { headers: { "X-API-Key": process.env.CMS_API_KEY } }
);

const { data, meta } = await res.json();

A single article

JavaScript
const res = await fetch(
  `https://cms-api.contioreach.com/v1/blogs?slug=${slug}&minimal=false`,
  { headers: { "X-API-Key": process.env.CMS_API_KEY } }
);

const { data } = await res.json();

// data is an object here, not an array
const post = Array.isArray(data) ? data[0] : data;

Filtered by category and tags

JavaScript
const res = await fetch(
  "https://cms-api.contioreach.com/v1/blogs" +
    "?category=headless-cms&tags=seo,ai&minimal=true",
  { headers: { "X-API-Key": process.env.CMS_API_KEY } }
);

Keyword search

JavaScript
const res = await fetch(
  "https://cms-api.contioreach.com/v1/blogs?search=seo&limit=10&minimal=true",
  { headers: { "X-API-Key": process.env.CMS_API_KEY } }
);

Errors

StatusCodeMeaning
401INVALID_API_KEYThe API key is missing, incorrect, or inactive.
429USAGE_LIMIT_EXCEEDEDYour plan's monthly API calls are used up. Requests resume when the allowance resets.
404NOT_FOUNDNo post matches the requested slug.
404 response
{
  "success": false,
  "error": {
    "code": "NOT_FOUND",
    "message": "Blog not found"
  }
}

Was this page helpful?