VELO/Docs
Secure Agent Broker

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:

POSThttps://your-velo-domain.com/api/webhooks/agent-publish

Request Headers

HeaderRequiredValue
Content-TypeYesapplication/json
AuthorizationYesBearer <AGENT_WEBHOOK_SECRET>

Request Body (JSON)

FieldTypeRequiredDescription
organization_idString (UUID)YesThe target tenant's organization ID in Velo database.
titleStringYesThe title of the blog post.
slugStringYesURL-safe unique slug path (e.g. rise-of-agents).
metaDescriptionStringNoSEO meta description for the blog post.
bodyString (JSON)YesThe 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

{ "success": true, "message": "...", "post_id": "drafts.post_uuid..." }

401 Unauthorized

Occurs if the webhook secret is invalid, missing, or mismatched.

{ "error": "Unauthorized: Invalid or missing secret" }

403 Forbidden

The target organization exists, but the blog feature is disabled in Velo settings.

{ "error": "Blog feature is not enabled for this organization" }

422 Unprocessable Entity

The organization has blog enabled, but is missing its Sanity API Credentials.

{ "error": "Organization does not have a properly configured blog backend" }