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 |