Everything on this blog is also available as JSON, for your own reader, a widget, or a script. It’s a set of static files rebuilt with the blog on every push and every day, so there’s no key and no sign-up, and any website can fetch it (CORS is open). GitHub Pages may cache a file for up to ten minutes.

Only published posts appear. A scheduled post joins the API with the build that publishes it.

Quick start

# every post, newest first
curl -s https://londopy.github.io/blog/api/v1/posts.json

# one post in full
curl -s https://londopy.github.io/blog/api/v1/posts/gitattributes.json

# the list, readable in a terminal
curl -s https://londopy.github.io/blog/api/v1/posts.txt

From a web page:

const res = await fetch("https://londopy.github.io/blog/api/v1/latest.json");
const { data: post } = await res.json();
console.log(post.title, post.url);

With jq:

curl -s https://londopy.github.io/blog/api/v1/posts.json |
  jq -r '.data[] | "\(.published[:10])  \(.title)"'

Endpoints

EndpointWhat you get
Discovery
/blog/api/v1/index.jsonEvery endpoint, with its URL
/blog/api/openapi.jsonThis API, described in OpenAPI 3.1
/blog/api/v1/search.jsonEvery post, page and tag, in one small file for search
Site
/blog/api/v1/site.jsonTitle, tagline, links, license and publishing schedule
Posts
/blog/api/v1/posts.jsonEvery published post, newest first
/blog/api/v1/posts/{slug}.jsonOne post in full, with its text, headings, code, links and images
{slug}: A post's slug, from posts.json
/blog/api/v1/latest.jsonThe newest post, in full
Taxonomy
/blog/api/v1/tags.jsonTags, most used first, with the posts carrying each
/blog/api/v1/tags/{tag}.jsonOne tag, with its posts
{tag}: A tag's slug, from tags.json
/blog/api/v1/archive.jsonPosts grouped by year and month
Activity
/blog/api/v1/stats.jsonThe numbers, all in one place
Feeds
/blog/api/v1/feed.jsonJSON Feed 1.1, with full post content
/blog/index.xmlRSS 2.0, with full post content
Badges
/blog/api/v1/badges/{metric}.jsonA shields.io endpoint badge
{metric}: posts, words, latest or updated
Terminal
/blog/api/v1/posts.txtThe post list, for curl

The same list is available as JSON at /blog/api/v1/index.json. The whole API is described in OpenAPI 3.1 at /blog/api/openapi.json, which you can load into Swagger UI, Postman, or a client generator.

The envelope

Every response wraps its payload the same way as my portfolio’s API:

{
  "meta": {
    "api": "londopy-blog",
    "version": "1.0.0",
    "generated": "2026-09-25T20:39:31Z",
    "self": "https://londopy.github.io/blog/api/v1/posts.json",
    "docs": "https://londopy.github.io/blog/api/"
  },
  "data": []
}

The standard formats skip the envelope, so their usual tools work on them: the JSON Feed, the shields.io badges, RSS, and posts.txt.

A post

The lists (posts.json, tags/{tag}.json) carry a summary of each post:

FieldWhat it is
slug, title, descriptionThe post’s slug, title, and my one-paragraph description
summaryThe opening of the post, as plain text
urlThe post on this blog, which is always the original
api_urlThe post in full, as JSON
published, updatedISO 8601 dates; updated comes from git
tagsEach tag’s name, slug, url and api_url
reading_time_minutes, word_countHow long it is
coverThe cover image’s url, width, height and alt

posts/{slug}.json and latest.json add the rest:

FieldWhat it is
content_htmlThe rendered post, with every link and image URL made absolute
content_textThe same post as plain text
headingsEach heading’s level, id, title, and a url straight to it
codeHow many code blocks, and in which languages
linksEvery link in the post, split into internal and external
imagesEach image’s url, width and height, and whether it’s the cover
older, newerThe posts on either side, or null
licenseCC-BY-4.0 for the writing, MIT for the code
sourceThe Markdown on GitHub, the raw file, and its history

Feeds and badges

The JSON Feed at /blog/api/v1/feed.json and the RSS feed at /blog/index.xml both carry full posts, so either works in a feed reader.

The badges plug into shields.io, for a README or anywhere else:

![blog posts](https://img.shields.io/endpoint?url=https://londopy.github.io/blog/api/v1/badges/posts.json)

The metrics are posts, words, latest (the newest post’s title) and updated (its date).

Versioning

This is version 1. Within v1, changes only add things: new fields, new endpoints. Anything that would break a client gets a new /api/v2/, and v1 stays up alongside it.

Before every deploy, scripts/check_api.py validates every response against the OpenAPI description, so what the docs promise is what you get.

Using the writing

The posts are licensed CC BY 4.0: quote them, translate them, or republish them, as long as you credit Londopy and link to the original post. Code in the posts is MIT. The whole site’s source is on GitHub.

My portfolio’s API covers everything else on londopy.github.io: the projects, pull requests, and more.