Skip to Content
DocsDevelopersAPI ReferenceStrategic Briefing

Strategic Briefing

REST endpoints for Strategic Briefing. Base URL https://api.competlab.com; every request needs a CL-API-Key header (see Authentication). Responses wrap in { item } or { items }; errors in { error }.

Get the current state of this project’s strategic briefing

GET/v1/projects/{projectId}/strategic-briefing

Get the current state of this project’s strategic briefing — the synthesized, as-of competitive read (what changed, what it means, what to do). This is the ANALYZED briefing; for the raw monitoring data use the per-dimension dashboards (e.g. /pricing), and for the monitored-competitor roster use /competitors.

This returns the LATEST run, whatever state it is in. meta.status is that run’s raw lifecycle status and is the field to branch on:

  • done — the run finished. item, coverage and contains are populated; this is the readable edition.
  • running — a briefing is being generated right now. item is null; meta.progress carries the step it is on and when it started. A typical run finishes in about 90 minutes and a healthy one can take up to ~2 hours — budget rather than busy-wait, and do not treat a run as late before then.
  • failed — the most recent attempt ended without producing an edition. item is null. A failed run does not resume the ~30-day cycle, so surface it rather than waiting it out.
  • null — this project has never had a briefing run at all. This is the only value that means the project genuinely has nothing.

When meta.status is not done, THIS RUN has no content — which says nothing about whether the project has a briefing. A previously published edition is usually still readable: call GET /v1/projects/{projectId}/strategic-briefing/history to list the editions and …/history/{runId} to read one. Never report that no briefing is available on the strength of a null item — check history first.

A missing or non-accessible project returns 404 project_not_found; the briefing lifecycle itself never 404s.

Sections — lean by default. sections selects what to return and defaults to ["hub"] — the executive digest AND the navigation map. Each hub diagnosis row carries a deepDive pointer naming the dimension to read next; prefix it with deep- to form the section value (a pointer of ai-visibility → request sections=deep-ai-visibility). Valid sections: hub, actions, competitors, the thirteen deep-<dimension> deep-dives, or all for the full document. Charts are off by default (includeCharts=false returns each chart’s title + note only); pass includeCharts=true for the full data series.

Returned with any finished edition, regardless of sections: coverage (methodology and data-quality caveats — read these before quoting any figure) and contains (the list of sections this edition actually holds, so you can pick what to fetch next instead of requesting slots blind). Both are null whenever meta.status is not done, which says nothing about whether earlier editions exist — check …/history.

Reading the numbers: the AI Visibility Score is 0–100 (higher is better); an AI rank is ordinal (lower is better); action impact is 1–4 (higher is more critical); action effort is bucketed as effortMinutes (<30 | 30-120 | >120, or null when the briefing gave that action no estimate — report it as unsized rather than as quick). A project’s next briefing is scheduled approximately 30 days after its last successful one.

Returns · { meta, item, coverage, contains }

Path parameters

NameTypeDescription
projectIdstringProject ID

Query parameters

NameTypeRequiredDescription
sectionsarray<string>Which sections to return. Defaults to [“hub”] — the executive digest and navigation map. Pass specific sections to go deeper (e.g. a hub diagnosis pointer of ai-visibility maps to deep-ai-visibility), or all for the full document. Prefer deriving deep-<dimension> values from the hub diagnosis pointers rather than requesting slots blind — the response’s contains array lists exactly which sections exist for this edition, in this same vocabulary.
includeChartsbooleanInclude full chart series data. Defaults to false — each chart returns its title and note only, with no underlying numbers. Pass true for the full series. Default false.

Request

curl "https://api.competlab.com/v1/projects/507f1f77bcf86cd799439011/strategic-briefing?sections=hub&includeCharts=false" \ -H "CL-API-Key: YOUR_COMPETLAB_API_KEY"

Response 200 OK

{ "meta": { "runId": "6a3950c06bda450a1372048e", "status": "done", "editionNumber": 4, "startedAt": "2026-06-22T14:20:02.110Z", "briefingDate": "2026-06-22T15:51:24.443Z", "progress": { "step": "researching", "startedAt": "2026-07-27T06:00:11.002Z", "updatedAt": "2026-07-27T06:41:03.771Z" } }, "item": { "hub": { "kind": "hub", "blocks": [ { "type": "headline", "verdict": "Pricing pressure is rising." } ] } }, "coverage": { "type": "coverage", "items": [ "review counts are directional" ] }, "contains": [ "hub", "actions", "competitors", "deep-ai-visibility", "deep-pricing" ] }

Errors

StatusCodeMeaning
401api_key_missing · api_key_invalid · api_key_revoked · api_key_expired · insufficient_scopeThe CL-API-Key is missing, malformed, revoked, expired, or lacks the required scope.
404project_not_foundNo project matches the id in the path.

Every error uses the shared { error: { code, message, status } } envelope; code is one of the values listed above.

{ "error": { "code": "api_key_invalid", "message": "Invalid API key", "status": 401 } }

List this project’s briefing editions

GET/v1/projects/{projectId}/strategic-briefing/history

