blawgy-com Public content API
Published posts for headless frontends and static builds. No key; callable from browsers; cacheable.
Published posts for headless frontends and static builds. No key; callable from browsers; cacheable.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/blawgy-com:blawgy-com-public-content-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Blawgy Public content API
version: 1.0.0
description: 'The Blawgy API: everything the Blawgy dashboard and MCP server can do, over HTTPS. Every endpoint is also an MCP tool (`x-mcp-tool`); both transports share keys, site scoping, plan gating, rate limits and the audit log.
**Authentication.** `Authorization: Bearer blk_live_...` with an API key from Settings > Account > AI agents in the Blawgy dashboard (or an OAuth access token issued for this host). Keys are server-side only: there is no CORS on /v1, except the keyless public content endpoints under `/public`.
**Arguments.** GET endpoints take theirs as query parameters; POST, PATCH, PUT and DELETE take a JSON body (`Content-Type: application/json`), and their query string carries only `dryRun`. Unknown arguments are a 400, never silently dropped.
**Errors.** Every non-2xx answer is `{ "error": { "code", "message", "details"?, "requestId" } }`. Every response carries `Request-Id`.
**Pagination.** Lists answer `{ data, nextCursor, total? }` and take `?limit=` and `?cursor=` (the previous page''s `nextCursor`). `limit` is capped per endpoint (never above 200); a larger value is clamped to the cap.
**Idempotency.** Send `Idempotency-Key` on POST, PATCH, PUT or DELETE to make a retry safe for 24 hours: the same key and request replays the stored answer (`Idempotent-Replayed: true`); the same key with a different request is a 422.
**Dry runs.** `?dryRun=true` on any write runs every gate (auth, scope, plan, validation) and returns a one-line summary without doing anything.
**Rate limits.** 240 calls a minute and 6,000 a day per key, shared with MCP. Responses carry `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`; a 429 adds `Retry-After`. The public content endpoints need no key and are limited per client IP instead.
**Async work.** Research, writing, scans and syncs return as soon as the job is queued; poll `GET /sites/{site}/jobs/{kind}`.
**Versioning.** `/v1` is frozen for breaking changes; additive changes ship freely.'
termsOfService: https://blawgy.com/terms
contact:
url: https://blawgy.com/developers
servers:
- url: https://app.blawgy.com/v1
security:
- bearerAuth: []
tags:
- name: Public content
description: Published posts for headless frontends and static builds. No key; callable from browsers; cacheable.
paths:
/public/sites/{site}/posts:
get:
operationId: list_public_posts
summary: List published posts
description: 'Published posts on a Blawgy site, newest first, 20 a page. Each slug appears once (its freshest version); drafts, scheduled and held articles never appear. Bodies are left out unless `include=content`. No key: the content is public, so a browser may call it directly (CORS for any origin, no credentials). Answers carry a weak `ETag`; send it back as `If-None-Match` and an unchanged answer is a 304 with no body. `Cache-Control: public, max-age=60, stale-while-revalidate=300`. Rate limited per client IP (a 429 says when to retry in `Retry-After`).'
tags:
- Public content
security: []
x-paged: true
parameters:
- name: site
in: path
required: true
schema:
type: string
description: The site, as its domain (example.com).
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 100
default: 20
description: 'Posts per page: 20 by default, at most 100 (50 with include=content). Values above the maximum are clamped to it.'
- name: cursor
in: query
required: false
schema:
type: string
description: The previous page's nextCursor.
- name: include
in: query
required: false
schema:
type: string
enum:
- content
description: 'content: add blogContent and articleSummary to every post.'
responses:
'200':
description: A page of published posts.
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
ETag:
$ref: '#/components/headers/ETag'
Cache-Control:
$ref: '#/components/headers/Cache-Control'
content:
application/json:
schema:
type: object
description: One page. Pass nextCursor as ?cursor= for the next one; null means this was the last page.
properties:
data:
type: array
items:
$ref: '#/components/schemas/PublicPost'
nextCursor:
type:
- string
- 'null'
total:
type: integer
description: Published posts on the site (each slug once).
required:
- data
- nextCursor
- total
'304':
description: 'Not modified: the copy you hold (If-None-Match) is current. No body.'
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
ETag:
$ref: '#/components/headers/ETag'
Cache-Control:
$ref: '#/components/headers/Cache-Control'
'400':
$ref: '#/components/responses/400'
'404':
$ref: '#/components/responses/404'
'429':
$ref: '#/components/responses/429'
/public/sites/{site}/posts/{slugOrId}:
get:
operationId: get_public_post
summary: Get a published post
description: 'One published post on a Blawgy site by its slug (the freshest version, the one the list shows) or its id, with its body. No key: the content is public, so a browser may call it directly (CORS for any origin, no credentials). Answers carry a weak `ETag`; send it back as `If-None-Match` and an unchanged answer is a 304 with no body. `Cache-Control: public, max-age=60, stale-while-revalidate=300`. Rate limited per client IP (a 429 says when to retry in `Retry-After`).'
tags:
- Public content
security: []
parameters:
- name: site
in: path
required: true
schema:
type: string
description: The site, as its domain (example.com).
- name: slugOrId
in: path
required: true
schema:
type: string
description: The post's slug, or its id.
responses:
'200':
description: The post.
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
ETag:
$ref: '#/components/headers/ETag'
Cache-Control:
$ref: '#/components/headers/Cache-Control'
content:
application/json:
schema:
$ref: '#/components/schemas/PublicPost'
'304':
description: 'Not modified: the copy you hold (If-None-Match) is current. No body.'
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
ETag:
$ref: '#/components/headers/ETag'
Cache-Control:
$ref: '#/components/headers/Cache-Control'
'400':
$ref: '#/components/responses/400'
'404':
$ref: '#/components/responses/404'
'429':
$ref: '#/components/responses/429'
components:
responses:
'429':
description: Rate limited; `Retry-After` says when to try again.
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: 'Not found: the route, the site (`site_not_found`) or the thing inside it.'
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'400':
description: The request is malformed or the arguments failed validation (`details.issues` lists them).
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
headers:
Request-Id:
schema:
type: string
description: Identifies this request in our logs and audit trail. Quote it to support.
Cache-Control:
schema:
type: string
description: 'How long a browser or CDN may reuse the answer (public content: `public, max-age=60, stale-while-revalidate=300`).'
ETag:
schema:
type: string
description: A weak validator for this answer (public content). Send it back as If-None-Match.
schemas:
PublicPost:
type: object
description: A published post. Fields without a value are left out.
required:
- id
properties:
id:
type: string
description: The post id. Works as {slugOrId}.
title:
type: string
blogTitle:
type: string
description: The title as written on the article.
slug:
type: string
blogContent:
type: string
description: The article body (HTML). On the list only with include=content.
articleSummary:
type: string
description: A short summary of the article. On the list only with include=content.
metaDescription:
type: string
metaKeywords:
type: string
keywords:
description: The keywords the article targets (usually an array of strings).
resources:
description: Sources and references the article cites.
imageUrl:
type: string
description: The featured image.
imageDescription:
type: string
description: Alt text for the featured image.
publishDate:
type: string
format: date-time
lastUpdated:
type: string
format: date-time
description: When the content last changed.
published:
type: boolean
blogStatus:
type: string
enum:
- published
category:
type: string
url:
type: string
description: The live URL, once known.
publishedUrl:
type: string
description: Same as url.
additionalProperties: false
Error:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
- requestId
properties:
code:
type: string
description: Stable machine-readable reason (site_not_found, invalid_request, upgrade_required, rate_limited, ...).
message:
type: string
details:
type: object
additionalProperties: true
description: 'Extra context; validation errors carry `issues: [{ path, code, message }]`.'
requestId:
type: string
description: Same as the Request-Id header.
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: blk_live_... API key or OAuth access token
description: An API key from Settings > Account > AI agents in the Blawgy dashboard. Read keys may only call GET endpoints; keys scoped to specific sites cannot reach other sites or change the account.