API
The article object
Every field on the document the Content API and the MCP read tools return: identity, body, SEO, language mirrors, recommendations, internal links and structured metadata.
Reading one article returns the stored document as it is, not a trimmed projection. That means two things: you get everything, and the exact set of fields depends on how the article was produced. A post written by hand has no internal_links; a post that was never translated has no alt_langs. Treat every field below as optional except _id, handle, lang and status.
Identity and placement#
| Field | Type | Description |
|---|---|---|
_id | string | MongoDB ObjectId. The article_id every API accepts. |
project_id | string | The project the article belongs to. |
handle | string | URL path, unique inside the project, for example guides/getting-started. This is what you route on. |
slug | string | The last segment of the handle, without the section prefix. |
url_segment_id | string | The URL section the article was filed under, so a project can run several blogs off one domain. |
lang | string | Language code, in the project's own casing -- usually uppercase, for example EN. |
status | string | draft or published. The Content API only ever returns published. |
main_article | boolean | True when this is the original an article's translations link back to. |
Content#
| Field | Type | Description |
|---|---|---|
title | string | Headline. |
md | string | The body, in Markdown. This is the field you render. |
cover | string | Cover image URL, served from the project CDN. Required before an article can be published. |
categories | string[] | Category slugs. The category filter on the feed matches against this array. |
No dashes in the body, on purpose
Reblog strips em dashes and en dashes from article text before it is stored. If your renderer normalizes typography, you do not need to handle them.
SEO and dates#
| Field | Type | Description |
|---|---|---|
meta_title | string | Title tag override. Falls back to title when absent. |
meta_description | string | Description tag. Required before an article can be published. |
date | ISO 8601 | Publication date. An article whose date is in the future is filtered out of every Content API response until that date passes. |
edit_date | ISO 8601 | Last meaningful content edit. Use it for <lastmod>, falling back to date. |
created_at | ISO 8601 | When the row was written. |
created_via | string | How the article came to exist -- the dashboard editor, an agent run, or a connected app over MCP. |
Relations#
| Field | Type | Description |
|---|---|---|
alt_langs | object[] | The same article in the project's other languages. Each entry carries _id, handle, lang, status and a main flag. Use it to render a language switcher and hreflang tags, and check status -- a translation can still be a draft. |
recommendations | object[] | Related articles chosen for this one, each with a title, handle, date and cover. Rendered as the "read next" block. |
internal_links | object[] | The internal links woven into the body, with target_id, target_handle, target_title, anchor_text and url. The links are already in md; this array exists so you can audit or visualize the mesh without parsing markdown. |
Structured metadata#
Reading one article by handle or article_id also joins in a metadata array: the structured records attached to that article whose validity window covers the current moment. Only the newest record per schema is returned, so you never have to sort or dedupe.
| Field | Type | Description |
|---|---|---|
schema_id | string | Which schema this record instantiates. |
schema_version | string | Version of that schema, so a consumer can branch on shape changes. |
payload | object | The data itself. |
effective_from | ISO 8601 | Start of the validity window. Absent means "always". |
effective_to | ISO 8601 | End of the validity window. Absent means "still valid". |
created_at | ISO 8601 | When the record was written. |
The metadata join runs on the single-article modes only. The category feed and the sitemap do not carry it.
Extra fields over MCP#
The MCP read tools return the same document plus two convenience links, so an agent (and the human reading its transcript) can go and look at what it just touched.
| Field | Type | Description |
|---|---|---|
preview_url | string | The live article on the project's own domain. |
editor_url | string | The article open in the Reblog dashboard editor. |
A full example#
{
"_id": "66f3c1a2b4d5e6f708192a3b",
"project_id": "7906b84e",
"title": "Getting started with Reblog",
"handle": "guides/getting-started",
"slug": "getting-started",
"url_segment_id": "guides",
"lang": "EN",
"status": "published",
"main_article": true,
"md": "## Why a headless blog\n\nYour site owns the rendering...",
"cover": "https://cdn.example.com/covers/getting-started.png",
"categories": ["guides"],
"meta_title": "Getting started with Reblog",
"meta_description": "How to publish your first article.",
"date": "2026-02-11T09:00:00.000Z",
"edit_date": "2026-03-02T14:22:10.000Z",
"created_at": "2026-02-10T18:41:03.000Z",
"alt_langs": [
{ "_id": "66f3c1a2b4d5e6f708192a4c", "handle": "fr/guides/demarrer", "lang": "FR", "status": "published" }
],
"recommendations": [
{ "title": "Scheduling a month of posts", "handle": "guides/scheduling", "date": "2026-02-20T09:00:00.000Z" }
],
"internal_links": [
{
"target_handle": "guides/scheduling",
"target_title": "Scheduling a month of posts",
"anchor_text": "schedule them ahead",
"url": "/articles/guides/scheduling"
}
],
"metadata": []
}