Public API — Articles
List and read your articles over the authenticated public API, including everything needed to build a sitemap on your own domain.
Public API — Articles
The public API lets your own site (custom CMS integration) list and read the articles Daily Blog Post generated for your organization.
Connecting a site for the first time? Start with the step-by-step API setup brief: it orders these endpoints into four steps with an acceptance checklist, and can be handed to an AI coding agent. This page is the reference.
Authentication
Every request needs your organization API token (create it in
Integrations → Public API), sent in the X-API-Key header:
curl -H "X-API-Key: $DBP_API_TOKEN" \
"https://dailyblogpost.app/api/public/articles"Authorization: Bearer is not accepted on these routes (it is the header
of the MCP server only): a request without X-API-Key answers 401.
List articles
GET /api/public/articles
| Query parameter | Description |
|---|---|
status | Defaults to published: without it you receive the articles published from Daily Blog Post, plus the ones already sent to your site by the API integration that your site has not confirmed yet (so a static site can render them, then confirm them). Those articles carry their real status (usually generated), so do not filter on status === "published" on your side. status=published returns published articles only (sitemaps). Any other value answers 400: this API serves what you published from Daily Blog Post, nothing else — articles are written and reviewed in the app or through the MCP server, never previewed through this API. |
page / limit | Pagination. limit is capped at 100. |
locale | Filter by article language (e.g. fr). |
q | Search in titles. |
updated_since | ISO date — only articles updated after it. Handy for incremental rebuilds. |
sort / order | createdAt (default), updatedAt or publishedAt / asc or desc. |
Each article in the response includes (non-exhaustive):
slug— the SEO slug, to build the URL on your domaintitle,metaTitle,metaDescription,content(HTML),keywordscoverImageUrl,featuredImagepublishedAt,updatedAt,createdAt(ISO dates)locale,status
Single article: GET /api/public/articles/{id} or
GET /api/public/articles/by-slug/{slug}. Same rule: a published article,
or one sent to your site and awaiting your confirmation; 404 otherwise.
Any status other than published answers 400.
Why published only? A site that builds its blog from this API would otherwise show an article the moment Plume generated it, before anyone in your team read it. Publishing from Daily Blog Post is what makes an article appear here.
Static sites — when to rebuild
Reading the API never notifies your site: a statically generated blog (Astro, Next.js export, Hugo, Eleventy…) shows a newly published article only after its next build. Two ways to make sure that build happens:
- Rebuild on a schedule (for example every hour) and pass
updated_sinceso the build can stop early when nothing changed since the last one. - Let publishing trigger the build: point the API integration
at your deploy hook or revalidation URL. It receives
dailyblogpost.publisheach time an article is sent to your site; answer2xx, and returnremote_urlonce the page exists. Until then the article stays unpublished on our side and is not counted as delivered, but the read API already serves it to you by default, so your build can render it and then confirm it.
Either way, confirm each article once it is online with the acknowledgement call: that is what turns "received" into "delivered" in your dashboard.
Recipe — sitemap for articles published via the API
If your site consumes Daily Blog Post through the API on your own domain, expose a dedicated sub-sitemap built from the list endpoint, then reference it from your main sitemap index:
- Fetch all published articles (paginate with
limit=100):GET /api/public/articles?status=published&sort=publishedAt&order=asc&limit=100&page=1 - For each article, emit one
<url>entry:<loc>— the article URL on your domain, built fromslug(e.g.https://example.com/blog/{slug})<lastmod>—updatedAt
- Serve the result as e.g.
https://example.com/sitemap-blog.xmland add it to your sitemap index:
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap><loc>https://example.com/sitemap-main.xml</loc></sitemap>
<sitemap><loc>https://example.com/sitemap-blog.xml</loc></sitemap>
</sitemapindex>Rebuild the sub-sitemap on a schedule (or on your deploy hook) and use
updated_since to detect changes cheaply between rebuilds.
Push mode — the API integration
Instead of pulling, you can let Daily Blog Post push each article to your site the moment it is published: configure an API integration (Integrations → API) with your endpoint URL and an optional auth header.
Your endpoint receives a JSON POST for two event types, and must answer
with a 2xx status:
{ "type": "dailyblogpost.test", "sent_at": "…" }— sent by the Test connection button. No article attached: just answer200so the integration can be validated and activated.{ "type": "dailyblogpost.publish", "sent_at": "…", "article": { "id", "title", "content", "seo_title", "seo_description", "seo_slug", "keywords", "cover_image_url", "cover_image_alt" } }— sent for each article pushed to your site. Answer with{ "remote_id": "…", "remote_url": "…" }so Daily Blog Post can record where the article lives on your site and mark it published. The push follows a redirect only between your apex domain and itswww.variant, and only on307/308(a301/302on aPOSTis refused): point the endpoint at the final host.
Handle the two types explicitly (early-return 200 on
dailyblogpost.test), and upsert on article.id so a re-publish updates
the existing entry instead of duplicating it.
What your answer proves
| Your 2xx answer | Status recorded in Daily Blog Post |
|---|---|
Body with remote_url (or url, permalink, link) and/or remote_id (or id, itemId, item_id) — first non-empty field wins | Published — counted as delivered, the URL is shown in the dashboard. |
| Empty body, or a body without those fields | Received, not confirmed — the article stays unpublished in the dashboard (the Publish button can send it again; upsert on article.id makes that harmless) and no article.published webhook fires. It becomes published and delivered when a later push returns the URL, your site acknowledges it with remote_url, or the weekly check through your read endpoint finds it online. A bare 2xx to a re-push of an article you already confirmed keeps it delivered. |
| Non-2xx | Failed — shown with the HTTP status on the integration card. Background publications are retried up to two more times; a manual publish is not retried until you click Publish again. |
A 200 only proves that your endpoint received the payload. Static sites
must also trigger a rebuild (deploy hook, CI job, revalidation) when they
receive dailyblogpost.publish, otherwise the article is stored but never
rendered — the dashboard cannot detect this unless you expose a read endpoint.
Acknowledge a publication (pull mode)
If your site pulls articles and publishes them itself, tell Daily Blog Post once an article is live, so it is marked published in the app:
POST /api/public/articles/{id}/publish (scope publish:write)
{ "provider": "api", "remote_id": "123", "remote_url": "https://example.com/blog/my-article" }remote_url is required for a published acknowledgement: it is the
public http(s) address of the article on your site, the only thing that
lets Daily Blog Post show, check and count the article as delivered. Without
it the call answers 422 with code: "remote_url_required" and nothing is
recorded. Optional fields: remote_id, status (published by default, or
pending / failed with an error_message), request_payload,
response_payload.
A published acknowledgement goes through the same checks as the Publish
button in the app. It answers 422 with code and issues when the
article cannot be published: invalid_status (archived, consolidated or
still generating), missing_content, missing_seo_slug or
language_mismatch (article not in the language of your site), and
remote_url_required when the address is missing (whatever the provider
you acknowledge for). Only acknowledge articles you read from this API's
default listing: it already applies these checks.
/api/public/articles/unpublished is reserved to the WordPress plugin and
answers 403 (wordpress_plugin_only) to any other caller.