The MCP tools and the REST API return the same data with the same identifiers. Use the MCP tools from an AI assistant, and the REST API from your own code, BI tools or data pipelines.
Overview
| MCP tool | REST endpoint | Returns |
|---|---|---|
list_tests | GET /v1/tests | Your organization’s tests and their availability |
read_results | GET /v1/tests/TEST_ID/results | The reviewed headline results for one test, for everyone in the test |
read_preview | GET /v1/tests/TEST_ID/preview | Up to 20 fixed, illustrative example entries |
Base URL: https://results.swayable.com (REST) and https://results.swayable.com/mcp (MCP).
Authentication: send Authorization: Bearer YOUR_API_KEY on every request.
Request rules (REST): use GET only, with no query parameters, no request body and no trailing slash. Responses are JSON and are not cached.
Request rules (MCP): list_tests takes no arguments. read_results and read_preview take exactly one argument, test_id.
list_tests
Lists the tests your organization can access. Takes no arguments.
Example response
{
"contract_version": 1,
"tests": [
{
"test_id": "test-0123456789abcdef01234567",
"title": "Spring Brand Campaign",
"availability": { "results": "available", "preview": "available" }
},
{
"test_id": "test-89abcdef0123456789abcdef",
"title": "Summer Video Test",
"availability": { "results": "draft", "preview": "unavailable" }
}
]
}
availability.results | Meaning |
|---|---|
available | Reviewed results exist and can be read |
draft | The test has no usable findings yet |
template | A test template with no usable findings |
withheld | The test is marked do-not-use |
no_comparison | The test has no eligible control comparison |
Only available tests return results. For the others, read_results returns an empty list, not an error. availability.preview is available or unavailable. Some tests may omit availability.
read_results
Returns the fixed, reviewed headline results for one test. Each result compares one creative with the control for one metric, across everyone in the test.
Input: test_id (string, required).
Example response
{
"contract_version": 1,
"test_id": "test-0123456789abcdef01234567",
"results": [
{
"result_id": "r-0001",
"label": "Brand Love lift: Creative A vs Control (overall)",
"value": 0.17,
"unit": "points on a 0-10 scale",
"ci95_lo": -0.07,
"ci95_hi": 0.41
}
]
}
| Field | Description |
|---|---|
result_id | Stable identifier for this result |
label | The metric, the creative compared with the control, and the population, in the form <metric> lift: <creative> vs <control> (overall) |
value | The lift: the creative’s average minus the control’s average |
unit | The unit of value: points on a 0-10 scale, or original metric units where a 0-10 scale can’t be confirmed. Always report values in this unit. |
ci95_lo, ci95_hi | The 95% confidence interval around value. When present, both bounds are present. |
See Reading your results for how to interpret these fields.
read_preview
Returns up to 20 fixed example entries that show the shape of the test’s data. Every call returns the same entries.
Input: test_id (string, required).
Example response
{
"contract_version": 1,
"test_id": "test-0123456789abcdef01234567",
"entries": [
{ "entry_id": "e-01", "values": { "company_size": "10-49 employees", "location_type": "Single location" } },
{ "entry_id": "e-02", "values": { "company_size": "1 (just myself)", "location_type": "Online only" } }
]
}
The preview is illustrative only. Don’t use it to estimate or recompute results; use read_results for that.
Errors
REST errors return JSON in the form {"error": {"code": "...", "message": "..."}}.
| Status | code | message |
|---|---|---|
| 400 | unsupported_parameters | Query parameters are not supported. |
| 400 | unsupported_body | Request bodies are not supported. |
| 401 | unauthorized | A valid API key is required. |
| 404 | not_found | Resource unavailable. Unknown paths, unknown test IDs and tests you can’t access all return this. |
| 405 | method_not_allowed | Use GET for this resource. |
| 503 | publication_unavailable | Test data is temporarily unavailable. |
MCP tool errors come back as a tool result with an error message:
Test unavailable.: the test doesn’t exist or isn’t available to you.Test data is temporarily unavailable.: retry later.Unsupported tool or arguments.: the call used an unknown tool or arguments other than those listed above.Invalid test identifier.:test_idwasn’t a string.
An MCP request without a valid key gets HTTP 401.
Limits
- Up to 500 results per test, and up to 20 preview entries per test.
- Test IDs have the form
test-followed by 24 hexadecimal characters.
Code examples
curl
Enter your key at a hidden prompt, then list your tests and read one test’s results. Replace YOUR_TEST_ID with a test_id from the list.
curl
printf 'API key: '; IFS= read -r -s SWAYABLE_API_KEY; printf '\n'
API_BASE=https://results.swayable.com
curl --fail-with-body --silent --show-error \
--header "Authorization: Bearer ${SWAYABLE_API_KEY}" \
"${API_BASE}/v1/tests"
TEST_ID=YOUR_TEST_ID
curl --fail-with-body --silent --show-error \
--header "Authorization: Bearer ${SWAYABLE_API_KEY}" \
"${API_BASE}/v1/tests/${TEST_ID}/results"
unset SWAYABLE_API_KEY
Python
Uses only Python 3’s standard library. Save it as read_results.py, run python3 read_results.py, and enter your key at the hidden prompt.
Python
import getpass
import json
from urllib.request import Request, urlopen
base_url = "https://results.swayable.com"
api_key = getpass.getpass("API key: ")
def get(path):
request = Request(base_url + path, headers={"Authorization": f"Bearer {api_key}"})
with urlopen(request, timeout=120) as response:
return json.load(response)
for test in get("/v1/tests")["tests"]:
print(test["title"], test.get("availability", {}))
if test.get("availability", {}).get("results") != "available":
continue
print(json.dumps(get(f'/v1/tests/{test["test_id"]}/results'), indent=2))
Postman
Select GET and enter a full URL such as https://results.swayable.com/v1/tests. Under Authorization → Bearer Token, enter your key. Leave the body empty.