Collimer API

API changes

Run a free AI-search visibility scan on any website (how visible a brand is in ChatGPT, Perplexity, Google AI, etc.) and read back a score, confidence interval, the biggest gap, and a branded report URL.

Depth-gating: the public API returns the score + top gap + report URL only. The full ranked fix plan and verification re-scan unlock with a free account on the web.

1. Start a scan

curl -X POST https://app.collimer.com/api/v1/scan \
  -H 'Authorization: Bearer <key>' \
  -H 'content-type: application/json' \
  -d '{"url":"example.com","source":"agent"}'

→ 201 { scan_token, status, poll_url, report_url }

2. Poll for the teaser

curl -H 'Authorization: Bearer <key>' https://app.collimer.com/api/v1/scan/<scan_token>

→ 202 while running, then 200 with the teaser (score, confidence_interval, top_gap, report_url, cta_url).

Writing and workflow API (/api/v0)

Base URL: https://app.collimer.com/api/v0. This version is unstable and can change. It exposes the writing workflow, brands, work, recommendations, audits, and scans. Send an API key or OAuth access token as Authorization: Bearer <token>. The /api/v0/openapi.json spec lists every operation, its required scope, parameters, and response shape. Some writing operations require writing access for the acting organization.

Successful JSON responses use {"data": {...}, "resolved": {...}, "hint": "next step", "url": "..."}. resolved echoes what the request matched; url is a UI link or null.

Some long-running operations return 202 with a receipt rather than a finished result. For example, POST /api/v0/articles/{id}/stat-candidates/find returns data.status: "pending" and data.receipt_id. Poll GET /api/v0/articles/{id}/writing-jobs/stat_candidates/{receipt_id} until data.status is done or failed. Other asynchronous operations have their own poll paths in the spec and response hint.

Errors

/api/v1 and /api/v0 errors use the same shape:

{"error": {"code": "rate_limited", "message": "Too many requests — try again later.", "retry_after": 60}}

code is a stable machine token, message is human text and may change, retry_after (seconds) is present only on 429/503 and mirrors the Retry-After response header. (/oauth/* and /mcp use their own spec-mandated error shapes instead.)

For /api/v0, common statuses include 400 for an invalid cursor or limit, 401 for an invalid credential, 403 for a missing scope, 404 for an unavailable resource, 409 for a state conflict, 422 for invalid input, and 429 for a rate limit or another active job. Branch on error.code; consult the v0 spec for operation-specific errors.

Authentication

Both scan routes require a bearer credential with scans:write. Read-only API keys and viewer grants receive 403. Create an API key at /connect; an OAuth access token also works. The public docs remain available before sign-in so you can inspect the API before requesting access.

Running headless with OAuth

Complete OAuth consent once interactively, requesting offline_access with the scopes your runner needs. Store the returned refresh token securely. Before the access token expires, refresh it through /oauth/token and persist the new refresh token after every refresh; the old token cannot be used again. A refresh token expires after 90 days without use. Give each parallel runner its own OAuth connection: sharing one refresh token can trigger reuse detection and revoke the grant. An API key from /connect is another option for unattended /api/v0 calls, but API keys cannot authenticate /mcp.

Pagination

List endpoints take ?limit= (max 50) and ?after=<cursor>. Pass the previous page's next_cursor as after to fetch the next page; it's null on the last page. The cursor is opaque — treat it as an unparseable token, not an offset. GET /api/v0/work defaults to 25; other list endpoints may have their own defaults, so check their spec entries.

Machine-readable

Run it inside an agent

Connect an MCP-capable client to the live Streamable HTTP endpoint /mcp with OAuth. Its server card describes the available tools. Scans initiated through the API can use source: "mcp" or source: "agent".