Outlines

Outlines

An outline is a proposed content structure for a page — a list of headings with guidance, generated from the page's primary keyword and a SERP snapshot of how competitors structure their own content for that keyword. This endpoint reads the page's latest outline, whatever its status.

Scope: sites:read

Creating and accepting outlines over the API isn't available yet — this release is read-only. Support for triggering generation and accepting/revising sections ships in the next release.


GET /pages/{pageId}/outline

Path parameters

Parameter Type Description
pageId integer The page's ID

Request

curl -s https://new.metamonster.ai/api/v1/pages/5001/outline \
  -H "Authorization: Bearer mm_YOUR_API_KEY"

Returns 404 when the page has never had an outline generated — this differs from the internal dashboard route, which returns { data: null } for the same case.

Section fields

Each entry in sections is one proposed heading:

Field Type Notes
key string Stable identifier within the outline (o1, o2, …) — use this to reference a section, not its array index.
level integer Heading level: 1, 2, or 3.
heading string The proposed heading text.
guidance string What to cover under this heading.
source string serp — competitors cover this topic. gap — competitors don't, but we'd add it anyway. own — kept from the page's existing content.
status string proposed (not yet acted on) → accepted / revised (heading text changed) / rejected.
revised_heading string | null The edited heading text, when status: "revised".
node_id string | null The ProseMirror node id once this section has been inserted into the page's document — null until then.

serp_snapshot

serp_snapshot is the competitor research the outline was generated from — the only place this API persists competitor heading structure. It's null if the outline predates snapshot capture or none could be built.

{
  "keyword": "example pricing",
  "results": [
    { "position": 1, "title": "Example Pricing Plans", "url": "https://competitor-a.com/pricing", "snippet": "Compare plans and pricing…" }
  ],
  "competitors": [
    {
      "position": 1,
      "title": "Example Pricing Plans",
      "url": "https://competitor-a.com/pricing",
      "domain": "competitor-a.com",
      "headings": [
        { "level": 1, "text": "Pricing Plans" },
        { "level": 2, "text": "Compare Features" }
      ],
      "word_count": 1450,
      "fetch_error": false
    }
  ]
}

Each competitors[] entry gives you the heading tree MetaMonster extracted from that competitor's page (headings) plus basic metadata (word_count, whether the fetch failed). Competitor body text is never included here or anywhere else in the API — only headings, so you can see how competitors structure content without receiving their copy.

Response 200

{
  "data": {
    "id": 901,
    "page_id": 5001,
    "status": "completed",
    "primary_keyword": "example pricing",
    "sections": [
      { "key": "o1", "level": 1, "heading": "Example Pricing Plans", "guidance": "Restate the primary keyword; set expectations for the page.", "source": "own", "status": "proposed", "revised_heading": null, "node_id": null },
      { "key": "o2", "level": 2, "heading": "Compare Plans Side by Side", "guidance": "A comparison table covering the tiers competitors also cover.", "source": "serp", "status": "proposed", "revised_heading": null, "node_id": null },
      { "key": "o3", "level": 2, "heading": "Annual vs Monthly Billing", "guidance": "Not covered by competitors — a genuine gap worth adding.", "source": "gap", "status": "proposed", "revised_heading": null, "node_id": null }
    ],
    "serp_snapshot": { "keyword": "example pricing", "results": [], "competitors": [] },
    "error": null,
    "triggered_by": null,
    "created_at": "2026-08-10T12:00:00Z",
    "completed_at": "2026-08-10T12:00:42Z",
    "updated_at": "2026-08-10T12:00:42Z"
  }
}

status is pending/processing while generation runs, completed once sections are ready, or failed. A failed outline carries a generic error message ("Outline generation failed") — never raw internals — and empty sections.

Errors

Status When
401 unauthorized Missing/invalid key
403 forbidden Key lacks sites:read
404 not_found No such page in your organization, or the page has never had an outline
429 rate_limited Rate limit exceeded