API Reference

Build on Roman

Use Roman's public API to create articles, manage content workflows, publish to your stack, and bring SEO performance data into your own tools.

Authentication

Public API requests must include a valid Bearer token in the Authorization header. Generate API keys from Settings > API Keys in the dashboard. Keys use the bf_mcp_ prefix and can be scoped for read, write, and AI execution access.

Base URL

https://tryroman.app

Request Header

Authorization: Bearer bf_mcp_your_api_key_here

Scopes

ScopeUse
api:readRead documented resources and analytics. Also covers the read-only AI Visibility API.
api:writeCreate, update, delete, publish, and start documented non-AI operations.
ai:executeRun endpoints that spend AI credits, such as generation, research, and deep analysis.

Example: List Articles

curl -X GET https://tryroman.app/api/articles \
  -H "Authorization: Bearer bf_mcp_your_api_key_here" \
  -H "Content-Type: application/json"

Example: Create an Article

curl -X POST https://tryroman.app/api/articles \
  -H "Authorization: Bearer bf_mcp_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "your-product-id",
    "target_keyword": "best crm for startups",
    "word_range": 2500
	  }'

Responses & Errors

Each endpoint below includes a representative success response. JSON endpoints may include additional fields as the resource grows, so clients should ignore unknown fields and key off stable identifiers, status values, and pagination fields.

Success Response Types

TypeHow to handle it
200 OK - JSONParse the response body as JSON. List endpoints usually return a data array plus pagination or totals.
202 Accepted - JSONThe job was queued or started. Poll the matching detail/status endpoint, or consume the event stream listed in the endpoint note.
text/event-streamRead Server-Sent Events until a done, completed, failed, or error event. Reconnect only if the job is still non-terminal.
application/x-ndjsonProcess one JSON object per line. Treat a final done line as success and an error line as a terminal failure.
binary fileUse the response blob or stream directly. Do not call JSON parsing on export endpoints.

Error Response Shape

Errors return JSON. The error field is safe to show in logs or developer tools. The codefield is the best value to branch on when present.

{
  "error": "API key requires the ai:execute scope for this endpoint.",
  "code": "API_SCOPE_REQUIRED",
  "required_scope": "ai:execute",
  "required_scopes": ["api:write", "ai:execute"]
}

Error Handling Guide

StatusRetryWhat to do
400NoFix the request payload or query parameters before sending again.
401NoCheck that the Bearer token is present, active, and not revoked.
403NoGrant the required scope, use a dashboard session, or switch to a documented public endpoint.
404NoVerify the resource ID and product/account ownership.
409After state changesPoll the active job or wait until the resource reaches a valid state.
429YesBack off, honor Retry-After when present, and add jitter before retrying.
500YesRetry with exponential backoff. Log the method, path, status, and response body.
503YesRetry with backoff. This can happen when auth, billing, provider, or configuration dependencies are temporarily unavailable.

Client Pattern

async function romanFetch(path, options = {}) {
  const res = await fetch(`https://tryroman.app${path}`, {
    ...options,
    headers: {
      Authorization: 'Bearer bf_mcp_your_api_key_here',
      'Content-Type': 'application/json',
      ...(options.headers || {})
    }
  })

  if (!res.ok) {
    const body = await res.json().catch(() => ({}))
    const retryable = [429, 500, 503].includes(res.status)
    throw { status: res.status, retryable, ...body }
  }

  if (res.status === 202) {
    return { accepted: true, body: await res.json() }
  }

  return res.json()
}

Webhook Publishing

Custom webhooks let Roman publish an article to any system that can receive an HTTP POST. Configure the destination in Settings > CMS > Custom Webhook, then publish articles from the dashboard.

Publish Flow

StepWhat happens
1. ConfigureAdd your receiver URL and optional secret in the Custom Webhook settings.
2. TriggerPublish the article from Roman after the webhook destination has been saved.
3. SendRoman posts article content and metadata to your URL as JSON. A request body contentHtml value overrides the saved article HTML for that publish.
4. ConfirmAny 2xx response is treated as success. Roman then marks the article as published and records webhook publish history.
5. FailIf your endpoint is unreachable or returns a non-2xx response, Roman returns an error to the caller and does not mark the article as published.

Outbound Request Headers

Content-Type: application/json
X-Webhook-Secret: your-secret  # only included when configured

Store the same secret in your receiver and compare it with the X-Webhook-Secret header before accepting the payload.