List this project’s Strategic Briefing runs, newest first — one cheap metadata row each, never briefing content.

Each row carries runId (pass it to …/history/{runId} to read that edition in full), briefingDate, status, the derived editionNumber, and headline — that edition’s one-line verdict, so you can pick which one to open without fetching every one.

Runs that failed or are still generating are included, with editionNumber, briefingDate and headline null. A gap between two editions is therefore explained rather than left unexplained.

Use this to answer “what did we say in April”, to trace how a read has changed over time, or — when GET /strategic-briefing reports a running or failed status — to find the last edition that is actually readable. For the current state use GET /strategic-briefing, not this.

Paginated with page and limit; check pagination.hasMore to fetch further pages. Briefings are produced roughly monthly, so this list is typically short.

Returns · { items, pagination }

Path parameters

NameTypeDescription
projectIdstringProject ID

Query parameters

NameTypeRequiredDescription
pagenumberPage number (1-indexed). Default 1. Min 1.
limitnumberNumber of items per page. Default 20. Range 1100.

Request

curl "https://api.competlab.com/v1/projects/507f1f77bcf86cd799439011/strategic-briefing/history?page=1&limit=20" \ -H "CL-API-Key: YOUR_COMPETLAB_API_KEY"

Response 200 OK

{ "items": [ { "runId": "6a3950c06bda450a1372048e", "editionNumber": 4, "briefingDate": "2026-06-22T15:51:24.443Z", "documentDate": "2026-06-22", "status": "done", "headline": "Pricing pressure is rising in your segment." } ], "pagination": { "page": 1, "limit": 20, "total": 47, "totalPages": 3, "hasMore": true } }

Paginated — pass page and limit query parameters and follow pagination.hasMore to page through the full set.

Errors

StatusCodeMeaning
401api_key_missing · api_key_invalid · api_key_revoked · api_key_expired · insufficient_scopeThe CL-API-Key is missing, malformed, revoked, expired, or lacks the required scope.

Every error uses the shared { error: { code, message, status } } envelope; code is one of the values listed above.

{ "error": { "code": "api_key_invalid", "message": "Invalid API key", "status": 401 } }

Get one briefing edition by id

GET/v1/projects/{projectId}/strategic-briefing/history/{runId}

Get one strategic briefing edition by runId, in exactly the same shape as GET /strategic-briefing.

Take the runId from GET /strategic-briefing/history (or from meta.runId on a current read). Accepts the same sections and includeCharts options, with the same ["hub"] default.

A runId naming a run that failed or is still generating returns 200 with meta.status set accordingly and item null — that run genuinely produced no edition, which is an answer rather than an error. A malformed id returns 400 invalid_run_id; an id that does not belong to this project returns 404 run_not_found.

Use this to read or quote a specific past edition. For the current state use GET /strategic-briefing.

Returns · { meta, item, coverage, contains }

Path parameters

NameTypeDescription
runIdstringBriefing run ID, from meta.runId or a history row
projectIdstringProject ID

Query parameters

NameTypeRequiredDescription
sectionsarray<string>Which sections to return. Defaults to [“hub”] — the executive digest and navigation map. Pass specific sections to go deeper (e.g. a hub diagnosis pointer of ai-visibility maps to deep-ai-visibility), or all for the full document. Prefer deriving deep-<dimension> values from the hub diagnosis pointers rather than requesting slots blind — the response’s contains array lists exactly which sections exist for this edition, in this same vocabulary.
includeChartsbooleanInclude full chart series data. Defaults to false — each chart returns its title and note only, with no underlying numbers. Pass true for the full series. Default false.

Request

curl "https://api.competlab.com/v1/projects/507f1f77bcf86cd799439011/strategic-briefing/history/6a3950c06bda450a1372048e?sections=hub&includeCharts=false" \ -H "CL-API-Key: YOUR_COMPETLAB_API_KEY"

Response 200 OK

{ "meta": { "runId": "6a3950c06bda450a1372048e", "status": "done", "editionNumber": 4, "startedAt": "2026-06-22T14:20:02.110Z", "briefingDate": "2026-06-22T15:51:24.443Z", "progress": { "step": "researching", "startedAt": "2026-07-27T06:00:11.002Z", "updatedAt": "2026-07-27T06:41:03.771Z" } }, "item": { "hub": { "kind": "hub", "blocks": [ { "type": "headline", "verdict": "Pricing pressure is rising." } ] } }, "coverage": { "type": "coverage", "items": [ "review counts are directional" ] }, "contains": [ "hub", "actions", "competitors", "deep-ai-visibility", "deep-pricing" ] }

Errors

StatusCodeMeaning
400invalid_parameters · invalid_run_id · invalid_check_idBad request — the payload failed validation.
401api_key_missing · api_key_invalid · api_key_revoked · api_key_expired · insufficient_scopeThe CL-API-Key is missing, malformed, revoked, expired, or lacks the required scope.
404run_not_foundNo run matches the id in the path.

Every error uses the shared { error: { code, message, status } } envelope; code is one of the values listed above.

{ "error": { "code": "invalid_parameters", "message": "Domain is required", "status": 400 } }
Last updated on