AI Agent Publishing
Velo serves as a secure middleman gateway, allowing autonomous AI publishing agents (e.g. writers, SEO bots) to publish blogs to client websites without storing or exposing write tokens.
The Middleware Advantage
Instead of giving third-party AI agents your direct Sanity database credentials, agents authenticate against Velo using a single global Webhook Secret. Velo looks up the target organization, validates licensing features, and safely routes content writes to that organization's isolated database.
Integration Overview
Autonomous agents can post content to the centralized Velo Agent Publish endpoint:
Request Headers
| Header | Required | Value |
|---|---|---|
| Content-Type | Yes | application/json |
| Authorization | Yes | Bearer <AGENT_WEBHOOK_SECRET> |
Request Body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
| organization_id | String (UUID) | Yes | The target tenant's organization ID in Velo database. |
| title | String | Yes | The title of the blog post. |
| slug | String | Yes | URL-safe unique slug path (e.g. rise-of-agents). |
| metaDescription | String | No | SEO meta description for the blog post. |
| body | String (JSON) | Yes | The content of the blog post. Must be a stringified TipTap JSON document. |
CRITICAL DATA FORMAT RULE
Do NOT submit plain text or raw HTML in the body field. Velo's blog engine renders dynamic pages by parsing TipTap JSON. Sending flat text will crash the client's website with rendering exceptions.
Body Formatting Example
The TipTap JSON schema represents documents as trees of node structures. Here is an example of what the raw JSON should look like before you stringify it:
{
"type": "doc",
"content": [
{
"type": "heading",
"attrs": { "level": 2 },
"content": [{ "type": "text", "text": "Post Subtitle" }]
},
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "This is a paragraph containing some " },
{ "type": "text", "marks": [{ "type": "bold" }], "text": "bolded text" },
{ "type": "text", "text": "." }
]
}
]
}AI Agent Publishing Script
A reference integration script in Node.js for dispatcher services or autonomous AI agent runners.
import fetch from 'node-fetch';
const bodyDoc = {
type: 'doc',
content: [
{
type: 'heading',
attrs: { level: 2 },
content: [{ type: 'text', text: 'Securing the Agentic CMS Pipeline' }]
},
{
type: 'paragraph',
content: [{ type: 'text', text: 'Velo serves as a secure middleware...' }]
}
]
};
const payload = {
organization_id: 'c348e5dc-31d7-4581-8a39-9aad54d9d822',
title: 'Securing the Agentic CMS Pipeline',
slug: 'securing-the-agentic-cms-pipeline',
metaDescription: 'A technical overview of broker-based headless CMS publishing.',
body: JSON.stringify(bodyDoc) // Must be a stringified JSON document!
};
const response = await fetch('https://yourdomain.com/api/webhooks/agent-publish', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + process.env.AGENT_WEBHOOK_SECRET
},
body: JSON.stringify(payload)
});
const result = await response.json();
console.log('Result:', result);Response Mapping & Errors
200 OK — Success
401 Unauthorized
Occurs if the webhook secret is invalid, missing, or mismatched.
403 Forbidden
The target organization exists, but the blog feature is disabled in Velo settings.
422 Unprocessable Entity
The organization has blog enabled, but is missing its Sanity API Credentials.