Article Payload

{
  "article_id": "uuid",
  "article_type": "normal_article",
  "article_subtype": "listicle",
  "title": "Article headline or keyword",
  "headline": "Article headline",
  "cover_image_url": "https://cdn.example.com/cover.png",
  "meta_title": "SEO meta title",
  "meta_description": "SEO meta description",
  "target_keyword": "Primary target keyword",
  "content_html": "<p>Full article HTML...</p>",
  "status": "complete",
  "published_at": "2026-06-29T10:30:00.000Z"
}

Payload Fields

FieldDescription
article_idUnique Roman article ID.
article_typeai_visibility_answer for visibility answer articles; otherwise normal_article.
article_subtypeSaved Roman article subtype, such as listicle, comparison, or ai_visibility_answer. May be null.
titleHeadline when available, then meta title, then target keyword.
headlineArticle headline, or null when unset.
cover_image_urlCover image URL, or null when no cover image is set.
meta_titleSEO title, or null when unset.
meta_descriptionSEO description, or null when unset.
target_keywordPrimary keyword the article targets.
content_htmlFull article body as HTML.
statusArticle status at the time the webhook is triggered.
published_atISO 8601 timestamp generated when Roman sends the webhook.

Example Receiver

export async function POST(request: Request) {
  const secret = request.headers.get('X-Webhook-Secret')

  if (secret !== process.env.ROMAN_WEBHOOK_SECRET) {
    return Response.json({ error: 'Unauthorized' }, { status: 401 })
  }

  const article = await request.json()
  await publishArticleToCms({
    id: article.article_id,
    title: article.title,
    html: article.content_html,
    coverImageUrl: article.cover_image_url,
  })

  return Response.json({ ok: true })
}

Testing and Errors

CaseResult
Test webhookThe settings page sends a small JSON test payload to your URL with the same secret header.
No URLThe publish endpoint returns WEBHOOK_NOT_CONFIGURED.
No contentRoman rejects the publish until the article has HTML content.
Receiver errorRoman returns WEBHOOK_FAILED for non-2xx responses and WEBHOOK_ERROR when the URL cannot be reached.

Articles

Create, update, generate, publish, and export articles.

GET/api/articles

List articles

api:read

Retrieve a paginated list of articles with optional filters.

Query Parameters
NameTypeRequiredDescription
pagenumberNoPage number, starting at 0.
limitnumberNoItems per page. Default 20.
searchstringNoSearch by target keyword.
statusesstringNoComma-separated status filter.
product_idsstringNoComma-separated product IDs.
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "target_keyword": "best crm", "status": "draft" }],
  "total": 42,
  "hasMore": true
}
POST/api/articles

Create an article

api:write

Create a draft article record. Use the generation endpoints to produce the outline or content.

Body Parameters
NameTypeRequiredDescription
product_idstringYesProduct ID.
target_keywordstringYesTarget keyword.
search_querystringNoSearch query. Defaults to target_keyword.
custom_instructionsstringNoExtra writing instructions.
word_rangenumberNoTarget word count.
Success Response

200 OK - JSON

{
  "id": "article-id",
  "target_keyword": "best crm for startups",
  "status": "draft"
}
PATCH/api/articles

Bulk update article status

api:write
Body Parameters
NameTypeRequiredDescription
idsstring[]YesArticle IDs to update.
statusstringYesNew status.
Success Response

200 OK - JSON

{ "success": true, "updated": 5 }
DELETE/api/articles

Bulk delete articles

api:write

Permanently delete multiple articles and their associated assets.

Body Parameters
NameTypeRequiredDescription
idsstring[]YesArticle IDs to delete.
Success Response

200 OK - JSON

{ "success": true }
GET/api/articles/:id

Get an article

api:read

Retrieve article content, outline, product, and writing-style details.

Success Response

200 OK - JSON

{
  "id": "...",
  "status": "active",
  "created_at": "2026-06-02T00:00:00.000Z",
  "updated_at": "2026-06-02T00:00:00.000Z"
}
PATCH/api/articles/:id

Update an article

api:write
Body Parameters
NameTypeRequiredDescription
target_keywordstringNoUpdated keyword.
statusstringNoUpdated status.
content_htmlstringNoUpdated HTML content.
outlineobjectNoUpdated outline.
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "updated_at": "2026-06-02T00:00:00.000Z"
}
DELETE/api/articles/:id

Delete an article

