Connect your site — API setup brief
The step-by-step brief to connect a custom site (Next.js, Astro, Nuxt, Hugo, home-grown CMS) to Daily Blog Post. Readable by a developer, executable by an AI coding agent.
Connect your site to Daily Blog Post — setup brief
This page is the complete brief to connect a custom site to Daily Blog Post. It is written for two readers at once:
- a developer who follows the steps by hand;
- an AI coding agent (Claude Code, Cursor, Codex…) that receives this page and an API token, and does the work.
Raw Markdown of this page, to paste or to fetch from an agent:
https://dailyblogpost.app/docs/en/api-setup.mdx. An agent connected to the
Daily Blog Post MCP server gets the same text with the
get_api_setup_guide tool.
Not for you if your site runs on WordPress (use the plugin), Shopify or Webflow (native integrations in Integrations): those channels need none of this.
What you get at the end
- A
/bloglisting and one page per article, built from the articles Daily Blog Post generated and you published. - Articles in your sitemap.
- Optional: your site rebuilds the moment you publish (steps 3).
- Optional: each article counted as delivered in your dashboard, with its public URL (step 4).
Step 0 — Pick your path
| You want | Do steps | Effort |
|---|---|---|
| A blog that reads Daily Blog Post and rebuilds on a schedule | 1 → 2 | one afternoon |
| …that also rebuilds the moment you publish | 1 → 2 → 3 | + 30 minutes |
| …and a dashboard that shows every article as delivered, with its URL | 1 → 2 → 3 → 4 | + 30 minutes |
Steps 1 and 2 are enough for a working blog. Steps 3 and 4 are independent of each other.
Step 1 — Get an API token
- In the app, open Integrations, find the Public API card and click Configure Public API.
- Create a token. Give it the name of the site (e.g. "Site Next.js
production"). Tick the permission
articles:read. Tickpublish:writeonly if you plan to do step 4. - Copy the token: it is shown once.
Rules for the token:
- Store it as an environment variable on the server or in the build, e.g.
DBP_API_TOKEN. Never ship it in browser code. - Send it in the
X-API-Keyheader.Authorization: Beareris not accepted on the public API (it is the MCP server's header). - Base URL:
https://dailyblogpost.app.
curl -H "X-API-Key: $DBP_API_TOKEN" \
"https://dailyblogpost.app/api/public/articles?limit=100&page=1"A 401 means the header is missing or the token was revoked.
Step 2 — Read the articles and build the pages
2a. List
GET /api/public/articles?limit=100&page=1 (then page=2… until
page > totalPages).
{
"articles": [
{
"id": "7f1c…",
"slug": "how-to-choose-a-standing-desk",
"title": "How to choose a standing desk",
"metaTitle": "How to choose a standing desk (2026 guide)",
"metaDescription": "Height range, stability, budget: the five criteria…",
"excerpt": "Height range, stability, budget: the five criteria…",
"content": "<h2>…</h2><p>…</p>",
"coverImageUrl": "https://…/cover.webp",
"keywords": ["standing desk", "ergonomic desk"],
"locale": "en",
"status": "published",
"publishedAt": "2026-10-02T08:00:00.000Z",
"updatedAt": "2026-10-03T09:12:41.000Z",
"createdAt": "2026-10-01T17:40:12.000Z"
}
],
"page": 1,
"limit": 100,
"total": 1,
"totalPages": 1
}Other useful parameters: locale=fr (one language), updated_since=<ISO date> (only what changed, for incremental builds), sort=publishedAt&order=asc.
2b. What the default list contains — read this twice
Without a status parameter you receive:
- the articles published from Daily Blog Post;
- plus the articles already sent to your site by the API integration of
step 3 that your site has not confirmed yet. Those carry their real
status(usuallygenerated).
So: do not filter on status === "published" on your side. If you do,
an article sent to your site is never rendered, so it is never confirmed, so
it never becomes published: a loop with no exit. Render everything the
default list returns.
Only the sitemap should use ?status=published (see 2e). Any other
status value answers 400: this API serves what you published, it never
previews an article that is still being written.
2c. One page per article
| Page element | Field | Rule |
|---|---|---|
| URL | slug | https://your-site.com/blog/{slug}. Keep this pattern stable: it is what you will confirm in step 4. |
<title> | metaTitle | falls back to title server-side, always present |
<meta name="description"> | metaDescription | may be empty |
| H1 | title | |
| Body | content | HTML produced by Daily Blog Post (headings, paragraphs, lists, links, images). Render it as HTML, do not escape it. |
| Cover image | coverImageUrl | may be null; alt = title |
| Dates | publishedAt, updatedAt | ISO strings; publishedAt is null for an article sent to your site and not confirmed yet — show createdAt then |
| Language | locale | set <html lang> or the page language accordingly |
Store or key everything on id: a re-publish of the same article must
update the existing page, never create a second one.
2d. Single article
GET /api/public/articles/{id} or GET /api/public/articles/by-slug/{slug}.
Same content rule as the list: published, or sent to your site and not
confirmed yet. 404 otherwise.
2e. Sitemap
Expose a sub-sitemap built from GET /api/public/articles?status=published&sort=publishedAt&order=asc&limit=100
and reference it from your sitemap index:
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap><loc>https://your-site.com/sitemap-main.xml</loc></sitemap>
<sitemap><loc>https://your-site.com/sitemap-blog.xml</loc></sitemap>
</sitemapindex>One <url> per article: <loc> from slug, <lastmod> from updatedAt.
2f. Rebuild on a schedule
A static site shows a new article only after its next build. Rebuild at least
every hour (CI schedule, host cron). On each build, fetch the full default
list and compare its ids with the pages you have: a new id is a page to
create, a missing one a page to remove (archived on our side). Do not
rely on updated_since alone to decide whether anything changed: an article
handed to your site by step 3 keeps its old updatedAt, and an archived
article leaves the list without ever appearing in updated_since. Use
updated_since only to limit how much content you re-download.
Checkpoint before step 3: curl with the token returns 200 and JSON; a
page exists for every article of the list; the token is server-side only;
the sitemap lists the published articles.
Step 3 (optional) — Rebuild the moment you publish
Instead of waiting for the next scheduled build, let Daily Blog Post call your site when you click Publish.
- Have an HTTPS URL that triggers a rebuild: your host's deploy hook (Vercel, Netlify, Cloudflare Pages, Coolify…), a CI dispatch URL, or a revalidation route you write.
- In the app, Integrations → API card: paste that URL as Endpoint
URL, add an authentication header if your hook needs one, Save, then
click Test. The Test sends
{ "type": "dailyblogpost.test" }; any2xxpasses. - From now on every Publish sends a JSON
POSTto that URL:
{
"type": "dailyblogpost.publish",
"sent_at": "2026-10-09T10:00:00.000Z",
"article": {
"id": "7f1c…",
"title": "…",
"content": "<h2>…</h2>",
"seo_title": "…",
"seo_description": "…",
"seo_slug": "how-to-choose-a-standing-desk",
"keywords": ["…"],
"cover_image_url": "https://…",
"cover_image_alt": "…"
}
}Rules:
- Answer
2xxquickly; do the rebuild asynchronously if it is slow. - Handle both
typevalues. Ondailyblogpost.test, return200and stop. - Point the URL at the final host (
www.or apex, whichever answers). The push follows a redirect only between the apex and itswww.variant, and only on307/308: a301or302on aPOSTis refused and the publication is recorded as failed. - You do not need to store the payload: the article is already in the default list of step 2 the moment it is sent. Your rebuild reads it from there.
After a bare 2xx the dashboard shows the article as received, not
confirmed, and the article stays unpublished on our side until step 4
confirms it. If you skip step 4, that is the normal, stable state for a
read-only site.
Step 4 (optional) — Confirm each article with its URL
Confirmation is what turns "received" into delivered in the dashboard,
publishes the article on our side and fires the article.published signal.
It always carries the public http(s) URL of the article on your site.
Pick one of the three ways:
| Way | When it fits | How |
|---|---|---|
| A. Answer the push with the URL | your endpoint of step 3 creates the page synchronously (a CMS, a database-backed site) | respond to dailyblogpost.publish with { "remote_url": "https://your-site.com/blog/{seo_slug}", "remote_id": "…" }. Any of the keys remote_url, url, permalink, link, remote_id, id, itemId, item_id in your answer counts as a confirmation, so a deploy-hook or revalidation endpoint must answer without them (an empty body is fine) until the page is really online. |
| B. Acknowledge after the build | static sites: the page exists only once the build finished | at the end of the build, for each article rendered for the first time, call the acknowledgement below (needs publish:write) |
| C. Give us a Read URL and let us check | you do not want to write any call | in Integrations → API, fill Read URL: an endpoint on your site that lists the articles online (contract in Custom API — Read endpoint). Daily Blog Post checks it weekly and confirms what it finds. |
Acknowledgement call (way B):
curl -X POST "https://dailyblogpost.app/api/public/articles/{id}/publish" \
-H "X-API-Key: $DBP_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "provider": "api", "remote_url": "https://your-site.com/blog/how-to-choose-a-standing-desk" }'remote_urlis required and must behttp(s): without it the call answers422withcode: "remote_url_required"and records nothing.- The call goes through the same checks as the Publish button.
422withissuestells you why:invalid_status(archived or still generating),missing_content,missing_seo_slug,language_mismatch. - Acknowledge each article once, after its page is really online, and
only the articles whose
publishedAtis stillnull. Acknowledging an already published article again resets its publication date and fires anarticle.updatedevent.
Acceptance checklist
Tick everything that applies to the path chosen in step 0.
-
GET /api/public/articleswith the token answers200JSON (step 1). - The token lives in an environment variable, server or build side only.
- One page per article at a stable URL built from
slug; title, meta description, HTML content and cover image rendered (step 2c). - No client-side filter on
status(step 2b). - Re-publishing an article updates the existing page (key on
id). - Sitemap built from
?status=publishedand referenced in the index. - Scheduled rebuild in place, driven by the full list of
ids (not byupdated_sincealone). - Step 3: the Test button in Integrations → API passes; the endpoint points at the final host.
- Step 4: each live article is confirmed with its URL; the dashboard shows it as delivered.
Prompt for an AI coding agent
Paste this in your agent, in the repository of your site:
Read https://dailyblogpost.app/docs/en/api-setup.mdx and connect this site to Daily Blog Post. The API token is in the environment variable
DBP_API_TOKEN; never print it or commit it. Do steps 1 to 4 (or: 1 and 2 only), following the field rules and the acceptance checklist exactly. Our article URL pattern ishttps://your-site.com/blog/{slug}. Stop and ask me before any change outside the blog pages, the sitemap and the build configuration.
Reference
- Endpoints, fields, pagination, error codes: Public API — Articles.
- Read endpoint contract (step 4, way C): Custom API — Read endpoint.
- Driving Daily Blog Post itself from an agent: MCP server.