Content API (headless)
The Content API is for sites that aren't on a supported CMS — a custom
app (Next.js, Astro, Nuxt, SvelteKit…), a PHP site, or anything you
build yourself. You pull your published articles as
JSON and render them on your own domain (for example
at yoursite.com/blog), in your own design.
Because the pages live on your domain, this is the best option for SEO — the content's link equity stays on your root domain, with no proxy and no DNS gymnastics. It's also the ideal fit for agencies: build the integration once, reuse it across every client site.
What you'll need
- Your API key — open the Publishing
tab of your site in
app.pilotscribe.com, or
just ask the assistant "give me my API key". It looks like
pk_<site-id>.<signature>. Keep it in an environment variable (PILOTSCRIBE_API_KEY). - The base URL —
https://blog.pilotscribe.com/v1
Authentication
Send the key as a Bearer token (recommended) or as a
?key= query param. The API is read-only and returns only
published articles. CORS is open, so both server-side
and browser fetch work — but render server-side when you
can, for SEO.
curl -H "Authorization: Bearer pk_<your-key>" \
https://blog.pilotscribe.com/v1/articles Endpoints
List articles
GET /v1/articles
{
"site": { "name": "Acme", "lang": "en" },
"total": 12,
"articles": [
{
"slug": "ai-writing-tools",
"title": "…",
"metaDescription": "…",
"excerpt": "…",
"lang": "en",
"publishedAt": "2026-06-04T12:00:03.378Z",
"updatedAt": "2026-06-04T12:00:03.378Z",
"imageUrl": "https://blog.pilotscribe.com/_media/articles/<id>.webp",
"imageAlt": "…"
}
]
} One article by slug — html is rendered
and sanitized (ready to inject); markdown is the raw body
if you'd rather style it yourself.
GET /v1/articles/{slug}
{
"slug": "ai-writing-tools",
"title": "…",
"metaDescription": "…",
"lang": "en",
"html": "<p>…</p>", // rendered + sanitized — ready to inject
"markdown": "…", // raw, if you'd rather render it yourself
"imageUrl": "…",
"imageAlt": "…",
"publishedAt": "…",
"updatedAt": "…",
"related": [ { "slug": "…", "title": "…" } ]
} Example — Next.js (App Router)
// app/blog/page.tsx — your blog index, on YOUR domain
const { articles } = await fetch("https://blog.pilotscribe.com/v1/articles", {
headers: { Authorization: `Bearer ${process.env.PILOTSCRIBE_API_KEY}` },
next: { revalidate: 3600 }, // cache 1h, refresh in background
}).then((r) => r.json());
// → map articles to <a href={`/blog/${a.slug}`}>…</a>
// app/blog/[slug]/page.tsx — a single article
const a = await fetch(`https://blog.pilotscribe.com/v1/articles/${slug}`, {
headers: { Authorization: `Bearer ${process.env.PILOTSCRIBE_API_KEY}` },
}).then((r) => r.json());
return (
<article>
{a.imageUrl && <img src={a.imageUrl} alt={a.imageAlt} />}
<h1>{a.title}</h1>
<div dangerouslySetInnerHTML={{ __html: a.html }} />
</article>
);
Astro, Nuxt and SvelteKit are the same idea: fetch in your
loader / getStaticPaths and render. Prefer build-time or
ISR (e.g. revalidate hourly) so pages are static and fast.
Example — PHP
<?php
$key = getenv('PILOTSCRIBE_API_KEY');
$ctx = stream_context_create(['http' => [
'header' => "Authorization: Bearer $key",
]]);
$json = file_get_contents(
"https://blog.pilotscribe.com/v1/articles/" . urlencode($slug), false, $ctx);
$a = json_decode($json, true);
echo "<h1>" . htmlspecialchars($a['title']) . "</h1>";
echo $a['html']; // already sanitized Good to know
- Caching. Responses are cacheable for an hour; revalidate on a schedule rather than fetching on every request.
- Images.
imageUrlis an absolute URL served from our CDN — use it directly, or download and re-host if you prefer. - Sitemap. Add your
/blogURLs to your own sitemap so search engines discover them on your domain. - Already on WordPress, Shopify, Webflow or Ghost? You don't need the API — use the direct CMS connector instead (no code).
- Using an AI coding agent? Skip the manual setup — connect Claude, Cursor or Claude Code to our Integration MCP and it wires this API into your site for you. Any LLM can also read
/llms.txtand/openapi.json.
Stuck? Ask the in-app assistant, or email contact@pilotscribe.com.