api:write
Success Response

200 OK - JSON

{ "success": true }
POST/api/articles/:id/generate-outline

Generate an outline

api:writeai:execute

Starts outline generation and returns 202 Accepted.

Fire-and-forget. Poll the article status or consume generation-events until a terminal event.

Body Parameters
NameTypeRequiredDescription
streambooleanNoWhen true, response includes a progress stream URL.
Success Response

202 Accepted - JSON

{
  "accepted": true,
  "articleId": "...",
  "stream": { "runId": "...", "url": "/api/articles/.../generation-events?runId=..." }
}
POST/api/articles/:id/generate-content

Generate article content

api:writeai:execute

Starts content generation from an existing outline and returns 202 Accepted.

Fire-and-forget. Poll the article status or consume generation-events until a terminal event.

Body Parameters
NameTypeRequiredDescription
keyword_rangesobjectNoSEO keyword ranges.
streambooleanNoWhen true, response includes a progress stream URL.
Success Response

202 Accepted - JSON

{
  "accepted": true,
  "id": "...",
  "status": "queued"
}
POST/api/articles/:id/generate-article

Generate full article

api:writeai:execute

Starts outline and content generation in one background run.

Fire-and-forget. Use generation-events for live progress.

Body Parameters
NameTypeRequiredDescription
streambooleanNoWhen true, response includes a progress stream URL.
Success Response

202 Accepted - JSON

{
  "accepted": true,
  "id": "...",
  "status": "queued"
}
GET/api/articles/:id/generation-events

Stream article generation progress

api:read

Server-Sent Events stream for an accepted outline, content, or full-article generation run.

SSE stream. The stream also emits heartbeat events while the job is running.

Query Parameters
NameTypeRequiredDescription
runIdstringNoGeneration run ID returned by the start endpoint.
kindstringNooutline or content.
Success Response

200 OK - text/event-stream

event: progress
data: {"status":"running","message":"Processing","processed":12,"total":50}

event: done
data: {"status":"completed","id":"..."}
POST/api/articles/:id/generate-links

Generate link suggestions

api:writeai:execute

Return internal and external link suggestions for an article.

Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "status": "created"
}
POST/api/articles/:id/generate-linkedin-post

Generate LinkedIn post draft

api:writeai:execute
Body Parameters
NameTypeRequiredDescription
customVisionstringNoExtra instructions for the post.
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "status": "created"
}
POST/api/articles/:id/publish-cms

Publish to connected CMS

api:write

Publishes an article through the configured CMS integration.

Returns an SSE progress stream.

Success Response

200 OK - text/event-stream

event: progress
data: {"status":"running","message":"Processing","processed":12,"total":50}

event: done
data: {"status":"completed","id":"..."}
POST/api/articles/:id/export-docx

Export as DOCX

api:write

Returns a binary DOCX file.

Body Parameters
NameTypeRequiredDescription
htmlstringYesHTML content to export.
titlestringNoDocument title.
Success Response

200 OK - DOCX file

Binary file response with Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document
GET/api/articles/:id/assets

List article assets

api:read
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "limit": 20,
  "total": 42
}
PATCH/api/articles/:id/assets

Update asset status

api:write
Body Parameters
NameTypeRequiredDescription
assetIdstringYesAsset ID.
statusstringYespending, approved, or rejected.
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "updated_at": "2026-06-02T00:00:00.000Z"
}
DELETE/api/articles/:id/assets

Delete article assets

api:write
Query Parameters
NameTypeRequiredDescription
assetIdstringNoSpecific asset ID to delete.
typestringNoDelete all assets of this type.
Success Response

200 OK - JSON

{ "success": true }
POST/api/articles/bulk-write

Bulk generate articles

api:writeai:execute

Generate content for multiple articles.

Returns one SSE session_created acknowledgement with HTTP 202. Generation runs in a durable server worker; poll GET /api/articles/bulk-write/:sessionId for progress.

Body Parameters
NameTypeRequiredDescription
idsstring[]YesArticle IDs to process.
modestringNooutline_ready_content (default) writes Outline Ready articles; draft_full_article researches, outlines, and writes Draft articles.
Success Response

200 OK - text/event-stream

event: progress
data: {"status":"running","message":"Processing","processed":12,"total":50}

event: done
data: {"status":"completed","id":"..."}
GET/api/articles/bulk-write

List bulk write sessions

