NowPage API & MCP Server

Paint-by-Numbers User Manual — Last updated Feb 20, 2026
Table of Contents
  1. Prerequisites & Base URL
  2. Step 1 — Create an API Key
  3. Step 2 — List Your Domains
  4. Step 3 — Publish a Page
  5. Step 4 — Update an Existing Page
  6. Step 5 — Set Up Webhooks
  7. Step 6 — CLI Publishing (hc-publish.js)
  8. Step 7 — MCP Server Setup (Claude Desktop)
  9. Step 8 — MCP Server on claude.ai
  10. MCP Tool Reference
  11. Full API Reference
  12. Troubleshooting

Prerequisites & Base URL

Everything you need before starting:

Base URL

https://nowpage-saas.vercel.app

All API endpoints below are relative to this base. Your published pages are served on your custom domain (e.g., https://ideas.asapai.net/your-slug).

Step 1 — Create an API Key

Why? API keys let you publish pages programmatically — from scripts, Forge VPS, n8n workflows, or the MCP server. They never expire unless you set a TTL.
1 Open Your Dashboard

Go to your NowPage dashboard. In the left sidebar, click API Keys.

2 Click "+ New Key"

Fill in:

FieldWhat to EnterExample
nameA label so you remember what it's forForge VPS
permissionsLeave empty for full access, or {"publish": true}{}
domain_idsLeave empty for all domains, or specific UUIDs[]
expires_in_daysLeave empty for permanent, or a number(empty)
3 Copy the Key IMMEDIATELY

The raw key (starts with np_live_) is shown only once. Copy it and save it somewhere safe.

If you lose the key, you must revoke it and create a new one. The raw key is hashed in the database and cannot be recovered.

Or via curl:

# Create key via API (requires browser session cookie)
curl -X POST https://nowpage-saas.vercel.app/api/keys \
  -H "Content-Type: application/json" \
  -H "Cookie: your_session_cookie" \
  -d '{
    "name": "My Automation Key",
    "permissions": {"publish": true},
    "domain_ids": []
  }'

# Response includes raw_key — save it NOW

Step 2 — List Your Domains

Before publishing, confirm which domains your API key can access:

1 Run this curl command
curl https://nowpage-saas.vercel.app/api/publish/domains \
  -H "Authorization: Bearer np_live_YOUR_KEY_HERE"
2 Check the Response
[
  {
    "id": "4f20a885-...",
    "full_domain": "ideas.asapai.net",
    "status": "active",
    "is_custom_domain": true,
    "hosting_type": "vercel"
  }
]

Use the full_domain value as the domain parameter when publishing.

Step 3 — Publish a Page

This is the core operation. Send HTML content and it goes live immediately.

1 Prepare Your HTML

Your HTML should include HC metadata blocks for full compliance:

<!DOCTYPE html>
<html lang="en">
<head>
  <title>My Page Title</title>
  <script id="hc-metadata" type="application/json">
  {
    "hc_version": "1.3.3",
    "hc_type": "artifact",
    "artifact_id": "my-page",
    "title": "My Page Title",
    "summary": "A brief description of this page",
    "tags": ["example", "demo"]
  }
  </script>
</head>
<body>
  <h1>My Page</h1>
  <p>Your content here.</p>
</body>
</html>
2 Send the Publish Request
curl -X POST https://nowpage-saas.vercel.app/api/publish \
  -H "Authorization: Bearer np_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "ideas.asapai.net",
    "html_content": "<!DOCTYPE html><html>...your full HTML...</html>",
    "tags": ["example", "demo"],
    "registry": "auto"
  }'
3 Check the Response
{
  "success": true,
  "page_id": "abc123-...",
  "url": "https://ideas.asapai.net/my-page-title",
  "action": "created",
  "registry_updated": true
}

Your page is live immediately at the returned URL. No deploy needed.

Publish API Parameters

ParameterRequiredTypeDescription
domainYesstringTarget domain: "ideas.asapai.net"
html_contentYesstringFull HTML string (min 10 chars)
slugNostringURL slug. Auto-generated from title if empty.
nameNostringPage name. Auto-extracted from hc-metadata or <title>.
folderNostringFolder name. Created automatically if missing.
tagsNoarray or stringArray ["a","b"] or comma-string "a,b"
registryNostring"auto" (default), "none", or a registry page UUID
update_modeNostring"version" (default, saves backup), "overwrite", "fail"
Auto-Registry Magic: When registry is "auto", the system looks at your tags:
• Tags containing meeting, standup, transcript → registers in Meeting Intelligence Registry
• Tags containing eod, daily, review → registers in EOD Reports Registry
• Everything else → registers in the main neural registry (homepage)

Step 4 — Update an Existing Page

To update a page, just publish to the same slug again. The update_mode controls what happens:

ModeBehavior
"version"Saves old content as a version snapshot, then overwrites. Default — recommended.
"overwrite"Overwrites without saving a version. Use for scratch/temp pages.
"fail"Returns an error if the slug already exists. Use for "create-only" workflows.
curl -X POST https://nowpage-saas.vercel.app/api/publish \
  -H "Authorization: Bearer np_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "ideas.asapai.net",
    "slug": "my-page-title",
    "html_content": "<!DOCTYPE html>...updated content...</html>",
    "update_mode": "version"
  }'

