Read the complete experiment results
const url = 'https://api.octaneai.com/v1/experiments/example/results';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://api.octaneai.com/v1/experiments/example/results \ --header 'Authorization: Bearer <token>'Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Responses
Section titled “Responses”The complete results, including decision evidence, gates, periods and attention context.
object
object
The error rate the range allows, 0.05
The decision metric per version, live version first: label, n, events, rate, se, raw_money, capped_money, design_effect
object
When the decision was made, UTC ISO 8601
The store’s order-matching window in days: how long after a visit an order still counts
What the range had to clear: k, alpha_used, se, n and needed_lo (the lead that excludes zero)
object
Notes recorded with the decision; currently always empty
The live version and the variant, in that order
Completion_rate | email_opt_in | order_conversion | rpv | aov | phone_opt_in | reached_page | product_page_clicked | custom_url_clicked | button_clicked | chose_answer
object
What the minimum counts: starts | visits | orders | events
The minimum a version needs before its number is read
object
Formula_cs | formula_k | formula_se | formula_srm | formula_floor | formula_guardrail | formula_rpv_cap
The formula as written, in LaTeX
The formula with this test’s numbers, in LaTeX
Each symbol with its meaning in words
object
True for our AI’s decision, its own judgement rather than the automatic rule’s
The visits expected by the decision date, where the range is tuned to be narrowest
Each protected metric when decided: kind, label, lo, hi, assessed, harmed
object
Under_minimum_hours | split_unhealthy | collecting | leaning | clear_for_control | clear | protected_harmed:
The kinds of revenue counted: added_from_quiz | shown_bought_later | bought_not_shown
The test’s revision when decided
object
The share of shoppers each version should get, 0 to 1, live version first
The variant’s share of shoppers the split was set to, 0 to 1
Whether the check has fired; once fired it stays on for the rest of the test
The evidence that shoppers are not landing as the split was set; the check fires above 6.91
The shoppers counted on both versions
Whether the 200 shoppers the check needs have been counted
Shoppers counted per version, live version first
Each version’s numbers in the current counting period, live version first
object
Distinct shoppers assigned to this version; a shopper without cookies counts once per visit
Visits that finished the quiz: reached its last page and answered whatever that page requires
Visits where the shopper submitted an email address
Orders linked to these visits with a line in a revenue kind the test counts
Visits where the shopper submitted a phone number
That revenue split by how each item reached the cart
object
Visits where the shopper answered or stepped forward at least once
Visits that opened the quiz on the store, whether or not the shopper answered anything; previews are not counted
Visits followed by at least one such order
The arm’s share of the split, a whole number weighed against the other arm’s
When these numbers were read, UTC ISO 8601; a read is served again for up to two hours
The store’s order-matching window in days: how long after a visit an order still counts
Whether revenue arriving since the decision moved the lead past half the recorded range
object
The error rate the range allows, 0.05
The decision metric per version, live version first: label, n, events, rate, se, raw_money, capped_money, design_effect
object
When the decision was made, UTC ISO 8601
The store’s order-matching window in days: how long after a visit an order still counts
What the range had to clear: k, alpha_used, se, n and needed_lo (the lead that excludes zero)
object
Notes recorded with the decision; currently always empty
The live version and the variant, in that order
Completion_rate | email_opt_in | order_conversion | rpv | aov | phone_opt_in | reached_page | product_page_clicked | custom_url_clicked | button_clicked | chose_answer
object
What the minimum counts: starts | visits | orders | events
The minimum a version needs before its number is read
object
Formula_cs | formula_k | formula_se | formula_srm | formula_floor | formula_guardrail | formula_rpv_cap
The formula as written, in LaTeX
The formula with this test’s numbers, in LaTeX
Each symbol with its meaning in words
object
True for our AI’s decision, its own judgement rather than the automatic rule’s
The visits expected by the decision date, where the range is tuned to be narrowest
Each protected metric when decided: kind, label, lo, hi, assessed, harmed
object
Under_minimum_hours | split_unhealthy | collecting | leaning | clear_for_control | clear | protected_harmed:
The kinds of revenue counted: added_from_quiz | shown_bought_later | bought_not_shown
The test’s revision when decided
object
The share of shoppers each version should get, 0 to 1, live version first
The variant’s share of shoppers the split was set to, 0 to 1
Whether the check has fired; once fired it stays on for the rest of the test
The evidence that shoppers are not landing as the split was set; the check fires above 6.91
The shoppers counted on both versions
Whether the 200 shoppers the check needs have been counted
Shoppers counted per version, live version first
object
What the event recorded, by kind; version ids in it are public ids, null once that version is deleted
object
Created | started | period_opened | weights_changed | control_published | arm_republished | decision_metric_changed | decision_option_changed | protect_changed | revenue_tiers_changed | settings_changed | evaluation_delayed | decision_traced | ai_decided | srm_flagged | clear | nudged | digest_sent | warning_sent | result_sent | ended | target_missing; a new kind may be added
object
After that many runs: decide at the first clear result without the AI, or wait for you
object
0 for the live version, 1 for the variant
The arm’s share of the split, a whole number weighed against the other arm’s
Completion_rate | email_opt_in | order_conversion | rpv | aov | phone_opt_in | reached_page | product_page_clicked | custom_url_clicked | button_clicked | chose_answer
Manual: the merchant decides. when_clear: publish at the first clear result. on_date: decide on a date. ai: the AI decides.
What happens on the date without a clear result: keep running, put the live version back, or tell the merchant and wait.
Whether reminder emails go out six weeks after the start and every two weeks after until it ends
The current counting period: 0 on a draft, 1 once started, one higher each time a new one opens
Why a counting period began.
The metrics the test watches for harm: completion_rate | email_opt_in | order_conversion | rpv | aov | phone_opt_in | reached_page | product_page_clicked | custom_url_clicked | button_clicked | chose_answer
The kinds of revenue counted: added_from_quiz | shown_bought_later | bought_not_shown
A number that goes up with every change to the test
Draft: set up, not started. running: shoppers are being split. waiting: still splitting, automatic decisions paused. ended: no longer assigning.
IANA name of the timezone decision_date is read in
Whether a weekly email reports where the test stands
The camelCase names of the help topics that explain the numbers in this response
True once the test has ended: the visits counted stop at its end while their orders keep arriving
object
What the decision metric reads now, in one sentence
What happens next, per how the test decides
What is tested: each version with its number and share of shoppers
object
The error rate the range allows, 0.05
object
Counted revenue with unusually large visits counted at the cap, in the store’s currency; 0 for a rate
How much returning shoppers widened the range; 1 means repeats made no difference
How many of those did what the metric counts; for the money metrics, the distinct counted orders
object
What the minimum counts: starts | visits | orders | events
The minimum a version needs before its number is read
The metric on this version: a rate from 0 to 1, or revenue per visit or per order in the store’s currency
The visits the metric is read on: starts for completion and opt-in rates, visits for the rest
Counted revenue before the cap on unusually large visits, in the store’s currency; 0 for a rate
The standard error of mean, with each returning shopper’s visits grouped
The larger of the two versions’ design effects
Completion_rate | email_opt_in | order_conversion | rpv | aov | phone_opt_in | reached_page | product_page_clicked | custom_url_clicked | button_clicked | chose_answer
Whether the line reads the two versions as level so far
The gap between the versions in one sentence, relative to the live version
The visits expected by the decision date, where the range is tuned to be narrowest
What the metric counts over: starts | visits | orders
Decider: the decision metric | exploratory: reported beside it, never decides
Collecting: not enough data | leaning: one version ahead, range still includes zero | clear: range excludes zero
The unit of delta and its range: percentage points, sent as a fraction (0.05 is five points) | currency per order | currency per visit
object
Counted revenue with unusually large visits counted at the cap, in the store’s currency; 0 for a rate
How much returning shoppers widened the range; 1 means repeats made no difference
How many of those did what the metric counts; for the money metrics, the distinct counted orders
object
What the minimum counts: starts | visits | orders | events
The minimum a version needs before its number is read
The metric on this version: a rate from 0 to 1, or revenue per visit or per order in the store’s currency
The visits the metric is read on: starts for completion and opt-in rates, visits for the rest
Counted revenue before the cap on unusually large visits, in the store’s currency; 0 for a rate
The standard error of mean, with each returning shopper’s visits grouped
object
Why the period began: started | split_changed | control_published | variant_republished | metric_changed | revenue_tiers_changed
object
The day of the current counting period, 1 on the day it began
What the progress says; empty when the period has no planned sample or the decision metric is clear
What each version has so far toward its quota, keyed control and variant
object
Min_days: inside the minimum days | estimating: no pace yet | reached: enough shoppers and clear | reached_unclear: enough shoppers, not clear | on_track | slow
object
Whether the metric has enough data to be checked
Whether even the best case for the variant is worse than the live version
The protected metric: completion_rate | email_opt_in | order_conversion | rpv | aov | phone_opt_in | reached_page | product_page_clicked | custom_url_clicked | button_clicked | chose_answer
Not checked yet: too little data | no harm | worse: blocks an automatic publish
object
The share of shoppers each version should get, 0 to 1, live version first
The variant’s share of shoppers the split was set to, 0 to 1
Whether the check has fired; once fired it stays on for the rest of the test
The evidence that shoppers are not landing as the split was set; the check fires above 6.91
The shoppers counted on both versions
Whether the 200 shoppers the check needs have been counted
Shoppers counted per version, live version first
Example
{ "arms": [], "as_of": "2026-09-16T12:00:00Z", "attribution_line": "Orders can arrive up to 7 days after a visit, so the newest visits look poorer on both versions for now.", "attribution_window_days": 7, "changed_since": false, "changes": [], "events": [], "experiment": { "ai_fallback": "when_clear", "app_id": "quiz_7c9e6679742540de944be07fc1f90ae7", "arms": [ { "id": "arm_00000000000000000000000000000001", "is_control": true, "label": "Live version", "position": 0, "version_id": "ver_00000000000000000000000000000001", "version_number": 1, "weight": 1 }, { "id": "arm_00000000000000000000000000000002", "is_control": false, "label": "Variant B", "position": 1, "version_id": "ver_00000000000000000000000000000002", "version_number": 2, "weight": 1 } ], "created_at": "2026-09-16T12:00:00Z", "decision_metric": "completion_rate", "decision_option": "when_clear", "fallback": "notify", "id": "expt_7c9e6679742540de944be07fc1f90ae7", "long_run_reminders": true, "name": "Skip the email page", "period": 0, "period_reason": "started", "protect_metrics": [], "revenue_tiers": [ "added_from_quiz", "shown_bought_later", "bought_not_shown" ], "revision": 0, "status": "draft", "timezone": "UTC", "updated_at": "2026-09-16T12:00:00Z", "weekly_digest": true }, "explainer_keys": [ "views", "starts", "completions", "completionRate", "experimentLift", "experimentInterval" ], "frozen": false, "gates": [ { "detail": "Completion rate is measured on both versions.", "key": "decision_metric", "label": "Decision metric", "met": true }, { "detail": "168 hours to go.", "key": "min_days", "label": "7-day minimum", "met": false }, { "detail": "No completions on either version yet.", "key": "enough_data", "label": "Enough data", "met": false }, { "detail": "Not enough shoppers to check yet.", "key": "split_health", "label": "Split healthy", "met": true }, { "detail": "No protected metric stands in the way.", "key": "protected", "label": "Protected metrics", "met": true } ], "header": { "current_read": "No completions on either version yet.", "day_line": "Day 1", "next": "Publishes the winner at the first clear result, once the test starts.", "testing": "Live version (v1) 50% vs Variant B (v2) 50%" }, "metrics": [], "periods": [], "progress": { "day": 1, "line": "", "observed": { "control": 0, "variant": 0 }, "tier": "min_days" }, "protection": [], "split": { "expected": [ 0.5, 0.5 ], "expected_share": 0.5, "latched": false, "log_odds": 0, "n": 0, "surfaced": false, "units_per_arm": [ 0, 0 ] }}The key is missing, malformed, revoked or expired.
The body of every non-2xx response.
object
What went wrong, for people
object
The input that failed, as a dotted path (body.label, query.from)
Why it failed
The same value as the Request-Id header; quote it to support
The HTTP status of the response
The machine-readable error code; the Errors guide lists every one
A stable URI naming the error, on this API’s public host
Example
{ "detail": "The API key is missing, malformed, revoked or expired", "request_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "status": 401, "title": "invalid_api_key", "type": "https://api.octaneai.com/errors/invalid_api_key"}Headers
Section titled “Headers”Example
BearerThe store’s plan has no API access, or the key lacks the scope.
The body of every non-2xx response.
object
What went wrong, for people
object
The input that failed, as a dotted path (body.label, query.from)
Why it failed
The same value as the Request-Id header; quote it to support
The HTTP status of the response
The machine-readable error code; the Errors guide lists every one
A stable URI naming the error, on this API’s public host
Examples
{ "detail": "The API key does not carry the scope this route needs", "request_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "required": [ "experiments:read" ], "status": 403, "title": "insufficient_scope", "type": "https://api.octaneai.com/errors/insufficient_scope"}{ "detail": "The merchant API is available on the Plus and Enterprise plans", "request_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "status": 403, "title": "plan_required", "type": "https://api.octaneai.com/errors/plan_required"}Not found
The body of every non-2xx response.
object
What went wrong, for people
object
The input that failed, as a dotted path (body.label, query.from)
Why it failed
The same value as the Request-Id header; quote it to support
The HTTP status of the response
The machine-readable error code; the Errors guide lists every one
A stable URI naming the error, on this API’s public host
Example
{ "detail": "Not found", "request_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "status": 404, "title": "not_found", "type": "https://api.octaneai.com/errors/not_found"}A request parameter is invalid.
The body of every non-2xx response.
object
What went wrong, for people
object
The input that failed, as a dotted path (body.label, query.from)
Why it failed
The same value as the Request-Id header; quote it to support
The HTTP status of the response
The machine-readable error code; the Errors guide lists every one
A stable URI naming the error, on this API’s public host
Example
{ "detail": "A request parameter is invalid.", "request_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "status": 422, "title": "validation_error", "type": "https://api.octaneai.com/errors/validation_error"}The key’s or the store’s bucket is full; Retry-After says when to try again.
The body of every non-2xx response.
object
What went wrong, for people
object
The input that failed, as a dotted path (body.label, query.from)
Why it failed
The same value as the Request-Id header; quote it to support
The HTTP status of the response
The machine-readable error code; the Errors guide lists every one
A stable URI naming the error, on this API’s public host
Example
{ "detail": "Too many requests", "request_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "retry_after": 1, "status": 429, "title": "rate_limited", "type": "https://api.octaneai.com/errors/rate_limited"}Request limits cannot be checked right now; retry shortly.
The body of every non-2xx response.
object
What went wrong, for people
object
The input that failed, as a dotted path (body.label, query.from)
Why it failed
The same value as the Request-Id header; quote it to support
The HTTP status of the response
The machine-readable error code; the Errors guide lists every one
A stable URI naming the error, on this API’s public host
Example
{ "detail": "Request limits cannot be checked right now; retry shortly", "request_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "status": 503, "title": "limiter_unavailable", "type": "https://api.octaneai.com/errors/limiter_unavailable"}The request timed out.
The body of every non-2xx response.
object
What went wrong, for people
object
The input that failed, as a dotted path (body.label, query.from)
Why it failed
The same value as the Request-Id header; quote it to support
The HTTP status of the response
The machine-readable error code; the Errors guide lists every one
A stable URI naming the error, on this API’s public host
Example
{ "detail": "The request timed out.", "request_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "status": 504, "title": "timeout", "type": "https://api.octaneai.com/errors/timeout"}