API Reference

REST API Documentation

Full reference for the Otter A/B REST API. Manage projects, create experiments, inspect results, and automate your testing workflows.

Authentication

All API requests require a bearer token. Generate API keys from your dashboard under Settings → API & MCP.

Base URL

https://www.otterab.com/api/v1

Token Format

oab_live_<token_id>_<secret>

oab_live_ for production, oab_test_ for sandbox.

Example Request

curl https://www.otterab.com/api/v1/projects \
  -H "Authorization: Bearer oab_live_abc123_9f8e7d..." \
  -H "Accept: application/json"

Idempotency on Writes

Write endpoints support the optional Idempotency-Key header. Re-send the same method, path, and body with the same key to safely retry after a timeout or transport failure. Reusing a key for a different write request returns 409 Conflict.

Available Scopes

projects:read

List and view projects

projects:write

Create, update, delete projects

experiments:read

List and view experiments

experiments:write

Create, update, manage experiments

results:read

View experiment results

account:read

View account and usage info

api_keys:write

Manage API keys

Errors & Rate Limits

All errors follow a consistent envelope. Rate limits are enforced per account based on your plan.

Error Response

{
  "error": {
    "code": "validation_error",
    "message": "The request was invalid.",
    "details": [
      { "field": "name", "message": "can't be blank" }
    ],
    "request_id": "req_abc123"
  }
}

Error Codes

401
invalid_api_key

Missing or invalid bearer token

402
account_inactive

Subscription expired or inactive

403
forbidden

Missing required scope

404
not_found

Resource does not exist

409
idempotency_key_reused

Idempotency key was reused for a different write request

422
validation_error

Invalid request body

429
rate_limited

Too many requests

Rate Limits by Plan

PlanRequests / Minute
Starter100
Growth500
Scale2,000

Pagination

List endpoints accept page and per_page query parameters. Responses include a meta object with page, per_page, and total count.

Projects

Projects are containers for experiments. Each project maps to a website or app where the SDK snippet is installed.

# List all projects
curl https://www.otterab.com/api/v1/projects \
  -H "Authorization: Bearer oab_live_abc123_9f8e7d..."

# Create a project
curl -X POST https://www.otterab.com/api/v1/projects \
  -H "Authorization: Bearer oab_live_abc123_9f8e7d..." \
  -H "Content-Type: application/json" \
  -d '{"name": "Marketing Site", "url": "https://example.com", "platform": "custom_js"}'

Experiments

Experiments contain variants, goals, and targeting rules. Create and update the full experiment draft in a single request.

# List experiments for a project
curl https://www.otterab.com/api/v1/projects/42/experiments \
  -H "Authorization: Bearer oab_live_abc123_9f8e7d..."

# Create and immediately view an experiment draft
curl -X POST https://www.otterab.com/api/v1/projects/42/experiments \
  -H "Authorization: Bearer oab_live_abc123_9f8e7d..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Pricing Hero Test",
    "type": "visual",
    "url": "https://example.com/pricing",
    "url_match_type": "exact",
    "traffic_allocation": 100,
    "variants": [
      {"name": "Control", "is_control": true, "weight": 1, "changes": []},
      {"name": "New Headline", "is_control": false, "weight": 1, "changes": [
        {"selector": "h1", "action": "modify_text", "value": "Start winning."}
      ]}
    ],
    "goals": [
      {"name": "Signup", "goal_type": "pageview", "is_primary": true, "config": {"url": "https://example.com/success"}}
    ]
  }'

# Start an experiment
curl -X POST https://www.otterab.com/api/v1/projects/42/experiments/88/start \
  -H "Authorization: Bearer oab_live_abc123_9f8e7d..."

Results

Query experiment results with optional segment filters. The summary endpoint is ideal for dashboards and reporting bots.

# Get results summary for primary goal
curl https://www.otterab.com/api/v1/projects/42/experiments/88/results/summary \
  -H "Authorization: Bearer oab_live_abc123_9f8e7d..."

# Get results filtered by country
curl "https://www.otterab.com/api/v1/projects/42/experiments/88/results?country=US" \
  -H "Authorization: Bearer oab_live_abc123_9f8e7d..."

# Get time series for charting
curl https://www.otterab.com/api/v1/projects/42/experiments/88/results/timeseries \
  -H "Authorization: Bearer oab_live_abc123_9f8e7d..."

Account & Usage

View account details, team members, plan limits, and manage API keys programmatically.

Capabilities

Discovery endpoints for building valid requests. Useful for MCP clients and automation that need to construct targeting rules or experiments dynamically.

MCP Integration

Connect your AI assistant directly to Otter A/B using the Model Context Protocol. Use the same API key — all scopes and project restrictions apply.

Quick Start

# Claude Code (recommended)
claude mcp add --transport http otterab https://www.otterab.com/mcp/YOUR_API_KEY/v2/mcp

# Or run locally via npx
claude mcp add --transport stdio --env OTTERAB_API_KEY=oab_live_... otterab -- npx -y @otterab/mcp

Claude Code & Desktop

One-line setup via remote URL or local npx. Full tool support.

Cursor & VS Code

Add to your MCP config with npx. Works with Copilot agent mode.

Windsurf & Others

Standard MCP config. Any client supporting stdio or remote HTTP MCP servers.