api:read
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "limit": 20,
  "total": 42
}
GET/api/articles/bulk-write/:sessionId

Get bulk write session

api:read
Success Response

200 OK - JSON

{
  "id": "...",
  "status": "active",
  "created_at": "2026-06-02T00:00:00.000Z",
  "updated_at": "2026-06-02T00:00:00.000Z"
}
PATCH/api/articles/bulk-write/:sessionId

Update bulk write session

api:write
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "updated_at": "2026-06-02T00:00:00.000Z"
}
POST/api/articles/bulk-publish-cms

Bulk publish to CMS

api:write

Returns an SSE stream with progress.

Success Response

200 OK - text/event-stream

event: progress
data: {"status":"running","message":"Processing","processed":12,"total":50}

event: done
data: {"status":"completed","id":"..."}

Products

Manage products and product research inputs.

GET/api/products

List products

api:read
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "limit": 20,
  "total": 42
}
POST/api/products

Create a product

api:write
Body Parameters
NameTypeRequiredDescription
namestringYesProduct name.
descriptionstringNoProduct description.
sitemap_urlstringNoWebsite or sitemap URL.
writing_styleobjectNoInitial writing style.
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "status": "created"
}
GET/api/products/:id

Get a product

api:read
Success Response

200 OK - JSON

{
  "id": "...",
  "status": "active",
  "created_at": "2026-06-02T00:00:00.000Z",
  "updated_at": "2026-06-02T00:00:00.000Z"
}
PATCH/api/products/:id

Update a product

api:write
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "updated_at": "2026-06-02T00:00:00.000Z"
}
DELETE/api/products/:id

Delete a product

api:write
Success Response

200 OK - JSON

{ "success": true }
POST/api/products/analyze-url

Analyze product URL

api:writeai:execute

Extract product details from a website.

Body Parameters
NameTypeRequiredDescription
urlstringYesWebsite URL.
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "status": "created"
}
POST/api/products/analyze-writing-style

Extract writing style

api:writeai:execute
Body Parameters
NameTypeRequiredDescription
urlsstring[]YesBlog URLs to analyze. Max 5.
productNamestringNoProduct name for context.
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "status": "created"
}
POST/api/products/suggest-positioning

Suggest positioning

api:writeai:execute
Body Parameters
NameTypeRequiredDescription
productobjectYesProduct details.
answersobjectNoOptional questionnaire answers.
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "status": "created"
}
POST/api/products/extract-document

Extract product data from document

api:writeai:execute

Send as multipart/form-data.

Body Parameters
NameTypeRequiredDescription
fileFileYesPDF, TXT, or Markdown file.
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "status": "created"
}

Keywords

Research keywords, inspect SERPs, and move keywords into import batches.

POST/api/keywords/research

Run keyword research

api:writeai:execute
Body Parameters
NameTypeRequiredDescription
keywordsstring[]NoOne to five seed keywords. Use this or seed_keyword.
seed_keywordstringNoLegacy single seed keyword. Use this or keywords.
product_idstringNoProduct ID used to associate saved research and dedupe.
language_codestringNoLanguage code. Defaults to en.
location_codenumberNoDataForSEO location code. Defaults to United States (2840).
Success Response

200 OK - JSON

{
  "query_id": "...",
  "status": "completed",
  "data": []
}
GET/api/keywords/research/history

List keyword research history

api:read
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "limit": 20,
  "total": 42
}
GET/api/keywords/research/:queryId

Get keyword research results

api:read
Success Response

200 OK - JSON

{
  "id": "...",
  "status": "active",
  "created_at": "2026-06-02T00:00:00.000Z",
  "updated_at": "2026-06-02T00:00:00.000Z"
}
POST/api/keywords/research/add-to-import

Add keyword results to import

api:write
Body Parameters
NameTypeRequiredDescription
result_idsstring[]YesKeyword result IDs.
product_idstringYesProduct ID.
batch_idstringNoExisting batch ID.
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "status": "created"
}
POST/api/keywords/research/serp

Fetch SERP competitors

api:write
Body Parameters
NameTypeRequiredDescription
keywordstringYesKeyword to check.
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "status": "created"
}

Bulk Import

Create keyword batches and generate articles in bulk.

GET/api/bulk-import

List keyword import batches

api:read
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "limit": 20,
  "total": 42
}
POST/api/bulk-import

Create keyword import batch

