AI-Powered Content API

Turn HTML and Prompts
into Structured Blocks

SSO CMS converts raw dealer page HTML or natural-language prompts into structured, renderable content-block JSON — powered by GPT-4o mini.

4
Endpoints
9
Widget Types
6
Layout Options

Four focused endpoints

AI endpoints require an X-Service-Key header. /blocks-to-html is open — no auth, no AI cost.

POST
/ai/html-to-blocks

HTML to Blocks

Paste raw dealer page HTML (up to 100 KB) and receive a normalized content-block JSON array — widgets, layout, and props extracted automatically.

Input: html (string) Output: rows[] X-Service-Key
POST
/ai/prompt-to-blocks

Prompt to Blocks

Describe a page in plain language ("About page for a luxury Honda dealer") and receive a full content-block layout — no existing HTML required.

Input: prompt, hostname? Output: rows[] X-Service-Key
POST
/ai/validate-blocks

Validate Blocks

Submit an existing content JSON array for AI-assisted validation and repair. Fixes unknown widget types, missing required props, and malformed layouts.

Input: contentJson (array) Output: rows[] X-Service-Key
POST
/blocks-to-html

Blocks to HTML

Render a content-block JSON array to a scoped HTML fragment. No AI call — deterministic, fast, and free. Returns the fragment and a unique scopeId for CSS targeting.

Input: rows[], id? Output: html, scopeId No auth required
🔒

Service-key authentication

All /ai/* routes require a valid X-Service-Key header matching the CMS_SERVICE_KEY environment variable. Requests with a missing or wrong key receive a 401 or 403 response. In local development, leave CMS_SERVICE_KEY unset to bypass auth entirely.

X-Service-Key: <your-cms-service-key>

Call the API in 30 seconds

Pick a request style and copy the snippet.

# Convert a prompt to content blocks
curl -X POST http://localhost:4132/ai/prompt-to-blocks \
  -H "Content-Type: application/json" \
  -H "X-Service-Key: your-key" \
  -d '{
    "prompt": "About page for a luxury Honda dealership in Phoenix",
    "hostname": "dealer.example.com"
  }'
const res = await fetch('http://localhost:4132/ai/prompt-to-blocks', {
  method:  'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Service-Key': process.env.CMS_SERVICE_KEY,
  },
  body: JSON.stringify({
    prompt:   'About page for a luxury Honda dealership in Phoenix',
    hostname: 'dealer.example.com',
  }),
});

const { rows, usage } = await res.json();
// rows → array of layout rows with columns and widgets
// usage → { prompt_tokens, completion_tokens, total_tokens }
{
  "rows": [
    {
      "layout": "full",
      "columns": [
        {
          "widgets": [
            {
              "type": "header",
              "props": { "text": "About Our Dealership", "tag": "h1" }
            },
            {
              "type": "text",
              "props": { "content": "Serving Phoenix since 1987..." }
            }
          ]
        }
      ]
    },
    {
      "layout": "1/3+2/3",
      "columns": [ /* ... */ ]
    }
  ],
  "usage": {
    "prompt_tokens": 312,
    "completion_tokens": 487,
    "total_tokens": 799
  }
}

9 built-in widget types

Every block in a response is one of these known types. The AI will never hallucinate a widget outside this closed set.

🔢

text

HTML content with optional AI-generated copy recommendations.

📷

image

Image widget with src, alt, and optional caption.

📖

header

Heading element — supports h1 through h6 tags.

🎥

video

Video embed with src, poster, and autoplay flag.

sideScrollGallery

Horizontally scrollable image array with optional links.

🔗

navigation

Structured link array — useful for menus or CTAs.

masonryGrid

Masonry image grid with optional per-image links.

📰

feedContent

RSS feed widget — includes URL, title, and max item count.

</>

customHtml

Raw HTML passthrough — for content the AI should preserve as-is.

6 column layouts

Each row declares one of these layouts to control how columns divide the horizontal space.

full
1/2+1/2
1/3+2/3
2/3+1/3
1/3+1/3+1/3
1/4+1/4+1/4+1/4
Service health endpoint live

Deployment-ready

Every deploy is verified via GET /health. The response includes a SHA-256 file hash of server.js — deploy scripts compare this against the built artifact to confirm the correct version is running.

GET /health