# Response: "action": "updated"

Step 5 — Set Up Webhooks

Get notified when pages are published or updated. Great for triggering n8n workflows, Slack alerts, or Forge pipelines.

1 Create a Webhook
curl -X POST https://nowpage-saas.vercel.app/api/webhooks \
  -H "Cookie: your_session_cookie" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "n8n Page Published",
    "url": "https://your-n8n.example.com/webhook/abc123",
    "event_types": ["page.published", "page.updated"]
  }'

Response includes a secret for HMAC verification. Save it.

2 Webhook Payload Format

When a page is published, your URL receives:

POST https://your-webhook-url.com
Headers:
  Content-Type: application/json
  X-NowPage-Signature: sha256=abc123def456...

Body:
{
  "event": "page.published",
  "timestamp": "2026-02-20T10:30:00Z",
  "data": {
    "page": {
      "id": "abc-123",
      "url": "https://ideas.asapai.net/my-page",
      "title": "My Page",
      "tags": ["meeting", "gtm"],
      "hc_type": "artifact"
    },
    "domain": "ideas.asapai.net",
    "registry_updated": true
  }
}
3 Verify the Signature (optional but recommended)
# Node.js verification example:
const crypto = require('crypto');
const signature = req.headers['x-nowpage-signature'];
const expected = 'sha256=' + crypto
  .createHmac('sha256', YOUR_WEBHOOK_SECRET)
  .update(JSON.stringify(req.body))
  .digest('hex');

if (signature === expected) {
  // Verified! Process the event.
}

Webhook Events

EventFires When
page.publishedA new page is created via API
page.updatedAn existing page is updated via API
registry.updatedA registry page is modified (auto or manual)

Step 6 — CLI Publishing (hc-publish.js)

For local publishing from your terminal or Claude Code sessions:

1 Ensure .env.local has your Supabase creds

The script reads from .env.local in the project root (or parent directories). Required keys: SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY.

2 Publish a file
node scripts/hc-publish.js \
  --domain ideas.asapai.net \
  --file /path/to/your-page.html \
  --tags "meeting,gtm,sprint" \
  --registry auto
3 CLI Options Quick Reference
FlagDescriptionDefault
--domainTarget domain (required)
--filePath to HTML file (required)
--slugURL slugAuto from title
--namePage nameAuto from metadata
--folderFolder nameRoot level
--tagsComma-separated tagsNone
--registryauto, none, or page UUIDauto
--updateversion, overwrite, failversion
--dry-runPreview without saving
--apiUse remote API instead of direct Supabase
--api-urlBase URL for API modeFrom .env.local

Step 7 — MCP Server Setup (Claude Desktop)

What's this? The MCP server lets Claude Desktop publish pages, list domains, and fetch page HTML — all through natural conversation. Say "publish this meeting summary to ideas.asapai.net" and Claude does the rest.
1 Install Python Dependencies
pip install "mcp[cli]>=1.0.0" httpx>=0.27.0

Requires Python 3.8+. Verify with: python --version

2 Locate the Server File

The MCP server is at:

C:/Users/jason/Downloads/folio-saas/mcp-nowpage/server.py

If you clone the repo elsewhere, update the path accordingly.

3 Get Your API Key

You need an np_live_ key (see Step 1). Copy it — you'll paste it in the config.

4 Edit Claude Desktop Config

Open the config file:

# Windows path:
%APPDATA%\Claude\claude_desktop_config.json

# Mac path:
~/Library/Application Support/Claude/claude_desktop_config.json

Add the nowpage server to the mcpServers object:

{
  "mcpServers": {
    "nowpage": {
      "command": "python",
      "args": ["C:/Users/jason/Downloads/folio-saas/mcp-nowpage/server.py"],
      "env": {
        "NP_API_KEY": "np_live_YOUR_KEY_HERE"
      }
    }
  }
}
Already have other MCP servers? Just add the "nowpage": {...} block alongside them inside the existing mcpServers object. Don't replace the whole file.
5 Restart Claude Desktop

Close and reopen Claude Desktop (or use "Reload MCP Servers" if available). You should see "NowPage" in the MCP server list.

6 Test It!

In Claude Desktop, try:

"List my NowPage domains"
"Publish a test page to ideas.asapai.net with a hello world"
"Fetch the HTML of ideas.asapai.net/meta-registry"

Step 8 — MCP Server on claude.ai

Why? claude.ai supports remote MCP servers, so you can publish from any browser session — no local install needed. This syncs your Claude Desktop and web experience.
1 Option A: Use an MCP Proxy (Recommended)

claude.ai needs an HTTP-based MCP server (not stdio). Use mcp-remote or ngrok to expose your local server:

# Install mcp-remote (bridges stdio → SSE for claude.ai)
npx @anthropic-ai/mcp-remote

# Or use Cloudflare Workers / ngrok to expose the server
# See: https://modelcontextprotocol.io/docs/remote
2 Option B: Deploy to Forge VPS (Persistent)

For always-on access, deploy the MCP server on your VPS:

# On Forge VPS:
cd /opt/forge/mcp-nowpage
pip install "mcp[cli]>=1.0.0" httpx>=0.27.0

# Run with SSE transport (for remote clients)
NP_API_KEY=np_live_YOUR_KEY python server.py --transport sse --port 8765
3 Add to claude.ai Settings

In claude.ai, go to Settings → Integrations → MCP Servers → Add Server:

FieldValue
NameNowPage
URLhttps://your-vps:8765/sse (or ngrok URL)
AuthenticationNone (API key is baked into the server env)
4 Sync Claude Desktop ↔ claude.ai

Both point to the same NowPage API with the same API key. Any page published from Claude Desktop is visible from claude.ai and vice versa. The source of truth is always the Supabase database.

Pro tip: Use the same API key in both configs so published pages, registries, and version history are unified.

MCP Tool Reference

These are the 4 tools available when the NowPage MCP server is connected:

1. publish_page

ParameterTypeRequiredDescription
domainstringYesTarget domain, e.g. "ideas.asapai.net"
html_contentstringYesFull HTML with hc-metadata blocks
slugstringNoURL slug (auto from title if empty)
namestringNoPage name (auto from metadata)
folderstringNoFolder (created if missing)
tagsstringNoComma-separated: "meeting,gtm"
registrystringNo"auto", "none", or page UUID
update_modestringNo"version", "overwrite", "fail"

2. list_domains

No parameters. Returns all active domains accessible to the API key.

3. list_templates

No parameters. Returns 8 HC template references with names and descriptions.

4. get_page_html

ParameterTypeRequiredDescription
domainstringYesDomain name
slugstringYesPage slug

Returns raw HTML source (truncated at 50KB for large pages).

Full API Reference

Publishing

MethodEndpointAuthPurpose
POST/api/publishAPI Key or SessionPublish a page
GET/api/publish/domainsAPI Key or SessionList accessible domains

Pages (CRUD)

MethodEndpointAuthPurpose
GET/api/pages?domain_id=IDSessionList pages for a domain
POST/api/pagesSessionCreate a page
PUT/api/pages?id=IDSessionUpdate a page
DEL/api/pages?id=IDSessionDelete a page

API Keys

MethodEndpointAuthPurpose
GET/api/keysAPI Key or SessionList your keys (no raw values)
POST/api/keysSession onlyCreate key (returns raw once)
DEL/api/keys?id=IDSession onlyRevoke a key

Webhooks

MethodEndpointAuthPurpose
GET/api/webhooksSessionList webhooks
POST/api/webhooksSessionCreate webhook (returns secret once)
PUT/api/webhooks?id=IDSessionUpdate webhook
DEL/api/webhooks?id=IDSessionDelete webhook

HC Registries

MethodEndpointAuthPurpose
GET/api/hc/registriesSessionList your registries
POST/api/hc/update-registrySessionAdd artifact to registry
POST/api/hc/remove-from-registrySessionRemove artifact from registry
POST/api/hc/analyzeSessionAnalyze HTML content with Claude

Other Endpoints

MethodEndpointAuthPurpose
GET/api/templatesPublicList HC templates
GET/api/page-versions?page_id=IDSessionGet version history
GET/api/folders?domain_id=IDSessionList folders
GET/api/navigation?domain=DPublicGet navigation JSON
POST/api/chatPublicClaude proxy (keeps API key server-side)

Troubleshooting

Common Issues

SymptomCauseFix
401 UnauthorizedMissing or invalid API keyCheck Authorization: Bearer np_live_... header
403 ForbiddenKey lacks permission or domain accessCreate key with permissions: {} (all) or add the domain to domain_ids
400 "Required fields"Missing domain or html_contentBoth are required in POST /api/publish
MCP server not showingConfig path wrong or Python not foundVerify python is on PATH and the args path exists
"NP_API_KEY not set"Env var missing in MCP configAdd "env": {"NP_API_KEY": "np_live_..."} to config
Page published but not in registryTags don't match any registry patternAdd meeting or eod tag, or use registry: "none" intentionally
Registry row not visibleMissing <tbody id="meeting-feed">Registry template must have the correct tbody ID for injection
Version history missingFirst publish doesn't create a versionNormal — versions are saved on updates, not first create

Test Your Setup

# 1. Check domains
curl -s https://nowpage-saas.vercel.app/api/publish/domains \
  -H "Authorization: Bearer np_live_YOUR_KEY" | python -m json.tool

# 2. Publish a test page
curl -s -X POST https://nowpage-saas.vercel.app/api/publish \
  -H "Authorization: Bearer np_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "ideas.asapai.net",
    "html_content": "<html><head><title>API Test</title></head><body><h1>It works!</h1></body></html>",
    "slug": "api-test-delete-me",
    "registry": "none"
  }' | python -m json.tool

# 3. Verify the page is live
curl -s -o /dev/null -w "%{http_code}" https://ideas.asapai.net/api-test-delete-me
You're all set! You can now publish HC pages from curl, Node.js scripts, Python, Forge VPS, n8n, or directly from Claude Desktop / claude.ai via the MCP server. Happy publishing!