api:write
Body Parameters
NameTypeRequiredDescription
product_idstringYesProduct ID.
keywordsobject[]YesKeyword rows.
namestringNoBatch name.
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "status": "created"
}
GET/api/bulk-import/batch/:batchId

Get import batch

api:read
Success Response

200 OK - JSON

{
  "id": "...",
  "status": "active",
  "created_at": "2026-06-02T00:00:00.000Z",
  "updated_at": "2026-06-02T00:00:00.000Z"
}
PATCH/api/bulk-import/:id

Update a keyword import row

api:write
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "updated_at": "2026-06-02T00:00:00.000Z"
}
DELETE/api/bulk-import/:id

Delete a keyword import row

api:write
Success Response

200 OK - JSON

{ "success": true }
POST/api/bulk-import/generate

Generate from batch

api:writeai:execute

Returns an SSE stream with progress.

Body Parameters
NameTypeRequiredDescription
idsstring[]YesKeyword import IDs to process.
Success Response

200 OK - text/event-stream

event: progress
data: {"status":"running","message":"Processing","processed":12,"total":50}

event: done
data: {"status":"completed","id":"..."}

Content Import

Import existing content from sitemaps or connected CMS providers.

GET/api/content-import

List content import batches

api:read
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "limit": 20,
  "total": 42
}
POST/api/content-import/batch

Create content import batch

api:write
Body Parameters
NameTypeRequiredDescription
product_idstringYesProduct ID.
source_typestringYessitemap or CMS provider.
sitemap_urlstringNoSitemap URL for sitemap imports.
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "status": "created"
}
GET/api/content-import/batch/:batchId

Get content import batch

api:read
Success Response

200 OK - JSON

{
  "id": "...",
  "status": "active",
  "created_at": "2026-06-02T00:00:00.000Z",
  "updated_at": "2026-06-02T00:00:00.000Z"
}
GET/api/content-import/batch/:batchId/events

Stream content import progress

api:read

SSE stream.

Success Response

200 OK - text/event-stream

event: progress
data: {"status":"running","message":"Processing","processed":12,"total":50}

event: done
data: {"status":"completed","id":"..."}
POST/api/content-import/fetch

Fetch source content

api:write

Returns an SSE stream.

Success Response

200 OK - text/event-stream

event: progress
data: {"status":"running","message":"Processing","processed":12,"total":50}

event: done
data: {"status":"completed","id":"..."}
POST/api/content-import/import

Import fetched content as articles

api:write

Returns an SSE stream.

Success Response

200 OK - text/event-stream

event: progress
data: {"status":"running","message":"Processing","processed":12,"total":50}

event: done
data: {"status":"completed","id":"..."}

AI Visibility

Read-only visibility, citation, prompt, competitor, alert, and run data.

GET/api/ai-visibility/overview

Get AI Visibility overview

api:read

Returns aggregate metrics, trend points, provider breakdowns, top prompts to fix, alerts, and suggestions.

Query Parameters
NameTypeRequiredDescription
product_idstringNoProduct ID. Defaults to the active product.
windownumberNoLookback window in days.
Success Response

200 OK - JSON

{
  "visibility_score": 72,
  "share_of_voice": 0.34,
  "citation_rate": 0.61,
  "providers": [{ "provider": "chatgpt", "visibility_score": 76 }],
  "alerts": [],
  "suggestions": []
}
GET/api/ai-visibility/settings

Get AI Visibility settings

api:read

Read the configured brand, competitors, aliases, providers, cadence, and setup state.

Query Parameters
NameTypeRequiredDescription
product_idstringNoProduct ID. Defaults to the active product.
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "page_size": 20,
  "total": 42
}
GET/api/ai-visibility/prompts

List tracked prompts

api:read
Query Parameters
NameTypeRequiredDescription
product_idstringNoProduct ID.
pagenumberNoPage number. Default 1.
page_sizenumberNoPage size. Max 100.
activebooleanNoSet false to list inactive prompts.
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "page_size": 20,
  "total": 42
}
GET/api/ai-visibility/prompts/:id

Get prompt detail

api:read

Returns prompt metrics, provider responses, citations, fan-out queries, competitor rows, and timeline data.

Query Parameters
NameTypeRequiredDescription
pagenumberNoResponse page number.
page_sizenumberNoResponse page size. Max 50.
citation_pagenumberNoCitation page number.
citation_page_sizenumberNoCitation page size. Max 50.
Success Response

200 OK - JSON

