Skip to Content
DevelopersSDKSDK Reference

SDK Reference

Conventions

A few things hold for every method on this page:

  • You destructure data. Each call returns { data, request, response }; data is the parsed body. TypeScript types it as possibly undefined, so examples write data! — see the Quickstart for why.
  • Envelopes. A single resource returns { item }, a list returns { items }, and a paginated list returns { items, pagination } where pagination is { page, limit, total, totalPages, hasMore }. Paging is manual.
  • Errors throw. Any non-2xx response throws a CompetLabError with status, code, and message. It’s not a returned value; you catch it.
  • Types are exported. Every response type named below (ProjectDetailResponse, PaginationMeta, and the rest) is exported from @competlab/sdk for you to import.

Construct the client once and reuse it:

import CompetLab from '@competlab/sdk'; const cl = new CompetLab({ apiKey: process.env.COMPETLAB_API_KEY! });

health

Service liveness. The one method that needs no API key.

MethodParametersReturnsEndpoint
cl.health.check(){ item: HealthResponse }GET /v1/health

projects

Your projects — the top of every other call, since most methods take a projectId.

MethodParametersReturnsEndpoint
cl.projects.list(){ items: ProjectListItemResponse[] }GET /v1/projects
cl.projects.get(projectId)projectId: string{ item: ProjectDetailResponse }GET /v1/projects/{projectId}

competitors

The competitors tracked within a project.

MethodParametersReturnsEndpoint
cl.competitors.list(projectId)projectId: string{ items: CompetitorListItemResponse[] }GET /v1/projects/{projectId}/competitors
cl.competitors.get(projectId, competitorId)projectId: string, competitorId: string{ item: CompetitorDetailResponse }GET /v1/projects/{projectId}/competitors/{competitorId}

aiVisibility

How the AI engines mention your brand versus competitors — dashboard, history, one check’s detail, and a provider trend over time.

MethodParametersReturnsEndpoint
cl.aiVisibility.dashboard(projectId)projectId: string{ item: AiVisibilityDashboardResponse }GET …/ai-visibility
cl.aiVisibility.history(projectId, query?)query?: { page?, limit? }{ items: AiVisibilityHistoryItemResponse[], pagination }GET …/ai-visibility/history
cl.aiVisibility.checkDetail(projectId, checkId)projectId: string, checkId: string{ item: AiVisibilityCheckDetailResponse }GET …/ai-visibility/history/{checkId}
cl.aiVisibility.trend(projectId, query?)query?: { dateFrom?, dateTo?, provider? }{ items: AiVisibilityTrendDataPointResponse[] }GET …/ai-visibility/trend

The provider filter takes an AiProvider: 'openai' | 'claude' | 'gemini'. Note the wire value for ChatGPT is 'openai'cl.aiVisibility.trend(projectId, { provider: 'openai' }). The trend method returns a plain { items } list, not a paginated one.

positioning

Where you sit in the market narrative — dashboard, history, and one run’s detail.

MethodParametersReturnsEndpoint
cl.positioning.dashboard(projectId)projectId: string{ item: PositioningDashboardResponse }GET …/positioning
cl.positioning.history(projectId, query?)query?: { page?, limit? }{ items: PositioningHistoryItemResponse[], pagination }GET …/positioning/history
cl.positioning.runDetail(projectId, runId)projectId: string, runId: string{ item: PositioningRunDetailResponse }GET …/positioning/history/{runId}

pricing

Competitor pricing and plan changes — dashboard, history, and one run’s detail.

MethodParametersReturnsEndpoint
cl.pricing.dashboard(projectId)projectId: string{ item: PricingDashboardResponse }GET …/pricing
cl.pricing.history(projectId, query?)query?: { page?, limit? }{ items: PricingHistoryItemResponse[], pagination }GET …/pricing/history
cl.pricing.runDetail(projectId, runId)projectId: string, runId: string{ item: PricingRunDetailResponse }GET …/pricing/history/{runId}

content

Competitor content and messaging changes — dashboard, history, run detail, and a changelog of what changed.

MethodParametersReturnsEndpoint
cl.content.dashboard(projectId)projectId: string{ item: ContentDashboardResponse }GET …/content
cl.content.history(projectId, query?)query?: { page?, limit? }{ items: ContentHistoryItemResponse[], pagination }GET …/content/history
cl.content.runDetail(projectId, runId)projectId: string, runId: string{ item: ContentRunDetailResponse }GET …/content/history/{runId}
cl.content.changelog(projectId, query?)query?: { page?, limit?, competitorId?, category?, allUrlsPerCategory? }{ items: ContentChangelogItemResponse[], pagination, truncated }GET …/content/changelog

The changelog adds a truncated boolean to the envelope, set when the result was capped.

