Developer reference · REST

Keyed REST API

Ordinary HTTP against a bearer key. The same records the application and the MCP connector read, exposed as 13 routes under /api/v2.

Authentication

Send a key as a bearer credential. The key resolves the organization, and the brand comes from the key or from the request. No route takes a brand id in its path.

curl https://app.optimly.ai/api/v2/brand \
  -H "Authorization: Bearer $OPTIMLY_KEY" \
  -H "X-Optimly-Brand: $BRAND_ID"

Every brand in the organization

An sk_live_… key created under Connections, shown once, with its scope left on every brand — the default. Each request selects one with an X-Optimly-Brand header, and GET /api/v2/brands lists the ids it accepts. The same key works on the MCP connector, where the tool call carries the brand instead of a header.

One brand

The same key, created with a single brand chosen. It pins that brand, so no request needs to name one, and a selector naming a different brand is ignored rather than obeyed.

Routes

MethodPathReturns
GET /api/v2/brands Every brand in the key's org, ordered by name — the ids an `X-Optimly-Brand` selector accepts. A brand-scoped key sees only its own brand.
GET /api/v2/brand Identity meta: name, canonical domain, slugs, and claim state.
GET /api/v2/vault The active vault — every section with its `publish_state`, plus competitors and disambiguation.
PUT /api/v2/vault Update and publish. Partial updates are allowed: sections you omit copy forward. Recorded with `origin_source='api'`.
GET /api/v2/recommendations Every recommendation for the key's brand.
PATCH /api/v2/recommendations/{rec_id} Act on a recommendation. `acted_by` stays NULL — the key acted, not a signed-in user — so the attribution overlay reads `acted_at` alone.
GET /api/v2/reports Every report for the key's brand, newest version first.
GET /api/v2/reports/{report_id} Report detail: the frozen summary metrics and the run's panel snapshot.
GET /api/v2/reports/{report_id}/questions Question Analysis: every question with its per-model answers and judgments.
GET /api/v2/reports/{report_id}/sources Sources: per-domain citation aggregation with owned / competitor / third-party classification.
GET /api/v2/attribution The attribution overlay: the metric trend across the brand's report versions plus the acted-on recommendation timeline.
GET /api/v2/vault/versions Version metadata for the key's brand, newest first.
GET /api/v2/vault/versions/{version} One version snapshot: its metadata plus the full section rows.

Conventions

Reports are read-only

Every route that returns report data is a GET. No route starts a run: measurement runs on schedules set in the application, so a report appears when the schedule produces it.

Writing is two verbs

PUT /api/v2/vault publishes a brand profile and PATCH /api/v2/recommendations/{rec_id} acts on a recommendation. Partial vault updates are allowed — sections you omit copy forward — and the write is recorded with its origin, so an API-authored change is distinguishable from one made in the application.

Rate limit

60 requests per minute per key. Every response carries X-RateLimit-* headers; a request over the limit answers 429.

Errors

Failures share one envelope with a machine-readable code, a human message, and any details the specific failure adds. The same envelope is what the MCP connector surfaces as a tool error, so an agent sees the same message a script would.

The previous version

Anything under /api/v1 answers 410 Gone. Use /api/v2.

Related

The MCP connector covers the same records for MCP clients, and is usually the shorter path for an agent.