docs menu

API Reference

Most people work with ImproveFast through their agent using the improve-fast skill — see Quick start. This page documents the plain REST API at https://improve.fast underneath it, for teams building their own integration with curl or any HTTP client.

POST /api/experiments

Creates a new experiment with the specified variants. Experiments expire 7 days after creation.

Request Body

  • variants (array of strings, required): List of variant identifiers to test. Minimum 2 variants required. Must be unique (case-sensitive).

curl

bash
curl -X POST https://improve.fast/api/experiments \
  -H "Content-Type: application/json" \
  -d '{"variants": ["A", "B", "C"]}'

Response

json
{
  "experimentId": "550e8400-e29b-41d4-a716-446655440000",
  "variants": ["A", "B", "C"],
  "createdAt": "2026-07-17T18:00:00.000Z",
  "expiresAt": "2026-07-24T18:00:00.000Z"
}

Save this experimentId — you'll need it for all subsequent operations. Treat it like a secret, since it's the only credential for the experiment.

GET /api/experiments/:id

Returns the current status of the experiment: how far along it is, whether it's found a clear winner yet, and the winner's stats once it has.

curl

bash
$ curl https://improve.fast/api/experiments/550e8400-e29b-41d4-a716-446655440000

Response (in progress)

json
{
  "experimentId": "550e8400-e29b-41d4-a716-446655440000",
  "totalEvaluations": 12,
  "progress": 0.06,
  "estimatedRemainingEvaluations": 138,
  "converged": false,
  "variants": [
    { "name": "A", "evaluations": 4, "meanScore": 0.61, "posteriorMean": 0.60, "posteriorStdDev": 0.19 },
    { "name": "B", "evaluations": 5, "meanScore": 0.72, "posteriorMean": 0.70, "posteriorStdDev": 0.17 },
    { "name": "C", "evaluations": 3, "meanScore": 0.58, "posteriorMean": 0.58, "posteriorStdDev": 0.22 }
  ],
  "winner": null
}

Response (converged)

json
{
  "experimentId": "550e8400-e29b-41d4-a716-446655440000",
  "totalEvaluations": 58,
  "progress": 0.16,
  "estimatedRemainingEvaluations": 0,
  "converged": true,
  "variants": [
    { "name": "A", "evaluations": 18, "meanScore": 0.653, "posteriorMean": 0.655, "posteriorStdDev": 0.045 },
    { "name": "B", "evaluations": 22, "meanScore": 0.847, "posteriorMean": 0.848, "posteriorStdDev": 0.038 },
    { "name": "C", "evaluations": 18, "meanScore": 0.712, "posteriorMean": 0.713, "posteriorStdDev": 0.041 }
  ],
  "winner": {
    "variantName": "B",
    "evaluations": 22,
    "meanScore": 0.847,
    "stdDev": 0.038,
    "confidenceInterval": [0.771, 0.923]
  }
}

progress just tracks how close the smallest variant is to a 50-evaluation safety limit — it isn't a confidence score. A winner is usually declared well before progress reaches 1.0, as soon as the leading variant has enough evaluations (15 or more), a steady average, and a clear lead over the runner-up. winner is null until then, then becomes an object with the winning variant's stats.

POST /api/experiments/:id/select

Returns the next variant to try. ImproveFast picks it using a technique called Thompson Sampling (a kind of multi-armed bandit algorithm) that leans toward whichever variant is doing best so far, while still trying the others often enough to stay fair. Picks aren't fixed — repeated calls with identical state can return different variants by design.

curl

bash
$ curl -X POST https://improve.fast/api/experiments/550e8400-e29b-41d4-a716-446655440000/select

Response

json
{
  "variant": "B"
}

POST /api/experiments/:id/record

Records the score for one try of a variant. ImproveFast updates its internal stats and checks whether there's a clear winner yet.

Request Body

  • variant (string, required): The variant identifier being evaluated. Must match one from the experiment's variants.
  • score (number, required): Normalized outcome score between 0.0 and 1.0 (inclusive). Higher is better. Values outside this range are rejected.

curl

bash
curl -X POST https://improve.fast/api/experiments/550e8400-e29b-41d4-a716-446655440000/record \
  -H "Content-Type: application/json" \
  -d '{"variant": "B", "score": 0.9}'

Response (no winner yet)

json
{
  "experimentId": "550e8400-e29b-41d4-a716-446655440000",
  "variant": "B",
  "score": 0.9,
  "totalEvaluations": 13,
  "progress": 0.06,
  "estimatedRemainingEvaluations": 137,
  "winner": null
}

Response (winner declared)

json
{
  "experimentId": "550e8400-e29b-41d4-a716-446655440000",
  "variant": "B",
  "score": 0.9,
  "totalEvaluations": 58,
  "progress": 0.16,
  "estimatedRemainingEvaluations": 0,
  "winner": {
    "variantName": "B",
    "evaluations": 22,
    "meanScore": 0.847,
    "stdDev": 0.038,
    "confidenceInterval": [0.771, 0.923]
  }
}

The winner field is null until ImproveFast is confident about a winner, then becomes an object with the winning variant's stats — it's not just the variant name.

Error Handling

All endpoints return errors as JSON with a machine-readable code:

json
{
  "error": {
    "code": "VARIANT_NOT_FOUND",
    "message": "Variant B not found in experiment 550e8400-e29b-41d4-a716-446655440000"
  }
}

Error Codes

  • VALIDATION_ERROR (400) - Request body is malformed, e.g. fewer than 2 variants or a score outside [0, 1]
  • DUPLICATE_VARIANTS (400) - Variant names in POST /api/experiments must be unique (case-sensitive)
  • ALREADY_INITIALIZED (400) - An experiment already exists for the given experimentId
  • VARIANT_NOT_FOUND (400) - Variant name doesn't match any from the experiment's original variants
  • EXPERIMENT_NOT_FOUND (404) - The experimentId is unknown or the experiment has expired (7-day TTL)
  • NOT_FOUND (404) - The route doesn't exist
  • METHOD_NOT_ALLOWED (405) - Wrong HTTP method for the endpoint