Automated content for Prismic
Automated content for Prismic: push Crontent posts into Prismic drafts with the Migration API or a custom write path.
How-to: Integrate Crontent with Prismic. Official docs: Prismic. Shared API contract: Publishing API and SDK.
Prismic writes are constrained, so plan a Migration API or custom write path. Verify the Crontent webhook, fetch the post, then create a draft document editors can approve.
What you need
CRONTENT_API_KEYandCRONTENT_WEBHOOK_SECRET- A Prismic repository with a custom type (e.g.
blog_post) - A Migration API access token (Prismic dashboard) or a middleware service that holds write credentials
- Webhook receiver with
@crontent/sdk
Register Crontent webhooks:
await crontent.webhooks.register({
projectId: process.env.CRONTENT_PROJECT_ID!,
url: "https://your-app.com/api/crontent/webhook",
events: ["post.ready"],
});Map Crontent fields to Prismic
| Crontent field | Prismic field | Notes |
|---|---|---|
title | title | Rich text or Key Text |
seo_title | meta_title | SEO metadata; fall back to title |
slug | uid | Document UID |
excerpt | summary | Key Text |
body_mdx / body_html | body | Rich text (convert HTML) |
tags | tags | Group or Key Text list |
hero_image_url | featured_image | Link to Media or external |
canonical_url | canonical_url | Key Text |
sources[] | sources | Repeatable group |
ready_at | crontent_ready_at | Timestamp field |
Crontent researches and drafts; you define angle in the brief. Store documents unpublished until an editor releases them in Prismic.
Receive and verify webhooks
Headers: X-Crontent-Signature, X-Crontent-Timestamp, X-Crontent-Delivery. Retries at 1m, 5m, 30m, 2h, 12h. Deduplicate on delivery ID.
import { Crontent } from "@crontent/sdk";
const crontent = new Crontent({ apiKey: process.env.CRONTENT_API_KEY! });
export async function POST(req: Request) {
const rawBody = await req.text();
const deliveryId = req.headers.get("x-crontent-delivery")!;
if (await seen(deliveryId)) return new Response("OK");
const valid = await crontent.webhooks.verify({
rawBody,
signature: req.headers.get("x-crontent-signature"),
timestamp: req.headers.get("x-crontent-timestamp"),
secret: process.env.CRONTENT_WEBHOOK_SECRET!,
});
if (!valid) return new Response("Unauthorized", { status: 401 });
const { post_id } = JSON.parse(rawBody);
const post = await crontent.posts.get(post_id);
await createPrismicDraft(post);
await markSeen(deliveryId);
return new Response("OK");
}Create a draft in Prismic
Use the Migration API to create unpublished documents. Prismic does not expose a general-purpose public write API for arbitrary content creation.
async function createPrismicDraft(post: Post) {
const res = await fetch(
`https://migration.prismic.io/documents`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PRISMIC_MIGRATION_TOKEN}`,
"Content-Type": "application/json",
"x-api-key": process.env.PRISMIC_REPOSITORY!,
},
body: JSON.stringify({
title: post.title,
type: "blog_post",
uid: post.slug,
lang: "en-us",
data: {
title: [{ type: "heading1", text: post.title }],
meta_title: post.seo_title ?? post.title,
summary: post.excerpt,
body: convertHtmlToPrismicRichText(post.body_html),
sources: post.sources.map((s) => ({
url: { link_type: "Web", url: s.url },
label: s.title,
})),
},
}),
}
);
if (!res.ok) throw new Error(await res.text());
}Alternative: store Crontent posts in your database and expose them to Prismic via Integration Fields for read-only preview, then migrate approved posts with the Migration API.
Backfill and polling
Use crontent.posts.list({ projectId, since, cursor }) to replay missed events. Track synced post.id values to avoid duplicate UIDs.