REST API 12 min read

Get your API key

Generate a sk_live_ key from Settings → API (Enterprise plan).

Go to Settings →

Endpoint Reference

Base URL: https://api.abtestbot.com Auth: Authorization: Bearer sk_live_...

All endpoints return the standard {data, meta} wrapper on success and {error: {code, message}} on failure. workspace_id is derived from the API key — you never pass it explicitly.


Sites

`GET /v1/sites`

List all sites registered in your workspace, ordered most-recent first.

Response:

{
  "data": [
    {
      "id": "uuid",
      "name": "mystore",
      "url": "https://mystore.com",
      "platform": "shopify",
      "crawl_status": "ok",
      "created_at": "2026-04-15T11:40:06.712852+00:00",
      "updated_at": "2026-04-15T11:40:06.712852+00:00"
    }
  ],
  "meta": { "workspace_id": "uuid" }
}

`POST /v1/sites`

Register a new site. Subject to your plan's site limit (Starter: 1, Pro: 10, Enterprise: 25).

Body:

Field Type Required Notes
name string yes Display name
url string yes Fully-qualified URL with scheme

Response: 201 Created with the full site object (same shape as GET, plus public_key used by the SplitKit tracking snippet).

`GET /v1/sites/:id`

Get one site by ID. Returns 404 not_found if it doesn't exist or belongs to another workspace.


Ideas

`GET /v1/ideas`

List A/B test ideas. Ordered by creation date (newest first).

Query parameters:

Param Type Notes
site_id uuid Filter to one site
status string new | approved | implemented | rejected | archived
category string e.g. cta, headline, layout
limit integer Default 20, max 100
offset integer Default 0

Response:

{
  "data": [
    {
      "id": "uuid",
      "title": "Test CTA button color",
      "hypothesis": "Changing from grey to green will increase CTR",
      "category": "cta",
      "priority": "high",
      "status": "new",
      "output_type": "html",
      "estimated_impact": "high",
      "mockup_data": { ... },
      "site_id": "uuid",
      "sites": { "name": "mystore", "url": "..." },
      "created_at": "...",
      "updated_at": "..."
    }
  ],
  "meta": { "workspace_id": "uuid" }
}

`POST /v1/ideas/generate`

Kick off AI-powered idea generation for a site. Returns 202 Accepted — the work runs asynchronously and emits the ideas.generated webhook when complete (15–30s typical).

Body:

Field Type Required Notes
site_id uuid yes
num_ideas integer no Default 5, max 10
output_type string no html (default) or screenshot

Response:

{
  "data": {
    "success": true,
    "ideas": [ { "id": "uuid", "title": "...", "hypothesis": "...", ... } ]
  },
  "meta": { "workspace_id": "uuid" }
}

`GET /v1/ideas/:id`

Get one idea in full, including the parent site summary and mockup data.

`PATCH /v1/ideas/:id`

Update an idea's status — typically after reviewing or implementing it.

Body:

{ "status": "approved" }

Valid status values: new, approved, implemented, rejected, archived.


Experiments

`GET /v1/experiments`

List experiments. Shares the standard pagination contract.

Query parameters:

Param Type Notes
site_id uuid Filter to one site
status string draft | active | paused | completed | archived
limit integer Default 20, max 100

Response: list of experiments with id, name, status, traffic_split, started_at, ended_at, site_id, plus a nested sites summary.

`POST /v1/experiments`

Create an experiment, optionally from an existing idea.

Body:

Field Type Required Notes
site_id uuid yes
name string yes
idea_id uuid no Link the experiment to an existing idea
variants array no [{ name: string, traffic_split?: number }] — defaults to 50/50 control + variant
goals array no Conversion goals to track

Response: 201 Created with the full experiment object including generated variants and goals.

`GET /v1/experiments/:id`

Get one experiment with all nested variants, goals, and parent site summary.

`PATCH /v1/experiments/:id`

Transition an experiment's lifecycle.

Body:

{ "action": "pause" }

Valid action values: pause, resume, complete, archive.

Response: { "data": { "id": "...", "status": "paused" } }


Schedules

Recurring idea-generation runs.

`GET /v1/schedules`

List all schedules in your workspace.

`POST /v1/schedules`

Create a schedule.

Body:

Field Type Required Default
site_id uuid yes
enabled boolean no false
frequency string no weekly (also daily, monthly)
day_of_week integer no 1 (Monday = 1, Sunday = 7)
ideas_per_run integer no 2
output_type string no html
target_pages array no [] — specific URLs to target

`PATCH /v1/schedules/:id`

Update a schedule. Any of the fields above can be partially updated.


Webhooks

Subscribe to events to react to API-driven or UI-driven changes in real time.

`GET /v1/webhooks`

List active webhook endpoints.

Response:

{
  "data": [
    {
      "id": "uuid",
      "url": "https://your-app.com/webhooks/abtestbot",
      "events": ["ideas.generated", "experiment.launched"],
      "is_active": true,
      "created_at": "..."
    }
  ]
}

`POST /v1/webhooks`

Register a new webhook endpoint. The 201 response includes a one-time signing secret — store it. Use it to verify incoming webhooks via the X-abTestBot-Signature header (HMAC-SHA256).

Body:

Field Type Required Notes
url string yes HTTPS endpoint
events array yes One or more event types from the list below

Supported event types:

  • ideas.generated — a scheduled or manual generate run completed
  • idea.status_changed — an idea moved to approved/implemented/etc.
  • experiment.launched — an experiment transitioned to active
  • experiment.completed — an experiment concluded (manually or auto)

`DELETE /v1/webhooks/:id`

Deactivate a webhook (soft-delete — flips is_active to false). Returns { "data": { "deleted": true } }.


Versioning

All endpoints live under /v1/. Breaking changes will ship as /v2/ — we don't modify /v1/ contracts once published.