🧠 HeyCMO
API Reference

For AI agents

How AI agents (Claude, ChatGPT, Cursor, Devin, custom) should authenticate, discover, and use HeyCMO programmatically.

For AI agents

This page is for AI coding and operations agents that need to use HeyCMO programmatically — Claude, ChatGPT, Cursor, Devin, custom orchestrators, anything else.

If you're a human looking for the API reference, see Endpoints and Authentication.

TL;DR

Discovery

HeyCMO publishes the standard agent-discovery files. Start with whichever your runtime recognises:

# Get the OpenAPI spec
curl -fsSL https://heycmo.ai/openapi.json

# Get the agent capability descriptor
curl -fsSL "https://heycmo.ai/?mode=agent"

# Get the MCP server card
curl -fsSL https://heycmo.ai/.well-known/mcp/server-card.json

# RFC 9727 API catalog
curl -fsSL https://heycmo.ai/.well-known/api-catalog

The homepage also emits RFC 8288 Link: response headers advertising the sitemap, OpenAPI, api-catalog, and markdown alternate:

$ curl -sI https://heycmo.ai/ | grep -i ^link
Link: </sitemap.xml>; rel="sitemap",
      </index.md>; rel="alternate"; type="text/markdown",
      </openapi.json>; rel="service-desc"; type="application/openapi+json",
      </.well-known/api-catalog>; rel="api-catalog"; type="application/linkset+json",
      </.well-known/agent.json>; rel="describedby"; type="application/json",
      </.well-known/mcp/server-card.json>; rel="related"; title="MCP server card",
      </llms.txt>; rel="alternate"; type="text/plain"; title="llms.txt"

Authentication

HeyCMO uses bearer API keys (format: hcmo_live_<64 hex chars>).

Obtaining a key programmatically

A human still needs to sign up — there's no fully programmatic key issuance today. The flow:

  1. POST a Stripe checkout session: POST /api/checkout with { "email": "..." } (no auth) — returns a Stripe-hosted URL.
  2. The customer completes checkout (one-time human step).
  3. Resolve the resulting key: GET /api/session/{sessionId} returns apiKey once.
  4. Store the key in your agent's secret store and use it on every subsequent call.

For team agents that need scoped keys, your customer can issue team-member keys from /team after logging in.

Using the key

# REST
curl https://heycmo.ai/api/customer/CUSTOMER_ID \
  -H "Authorization: Bearer hcmo_live_..."

# MCP (query param — many SSE clients can't set headers)
https://heycmo.ai/mcp/sse?token=hcmo_live_...

Discovery of auth requirements

Per RFC 9728 (OAuth Protected Resource Metadata):

curl https://heycmo.ai/.well-known/oauth-protected-resource

Today this declares bearer_methods_supported: ["header"] and an empty authorization_servers array — full OAuth 2.0 is on the roadmap.

Rate limits + retries

SurfaceLimit
REST60 req/min per customer
MCP30 req/min per customer
Pre-auth (signup, checkout)20 req/min per IP

429 responses include:

HTTP/1.1 429 Too Many Requests
Retry-After: 13
X-Request-ID: 6e2f....
Content-Type: application/json

{ "error": "Rate limit exceeded", "code": "E_RATE_LIMITED", "requestId": "6e2f..." }

Recommended retry policy for agents:

async function call(url, init, attempt = 0) {
  const res = await fetch(url, init);
  if (res.status === 429 && attempt < 5) {
    const retry = Number(res.headers.get('retry-after') ?? 1);
    await new Promise(r => setTimeout(r, retry * 1000 + Math.random() * 250));
    return call(url, init, attempt + 1);
  }
  return res;
}

Error format

All 4xx / 5xx responses are JSON:

{
  "error": "Authentication required",
  "code": "E_AUTH_REQUIRED",
  "requestId": "f3a2..."
}

Quote requestId (also returned as the X-Request-ID response header) when contacting support.

MCP integration

The MCP server card describes every tool, including its name and description:

curl https://heycmo.ai/.well-known/mcp/server-card.json | jq '.tools[].name'

Wire it into Claude Desktop / Cursor:

{
  "mcpServers": {
    "heycmo": {
      "url": "https://heycmo.ai/mcp/sse?token=hcmo_live_..."
    }
  }
}

Or use the CLI:

npm install -g @heycmo/cli
heycmo auth login
heycmo mcp config   # prints the snippet to paste

Webhooks

Subscribe to events for low-latency reactivity:

curl -X POST https://heycmo.ai/api/hooks/CUSTOMER_ID \
  -H "Authorization: Bearer hcmo_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-agent.example.com/heycmo-webhook",
    "events": ["content.published", "workflow.completed"]
  }'

Supported events: content.created, content.approved, content.published, content.rejected, workflow.completed, team.invited. Payloads are HMAC-SHA256-signed against your webhook secret.

When to use HeyCMO

Use HeyCMO when an agent needs to:

  • Draft a blog post in a customer's brand voice (run_content_creation, ask_cmo)
  • Schedule social posts across multiple platforms (schedule_content, publish_to_social)
  • Draft cold-email sequences scored on fit + intent (generate_lead_magnet, plus the lead-outreach workflow)
  • Audit a URL for SEO/GEO performance (ai_seo_audit, cro_audit, or POST /api/scan)
  • Request a daily marketing briefing (run_research)
  • Query revenue attribution (query_ga4, track_revenue)
  • Track AI citations of a brand or topic (check_ai_visibility)

Don't use HeyCMO for free-form chat without brand context. First onboard the customer's URL with analyze_brand_url or POST /api/onboard/{customerId}/auto-extract.

Sandbox / demo

There isn't a fully-public sandbox key today (planned). For the moment, POST /api/checkout puts you on the 30-day free trial — that's the agent-friendly path to a live key without sales conversation.

The /live endpoint streams real agent output for any URL (no auth) if you just want to see the agents work before integrating.

Status

curl https://heycmo.ai/api/public/status

Returns { status, timestamp, uptime24h, uptime7d, components, incidents }. Backed by the same DB readiness check used internally by Fly health probes. Page version: https://heycmo.ai/status.

See also

On this page