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/v1Token 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:readList and view projects
projects:writeCreate, update, delete projects
experiments:readList and view experiments
experiments:writeCreate, update, manage experiments
results:readView experiment results
account:readView account and usage info
api_keys:writeManage 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
invalid_api_keyMissing or invalid bearer token
account_inactiveSubscription expired or inactive
forbiddenMissing required scope
not_foundResource does not exist
idempotency_key_reusedIdempotency key was reused for a different write request
validation_errorInvalid request body
rate_limitedToo many requests
Rate Limits by Plan
| Plan | Requests / Minute |
|---|---|
| Starter | 100 |
| Growth | 500 |
| Scale | 2,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/mcpClaude 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.