Daily Blog Post Docs

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 /blog listing 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 wantDo stepsEffort
A blog that reads Daily Blog Post and rebuilds on a schedule1 → 2one afternoon
…that also rebuilds the moment you publish1 → 2 → 3+ 30 minutes
…and a dashboard that shows every article as delivered, with its URL1 → 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

  1. In the app, open Integrations, find the Public API card and click Configure Public API.
  2. Create a token. Give it the name of the site (e.g. "Site Next.js production"). Tick the permission articles:read. Tick publish:write only if you plan to do step 4.
  3. 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-Key header. Authorization: Bearer is 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 (usually generated).

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 elementFieldRule
URLslughttps://your-site.com/blog/{slug}. Keep this pattern stable: it is what you will confirm in step 4.
<title>metaTitlefalls back to title server-side, always present
<meta name="description">metaDescriptionmay be empty
H1title
BodycontentHTML produced by Daily Blog Post (headings, paragraphs, lists, links, images). Render it as HTML, do not escape it.
Cover imagecoverImageUrlmay be null; alt = title
DatespublishedAt, updatedAtISO strings; publishedAt is null for an article sent to your site and not confirmed yet — show createdAt then
Languagelocaleset <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.

  1. 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.
  2. 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" }; any 2xx passes.
  3. From now on every Publish sends a JSON POST to 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 2xx quickly; do the rebuild asynchronously if it is slow.
  • Handle both type values. On dailyblogpost.test, return 200 and stop.
  • Point the URL at the final host (www. or apex, whichever answers). The push follows a redirect only between the apex and its www. variant, and only on 307/308: a 301 or 302 on a POST is 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:

WayWhen it fitsHow
A. Answer the push with the URLyour 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 buildstatic sites: the page exists only once the build finishedat 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 checkyou do not want to write any callin 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_url is required and must be http(s): without it the call answers 422 with code: "remote_url_required" and records nothing.
  • The call goes through the same checks as the Publish button. 422 with issues tells 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 publishedAt is still null. Acknowledging an already published article again resets its publication date and fires an article.updated event.

Acceptance checklist

Tick everything that applies to the path chosen in step 0.

  • GET /api/public/articles with the token answers 200 JSON (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=published and referenced in the index.
  • Scheduled rebuild in place, driven by the full list of ids (not by updated_since alone).
  • 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 is https://your-site.com/blog/{slug}. Stop and ask me before any change outside the blog pages, the sitemap and the build configuration.

Reference