Publish to Payload
Add one endpoint to your Payload website, then connect it from GrowthSync with a URL and token.
1. Add a publish token
Create a long random token in the Payload website environment. GrowthSync will send this token in the Authorization header and the x-growthsync-publish-tokenheader. This is a shared GrowthSync publish token, not a Payload admin login token.
GROWTHSYNC_PUBLISH_TOKEN=replace-with-a-long-random-token2. Add the publish endpoint
Put this route in the Payload-powered Next.js app. Adjust the collection and field mapping to match your site.
The route must be reachable without the app session middleware. Keep it public at the routing layer and let GROWTHSYNC_PUBLISH_TOKEN authenticate the request. If the route redirects to sign-in or returns HTML, GrowthSync will block setup.
// app/api/growthsync/publish/route.ts
import { NextResponse } from "next/server";
import { getPayload } from "payload";
import config from "@payload-config";
export async function POST(req: Request) {
const token = req.headers.get("authorization")?.replace("Bearer ", "");
if (token !== process.env.GROWTHSYNC_PUBLISH_TOKEN) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const body = await req.json();
if (body.type === "connection_test") {
return NextResponse.json({ ok: true, message: "GrowthSync is connected." });
}
const payload = await getPayload({ config });
const collection = "posts";
const existing = await payload.find({
collection,
where: { slug: { equals: body.slug } },
limit: 1,
});
const data = {
title: body.title,
slug: body.slug,
excerpt: body.excerpt,
content: body.content.html,
meta: {
title: body.seo.title,
description: body.seo.description,
},
growthSync: body.source,
_status: "published",
};
const doc = existing.docs[0]
? await payload.update({ collection, id: existing.docs[0].id, data })
: await payload.create({ collection, data });
return NextResponse.json({
ok: true,
id: doc.id,
url: `/blog/${body.slug}`,
});
}3. Connect from GrowthSync
In a GrowthSync business profile, choose Payload CMS, enter the site URL, keep the endpoint as /api/growthsync/publish, paste the token, and run the connection test. A successful test must return JSON from the destination endpoint.
Payload sent by GrowthSync
GrowthSync sends one normalized blog payload. Your endpoint owns the final Payload schema mapping.
{
"type": "blog_post",
"externalId": "growthsync-page-id",
"title": "SEO blog title",
"slug": "seo-blog-title",
"status": "published",
"excerpt": "Meta description or summary",
"seo": {
"title": "Meta title",
"description": "Meta description",
"canonicalPath": "/seo-blog-title",
"schema": {}
},
"content": {
"html": "<p>Rendered HTML...</p>",
"hero": {},
"sections": [],
"faq": [],
"cta": {}
},
"source": {
"app": "growthsync",
"blueprint": {}
}
}