{
  "prompt": { "id": "...", "text": "...", "active": true },
  "metrics": { "visibility_score": 72, "share_of_voice": 0.34 },
  "responses": { "data": [], "page": 1, "page_size": 20 },
  "citations": { "data": [], "page": 1, "page_size": 20 }
}
GET/api/ai-visibility/citations

List AI Visibility citations

api:read
Query Parameters
NameTypeRequiredDescription
product_idstringNoProduct ID.
providerstringNoProvider filter.
categorystringNoCitation category filter.
prompt_idstringNoPrompt filter.
date_fromstringNoStart date.
date_tostringNoEnd date.
viewstringNoall or own.
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "page_size": 20,
  "total": 42
}
GET/api/ai-visibility/competitors

List competitor profiles

api:read

Returns lightweight competitor profile summaries with AI visibility, share of voice, citation rate, citation URL count, and stable identifiers.

Query Parameters
NameTypeRequiredDescription
product_idstringNoProduct ID.
competitorstringNoStable competitor identifier or legacy name used to scope gap_prompts.
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "page_size": 20,
  "total": 42
}
GET/api/ai-visibility/competitors/:competitor

Get competitor profile

api:read

Returns one competitor profile and a paginated list of citation URLs. Each URL carries its content category and a per-prompt breakdown of where it was cited. The competitor path value is the stable identifier returned by the list endpoint; legacy encoded names are also accepted.

Query Parameters
NameTypeRequiredDescription
product_idstringNoProduct ID.
pagenumberNoCitation URL page number. Default 1. Clamped to the last page of the filtered set.
page_sizenumberNoCitation URL page size. Max 100.
citation_categorystringNoFilter citation URLs by content category (listicle, marketing_page, comparison, …).
citation_providerstringNoFilter citation URLs by AI engine.
citation_promptstringNoFilter citation URLs to those cited under one prompt id.
citation_searchstringNoFree-text match against citation URL and title. Max 200 chars.
date_fromstringNoStart date.
date_tostringNoEnd date.
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "page_size": 20,
  "total": 42
}
GET/api/ai-visibility/alerts

List AI Visibility alerts

api:read
Query Parameters
NameTypeRequiredDescription
product_idstringNoProduct ID.
statusstringNoAlert status filter.
pagenumberNoPage number.
page_sizenumberNoPage size. Max 100.
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "page_size": 20,
  "total": 42
}
GET/api/ai-visibility/suggestions

List AI Visibility suggestions

api:read
Query Parameters
NameTypeRequiredDescription
product_idstringNoProduct ID.
statusstringNoSuggestion status filter.
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "page_size": 20,
  "total": 42
}
GET/api/ai-visibility/runs

List AI Visibility runs

api:read
Query Parameters
NameTypeRequiredDescription
product_idstringNoProduct ID.
pagenumberNoPage number.
page_sizenumberNoPage size. Max 100.
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "page_size": 20,
  "total": 42
}

SEO Audits

Create, inspect, and process technical SEO audits.

GET/api/seo-audit

List audits

api:read
Query Parameters
NameTypeRequiredDescription
product_idstringNoProduct ID filter.
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "limit": 20,
  "total": 42
}
POST/api/seo-audit

Create an audit

api:write

Creates an audit job and auto-starts background processing when possible.

Background job. Read GET /api/seo-audit/:id for status and page counts.

Body Parameters
NameTypeRequiredDescription
product_idstringNoProduct ID.
sitemap_urlstringNoWebsite or sitemap URL.
urlsstring[]NoExplicit URLs to audit.
modestringNofull or lite.
skip_lighthousebooleanNoSkip Lighthouse analysis.
Success Response

202 Accepted - JSON

{
  "accepted": true,
  "id": "...",
  "status": "queued"
}
GET/api/seo-audit/:id

Get audit details

api:read
Query Parameters
NameTypeRequiredDescription
slimbooleanNoLightweight polling mode.
no_pagesbooleanNoReturn audit metadata without page rows.
Success Response

200 OK - JSON

{
  "id": "...",
  "status": "active",
  "created_at": "2026-06-02T00:00:00.000Z",
  "updated_at": "2026-06-02T00:00:00.000Z"
}
DELETE/api/seo-audit/:id

Delete an audit

api:write
Success Response

200 OK - JSON

{ "success": true }
POST/api/seo-audit/:id/process

Start or continue audit processing

api:write