techTrust

Tech stack and trust signals — dashboard, history, and one run’s detail.

MethodParametersReturnsEndpoint
cl.techTrust.dashboard(projectId)projectId: string{ item: TechTrustDashboardResponse }GET …/tech-trust
cl.techTrust.history(projectId, query?)query?: { page?, limit? }{ items: TechTrustHistoryItemResponse[], pagination }GET …/tech-trust/history
cl.techTrust.runDetail(projectId, runId)projectId: string, runId: string{ item: TechTrustRunDetailResponse }GET …/tech-trust/history/{runId}

alerts

Notable changes surfaced across the dimensions, filterable.

MethodParametersReturnsEndpoint
cl.alerts.list(projectId, query?)query?: { page?, limit?, dimension?, severity?, competitorId? }{ items: AlertListItemResponse[], pagination }GET …/alerts

dimension is one of tech-trust, content, positioning, pricing, ai-visibility; severity is one of critical, high, medium, info.

schedules

The monitoring cadence configured for a project.

MethodParametersReturnsEndpoint
cl.schedules.list(projectId)projectId: string{ items: ScheduleItemResponse[] }GET …/schedules

strategicBriefing

The synthesized monthly read across every dimension. Its envelope is the one exception to the { item } pattern.

MethodParametersReturnsEndpoint
cl.strategicBriefing.get(projectId, query?)query?: { sections?, includeCharts? }{ item, meta, coverage, dimensionHealth }GET …/strategic-briefing

Check meta.availability'ready' | 'ready-refreshing' | 'preparing' | 'none' — before reading item, which is null until the first edition is ready. Pass sections to fetch specific parts (e.g. ['deep-ai-visibility', 'actions']) and includeCharts: true for chart data.

const { data } = await cl.strategicBriefing.get(projectId, { sections: ['deep-ai-visibility', 'actions'], includeCharts: true, }); if (data!.meta.availability === 'ready') { console.log(data!.item); }

tools

The free scan tools — the same public scans the MCP server exposes. These don’t take a projectId; they run against a URL you give them. Three return their result directly; the other three are asynchronous scans you start and then poll.

Direct (one call, result inline):

MethodParametersReturnsEndpoint
cl.tools.sitemapVisualizer(body)body{ item: SitemapVisualizerToolResponse }POST /v1/tools/sitemap-visualizer
cl.tools.aiCrawlerChecker(body)body{ item: AiCrawlerCheckerToolResponse }POST /v1/tools/ai-crawler-checker
cl.tools.fetchUrl(body)body: { url, bodyNeeded?, headersNeeded?, cleanHtml?, maxTimeoutMs?, bodyMaxBytes? }{ item: FetchUrlToolResponse }POST /v1/tools/fetch-url

Async scans (start, then poll — see the Quickstart):

MethodParametersReturnsEndpoint
cl.tools.techStack.startScan(body)body (e.g. { domain }){ item: TechStackScanResponse }POST /v1/tools/tech-stack/scans
cl.tools.techStack.getScan(scanId)scanId: string{ item: TechStackScanResponse }GET /v1/tools/tech-stack/scans/{scanId}
cl.tools.trustSignals.startScan(body)body (e.g. { domain }){ item: TrustSignalsScanResponse }POST /v1/tools/trust-signals/scans
cl.tools.trustSignals.getScan(scanId)scanId: string{ item: TrustSignalsScanResponse }GET /v1/tools/trust-signals/scans/{scanId}
cl.tools.agentAdoption.startScan(body)body (e.g. { domain }){ item: AgentAdoptionScanResponse }POST /v1/tools/agent-adoption/scans
cl.tools.agentAdoption.getScan(scanId)scanId: string{ item: AgentAdoptionScanResponse }GET /v1/tools/agent-adoption/scans/{scanId}

A scan response carries status'queued' | 'running' | 'completed' | 'failed' — with result present once completed and error present if failed. Scan IDs expire after 24 hours. Of the scan request bodies, only fetchUrl’s is strongly typed; the scanners accept an open object where the domain field is what they read.

Full method map

All 34 methods, at a glance:

health check projects list · get competitors list · get aiVisibility dashboard · history · checkDetail · trend positioning dashboard · history · runDetail pricing dashboard · history · runDetail content dashboard · history · runDetail · changelog techTrust dashboard · history · runDetail alerts list schedules list strategicBriefing get tools sitemapVisualizer · aiCrawlerChecker · fetchUrl techStack.{startScan,getScan} trustSignals.{startScan,getScan} agentAdoption.{startScan,getScan}

For the underlying HTTP — status codes, full request and response schemas, error codes — see the REST API reference. The SDK is a typed layer over exactly those endpoints.

Last updated on