blogsforseo

Content API

The Content API is how your website reads its published posts. It's plain HTTPS and JSON, so it works with any language or framework.

Basics

  • Base URL: https://blogsforseo.com/api/v1/sites/{SITE_KEY}
  • Authentication: none. The site key is public, and the API only ever returns published posts.
  • Methods: GET only. CORS is open, so browsers can call it too. Render posts on your server anyway, so crawlers can read them.
  • Caching: responses send Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=86400. Cache on your side too.
  • Indexing: responses carry X-Robots-Tag: noindex, so the API itself never shows up in search. Your pages do.

Endpoints

Endpoint Returns
GET / Site details: { name, url, blogUrlPattern }
GET /posts?page=1&pageSize=12 { posts: PostSummary[], page, totalPages, total }, newest first. pageSize 1–50
GET /posts/{slug} One Post, or 404
GET /sitemap [{ url, lastmod }] for every live post
GET /llms.txt Your posts as a plain-text llms.txt index
GET /sitemap.xml The same, as a sitemap file, for a Sitemap: line in your robots.txt
GET /html/posts?page=1 { body, page, totalPages, total }: a page of the blog index as finished HTML
GET /html/posts/{slug} { head, body, meta }: one post as finished HTML (see below), or 404
curl https://blogsforseo.com/api/v1/sites/{SITE_KEY}/posts
curl https://blogsforseo.com/api/v1/sites/{SITE_KEY}/posts/what-is-llms-txt

HTML endpoints

The /html endpoints power the simple way. They return unstyled HTML with bfs- class names:

  • head: meta tags for <head>: title, description, canonical and Open Graph.
  • body: the whole article, ending with its application/ld+json structured data.
  • meta: the same values as head, as data: { title, description, canonical, openGraph, twitter }.

Every value is escaped, and links are http(s) only.

PostSummary

Field Type Notes
slug string Lowercase words joined by hyphens
title string
metaDescription string
shortAnswer string A direct answer of 320 characters or fewer, written to be quoted
canonicalUrl string or null Built from your post URL pattern; null until you set the pattern
heroImage { url, alt, width, height } or null
tags string[]
publishedAt ISO 8601
updatedAt ISO 8601 Changes only when what readers see changes
readingMinutes number

Post

Everything in PostSummary, plus:

Field Type Notes
metaTitle string For <title>
keyTakeaways string[]
bodyHtml string Sanitised HTML, with heading ids and up to 5 links to your other posts
bodyMarkdown string The same body, as Markdown
toc { id, text, level }[] level is 2 or 3; link to #id
faqs { question, answer }[]
sources { label, url, asOf }[] Where each fact came from, and when it was true
related { slug, title, metaDescription, canonicalUrl }[] Up to 3
author { name, type, jobTitle?, bio?, avatarUrl?, url? } type is Person or Organization
jsonLd object A ready schema.org @graph: BlogPosting, FAQPage and BreadcrumbList
version number Goes up on every published change

When you put jsonLd in a <script type="application/ld+json">, replace every < with \u003c.

Errors

Every error looks like this:

{ "error": { "code": "not_found", "message": "No published post with that slug." } }
Status Code When
400 bad_request A bad query value, such as pageSize=500
404 not_found Unknown site key or slug, or 30 days after the site's subscription ended
429 rate_limited Over 600 requests a minute for one site from one caller; wait for Retry-After
500 internal Our fault; retry shortly