Idempotently queues durable processing and returns persisted progress, hasMore, and generic runtime estimates.

Returns 409 with { paused: true } while paused. Poll the audit details endpoint for completion.

Success Response

200 OK - JSON

{
  "progress": { "total": 160, "crawled": 42, "analyzed": 37 },
  "hasMore": true,
  "pages": [],
  "crawlRuntime": {
    "phase": "crawling",
    "currentUrl": "https://example.com/docs",
    "processedUrls": 42,
    "analyzedUrls": 37,
    "totalUrls": 160,
    "failedUrls": 1,
    "discardedUrls": 0,
    "estimatedCostUsd": 0.21,
    "crawlTargetSeconds": 1080,
    "crawlEtaSeconds": 708,
    "analysisEtaSeconds": 738,
    "summaryEtaSeconds": 60,
    "overallEtaSeconds": 798,
    "lastHeartbeatAt": "2026-07-15T12:00:00.000Z"
  }
}
POST/api/seo-audit/:id/summary

Get or queue the audit summary

api:writeai:execute

Completed audits return the durable summary immediately. Active audits queue durable processing and return persisted progress.

Clients must handle 200, 202, and 409 responses; an active request does not synchronously generate a summary.

Success Response

200 OK - JSON

// 200 — completed
{ "summary": { "overallScore": 82 }, "linkGraph": { "stats": { "totalPages": 160 } } }

// 202 — active
{ "queued": true, "progress": { "total": 160, "crawled": 42, "analyzed": 37 }, "hasMore": true }

// 409 — paused
{ "paused": true }

// 409 — failed
{ "error": "Resume, restart, or run a Deep Scan before requesting the summary." }
POST/api/seo-audit/:id/link-analysis

Run link analysis

api:writeai:execute

Returns an SSE stream with progress.

Success Response

200 OK - text/event-stream

event: progress
data: {"status":"running","message":"Processing","processed":12,"total":50}

event: done
data: {"status":"completed","id":"..."}
GET/api/seo-audit/:id/insights

Get audit insights

api:read
Success Response

200 OK - JSON

{
  "id": "...",
  "status": "active",
  "created_at": "2026-06-02T00:00:00.000Z",
  "updated_at": "2026-06-02T00:00:00.000Z"
}
GET/api/seo-audit/:id/page/:pageId

Get audited page details

api:read
Success Response

200 OK - JSON

{
  "id": "...",
  "status": "active",
  "created_at": "2026-06-02T00:00:00.000Z",
  "updated_at": "2026-06-02T00:00:00.000Z"
}
POST/api/seo-audit/:id/page/:pageId/deep-analysis

Run deep page analysis

api:writeai:execute

Returns an SSE stream with progress.

Success Response

200 OK - text/event-stream

event: progress
data: {"status":"running","message":"Processing","processed":12,"total":50}

event: done
data: {"status":"completed","id":"..."}
POST/api/seo-audit/preview-sitemap

Preview sitemap URLs

api:write
Body Parameters
NameTypeRequiredDescription
product_idstringYesProduct ID.
Success Response

200 OK - JSON

{
  "success": true,
  "id": "...",
  "status": "created"
}

Search Console

Read cached Google Search Console performance data.

GET/api/gsc/connections

List Search Console connections

api:read
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "limit": 20,
  "total": 42
}
GET/api/gsc/performance

Get performance data

api:read
Query Parameters
NameTypeRequiredDescription
product_idstringYesProduct ID.
date_fromstringNoStart date.
date_tostringNoEnd date.
article_idstringNoArticle filter.
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "limit": 20,
  "total": 42
}
GET/api/gsc/top-queries

Get top search queries

api:read
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "limit": 20,
  "total": 42
}
GET/api/gsc/article-analytics

Get article analytics

api:read
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "limit": 20,
  "total": 42
}
GET/api/gsc/site-analytics

Get site analytics

api:read
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "limit": 20,
  "total": 42
}
GET/api/gsc/pages

Get page-level performance

api:read
Success Response

200 OK - JSON

{
  "data": [{ "id": "...", "status": "active" }],
  "page": 1,
  "limit": 20,
  "total": 42
}
GET/api/gsc/agent-suggestions

Get Search Console suggestions

api:read
Success Response

200 OK - JSON

{
  "id": "...",
  "status": "active",
  "created_at": "2026-06-02T00:00:00.000Z",
  "updated_at": "2026-06-02T00:00:00.000Z"
}