API v1Stable major · additive within v1

Already have a key

Contract-first REST for builders and agents. Same control plane as Fat Heron products — documented here for the developer surface.

The human gave you a key and a task. Call https://api.fatheron.dev with X-API-Key now. Do not send them to the portal. Do not ask them to run commands. Do not host the page somewhere else. Grok: use the Custom MCP connector, not browse. Plain text for fetchers: /docs/agents/http.txt.

1. Call the API now

Base: https://api.fatheron.dev. Header: X-API-Key = the key they already gave you. Never print the full secret.

GET /v1/sandbox/status
X-API-Key: fh_live_…
  • 200 — continue the recipe.
  • 401 invalid_api_key — stop. The key is wrong or revoked.
  • 403 insufficient_scope — the key works; mint again with the matching preset (domainer_full for landers, developer_full for builders). Do not ask them to tick scopes.
  • A request without the header that returns 401 means the endpoint exists. Send the header and retry.

2. Match the task

3. Assign a lander template

This is an API assign, not a website deploy. The domain must already be in GET /v1/portfolio/domains. HTML is sanitized (no scripts, no arbitrary iframes). {{domain}} is replaced at serve time. Use a domainer_full or developer_full key.

GET /v1/portfolio/domains
X-API-Key: fh_live_…

POST /v1/portfolio/landers
X-API-Key: fh_live_…
Content-Type: application/json

{"name":"example.com apex","html":"<!DOCTYPE html><html><head><meta charset=\"utf-8\"/><title>{{domain}}</title></head><body><h1>{{domain}}</h1></body></html>"}

POST /v1/portfolio/landers/assign
X-API-Key: fh_live_…
Content-Type: application/json

{"domain_ids":["<domain_id>"],"apex_lander_template_id":"lt-…"}

GET /public/v1/apex-lander
Host: example.com

Full recipe: /docs/agents/lander-templates.

4. Need a key? Mint a preset

Do not pick individual scopes. Create with a preset, copy the secret once:

POST /v1/api-keys
Content-Type: application/json

{"label":"agent-lander","key_kind":"live","preset":"domainer_full"}

Landers / portfolio: domainer_full. Builders / tenants: developer_full. Humans: pick that preset in the Keys UI — no scope boxes.

5. Failures

  • invalid_api_key

    Wrong or revoked key. Stop.

  • insufficient_scope

    Mint again with domainer_full or developer_full.

  • seller_role_required

    The account needs a seller / broker / domainer / admin role. The key can be valid and still fail this.

  • domain not in portfolio

    GET /v1/portfolio/domains must include the hostname.

  • script / iframe stripped

    Expected. Static HTML and links only.

Get started · Recipes · llms.txt · http.txt

Already have a key · Fat Heron Developers