Use CMS Admin as a headless backend inside your own Next.js site. Read content, trigger deploys, and embed the AI chat — all authenticated with a permanent wh_ Access Token.
Overview
WebHouse CMS Admin is a full headless backend. Any Next.js (or other) site can call its REST API with a permanent wh_ Access Token — no OAuth redirect, no cookie session. This lets you build custom admin panels, booking management, form inboxes, and even an AI chat inside your own branded UI.
1. Create an Access Token
Go to Account Preferences → Access Tokens → Create custom token.
Choose only the permissions your site needs:
| Use case | Permissions |
|---|---|
| Read content | content.read |
| Full content CRUD | content.read content.create content.edit content.publish content.delete |
| Trigger deploys | deploy:trigger deploy:read |
| Form inbox | forms.read |
Set Site scope to restrict the token to a specific site. Store it in .env:
CMS_API_TOKEN=wh_xxxxxxxxxxxxxxxxxxxx
CMS_API_URL=https://webhouse.appNever expose the token client-side. Use it in server components, API routes, or getServerSideProps only.
2. Read Content
// app/posts/page.tsx
export default async function PostsPage() {
const res = await fetch(
`${process.env.CMS_API_URL}/api/cms/posts?status=published`,
{
headers: { Authorization: `Bearer ${process.env.CMS_API_TOKEN}` },
next: { revalidate: 60 },
}
);
const { documents } = await res.json();
return <ul>{documents.map((p: any) => <li key={p.slug}>{p.data.title}</li>)}</ul>;
}3. Content API Reference
GET /api/cms/{collection} List documents
GET /api/cms/{collection}/{slug} Get by slug
POST /api/cms/{collection} Create
PATCH /api/cms/{collection}/{slug} Update
DELETE /api/cms/{collection}/{id} Trash
Query params: status, locale, limit, offset, tags4. Site Admin Building Blocks
Trigger a deploy
await fetch(`${process.env.CMS_API_URL}/api/admin/deploy`, {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.CMS_API_TOKEN}` },
});Read form submissions
const res = await fetch(
`${process.env.CMS_API_URL}/api/admin/forms/contact/submissions`,
{ headers: { Authorization: `Bearer ${process.env.CMS_API_TOKEN}` } }
);
const { submissions } = await res.json();5. Embed the AI Chat
The CMS chat runs the same Claude model and tools as CMS Admin. Proxy it through a server route in your site:
// app/api/chat/route.ts
export async function POST(request: Request) {
const body = await request.text();
const upstream = await fetch(`${process.env.CMS_API_URL}/api/cms/chat`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.CMS_API_TOKEN}`,
},
body,
});
return new Response(upstream.body, {
headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' },
});
}Then consume the stream in a client component with a standard ReadableStream parser. The chat streams SSE events with event: text, event: tool_call, event: tool_result, and event: done.
Restrict tools by granting only the permissions you want on the Access Token — the chat only executes tools matching the token's permission set.
6. ICD Revalidation
Configure the revalidate webhook in Site Settings → Deploy → Revalidate URL to connect Next.js ISR with CMS content publishing:
// app/api/revalidate/route.ts
import { revalidatePath } from 'next/cache';
export async function POST(req: Request) {
const secret = req.headers.get('x-webhouse-secret');
if (secret !== process.env.REVALIDATE_SECRET) return new Response('Unauthorized', { status: 401 });
const { slug, collection } = await req.json();
revalidatePath(`/${collection}/${slug}`);
return Response.json({ revalidated: true });
}Further reading
- Access Tokens — creating and scoping tokens
- Content API — full endpoint reference
- ICD Deployment — instant content deployment