paulobrien.dev

Blog Builder API

Blog Builder API and AI connector.

Read and change posts, pages, pictures, menus and settings from your own code, or write with Claude or ChatGPT. Every blog has both built in, running on your own Cloudflare account.

1Get started

Blog Builder is built on EmDash, the MIT-licensed blogging software, and the API is EmDash's. It lives on your own blog:

https://blog.yourdomain.co.uk/_emdash/api
  1. Open API TokensSign in to your blog's admin and open Settings › API Tokens.
  2. Make a tokenGive it a name, tick what it may do and copy it. It's shown once, and starts with ec_pat_.
  3. Send it with each requestIn an Authorization header, like this:
curl "https://blog.yourdomain.co.uk/_emdash/api/content/posts?limit=5" \
  -H "Authorization: Bearer ec_pat_••••••••••••••••••••••••••••"

2Tokens and permissions

Make a separate token for each script or app. Each one only does what you ticked, so a script that reads posts can't publish or delete them. The main ones are:

PermissionWhat it allows
content:readRead posts and pages.
content:writeMake and change posts and pages.
content:publishPublish and unpublish them.
media:read, media:writeSee and upload pictures and files.
menus:manage, taxonomies:manageChange menus, categories and tags.
settings:read, settings:manageRead and change the blog's settings.

Deleting a token in Settings › API Tokens stops it straight away.

3Every request

The full list, with every field, is in the blog's own OpenAPI description, so developers can generate code from it or open it in tools such as Postman:

https://blog.yourdomain.co.uk/_emdash/api/openapi.json
RequestWhat it does
GET /content/{collection}A page of posts or pages. The collection is posts or pages.
GET /content/{collection}/{id}One post or page in full.
POST /content/{collection}Makes a new draft.
PUT /content/{collection}/{id}Changes a post or page.
POST /content/{collection}/{id}/publishPublishes it.
GET /search?q=…Searches the blog.
GET /mediaPictures and files. Upload with POST /media.
GET /menusThe blog's menus.
GET /settingsThe blog's settings.

4Examples

Read the five newest posts

curl "https://blog.yourdomain.co.uk/_emdash/api/content/posts?limit=5" \
  -H "Authorization: Bearer $BLOG_TOKEN"

Answers come back as {"success": true, "data": …}.

In JavaScript

const res = await fetch(`${BLOG_API_URL}/content/posts?limit=5`, {
  headers: { Authorization: `Bearer ${process.env.BLOG_TOKEN}` },
});
const body = await res.json();
if (!body.success) throw new Error(body.error.message);
console.log(body.data);

5Webhooks

Blog Builder doesn't send webhooks yet. To act when you publish, ask the API for recent posts on a schedule, or use the blog's RSS feed.

6AI connector

Add your blog to Claude, ChatGPT or any MCP client at:

https://blog.yourdomain.co.uk/_emdash/api/mcp

It signs in through your blog, and you choose what it may do. Then say things like “draft a post about…” or “fix the typos in my last post”. Step by step: Connect Claude.

7Errors and limits

Anything that goes wrong comes back with a status and a code and message:

{"success": false, "error": {"code": "INSUFFICIENT_SCOPE", "message": "Token lacks required scope: content:write"}}
StatusWhat it means
400Something in the request needs fixing.
401No token, or one that has been deleted.
403The token doesn't have the permission this needs. The message says which.
404Not found.
429Too many requests. Wait a little and try again.

Keep tokens on your server or in your scripts, never in a web page.

Questions or ideas? Ask in GitHub Discussions, or open an issue for a bug.

Stay in the loop

Subscribe for updates.

Leave your email and I'll tell you when there's a new version of one of my apps, or a new project to try. Nothing else.

That didn't work. Please check your email address and try again.

One email to confirm. Unsubscribe with one click. Your address is only used for these updates.