# livevariant probes, 2026-09-18T12:15Z, from a cloud container (one IP), no credentials, no payment # Responses are cut at 6000 bytes (initialize), 20000 (tools/list), 2500 (protected resource), 9000 (authorization server), 4000 (REST). Nothing here was sent with a credential. ## 1. MCP initialize, POST https://livevariant.com/mcp $ curl -sS -i -m 25 -X POST https://livevariant.com/mcp -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' -d '' HTTP/1.1 200 Connection Established HTTP/2 200 date: Fri, 18 Sep 2026 12:15:13 GMT content-type: application/json content-length: 3969 access-control-allow-origin: * access-control-expose-headers: mcp-session-id report-to: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=l5KWKxtPDGy%2FVfOmxqVrbyxAoPCXmV3R16x75frNq%2BXS7W%2Bm9V%2B9%2BCi4u%2FgSRWWMsxPoX%2BKMV3GloubYP1C3JZBWwqEBQ07y4uH2OcO%2F5L7gTAYtB4qIR9%2FThBD5Mkl6pXs%3D"}]} nel: {"report_to":"cf-nel","success_fraction":0.0,"max_age":604800} server: cloudflare cf-ray: a3d0465adc5ae8a9-BOS alt-svc: h3=":443"; ma=86400 {"result":{"protocolVersion":"2025-06-18","capabilities":{"tools":{"listChanged":true},"resources":{"listChanged":true}},"serverInfo":{"name":"livevariant","version":"0.1.5","icons":[{"src":"https://livevariant.com/icon.svg","mimeType":"image/svg+xml","sizes":["any"]},{"src":"https://livevariant.com/icon-512.png","mimeType":"image/png","sizes":["512x512"],"theme":"light"},{"src":"https://livevariant.com/icon-512-dark.png","mimeType":"image/png","sizes":["512x512"],"theme":"dark"}]},"instructions":"LiveVariant runs A/B tests with multi-armed bandits, so traffic shifts toward the winner while the test runs instead of waiting for a frozen split to reach significance.\n\nCreating a test needs no account. A test IS its config, encoded into its own URLs, and its identity is a hash of that config, so editing a variant produces a different test with its own empty history. build_test returns a stats secret exactly once; without it a test's results can never be read by anyone.\n\nThree shapes, one model: email/image tests (image variants, serve URL in an ), page redirect tests (url variants, one link that 302s), and website tests (text/html variants served on-page via the tag or SDK with the ENCODED config). Multi-element tests use slots; one model optimizes the combination.\n\nTypical flow: variant_brief to learn the constraints, then PLAN with the human before building: propose which elements (slots) and variants to test, defaulting to assets they already have and offering to generate creative rather than silently doing so, and show the full proposed test for iteration. Only then build_test for the URLs (an edit after building is a NEW test with an empty history, so iterate on the plan). Optionally generate_priors to warm-start from what you expect, then get_stats to read results. Trust get_stats's win probabilities over comparing conversion rates by eye.\n\nMissing image variants are not a blocker: author HTML/SVG, render to fixed-size PNGs (browser screenshot or your image tool), and upload_image each; all variants of one element must share exact dimensions.\n\nTo save a test into a human's account, ask for the publishable key (pk_...) for an organization they administer and pass it to build_test (registers at creation), or hand them build_test's manage URL (one signed-in click); never collect credentials. When returning a newly built test, include the manage URL plus the ready-to-paste links for the channel (per-slot for multi-slot tests, merge tag in id=, auto=0 for email). When the human sends through an ESP or newsletter template, also hand over build_test's emailTemplate spelling unprompted: wired in once, every future campaign mints its own fresh test with no build step, and the shared kh reads them all. Be explicit that a two-slot template carries three links: one serve link per slot in its own (slot=hero, slot=cta), plus the click link that records the win and redirects.\n\nRelay destination warnings: an unverified redirect destination shows visitors a continue screen (get_test_status reports this; so does build_test). The fix is verifying the domain under Settings (DNS TXT, well-known file, or the tag with their publishable key live on the site); the tag also auto-tracks conversions from GA events and enables on-page tests, so suggest it when the user owns the site.\n\nThese instructions are the short version. Before building your first test, read the full skill: it has the recipes (email pitfalls, the plain-URL grammar, multi-slot tests, priors, generating image variants) that these tools assume you know. Read it via this server's `skill` resource (resources/read), or fetch https://livevariant.com/skills/livevariant/SKILL.md. Agents with a skills directory can install it permanently with `npx skills add livevariant/livevariant`. The whole service is open source (AGPL): to read the source, start with the README at https://github.com/livevariant/livevariant."},"jsonrpc":"2.0","id":1} ## 1b. MCP tools/list, POST https://livevariant.com/mcp (initialize answered 200; the session id from step 1 is sent back when the server issued one) $ curl -sS -i -m 25 -X POST https://livevariant.com/mcp -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' -H 'MCP-Protocol-Version: 2025-06-18' [-H 'Mcp-Session-Id: '] -d '' # tools counted over the whole response before the cut, by occurrences of "inputSchema": 9 (0 means no list came back) HTTP/1.1 200 Connection Established HTTP/2 200 date: Fri, 18 Sep 2026 12:15:13 GMT content-type: application/json content-length: 29284 access-control-allow-origin: * access-control-expose-headers: mcp-session-id report-to: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=UblRYcuPKIW0HChJSrho9rAuulJPg9WatTy9V6a0CKRXwDklcXGlODbvT2TinzrQVSinxlpEu7i52bGEm894nqmHXRlEeErBywGs4wU3k7Y7X5Gusqa4h1Gunrr%2FxNABPsg%3D"}]} nel: {"report_to":"cf-nel","success_fraction":0.0,"max_age":604800} server: cloudflare cf-ray: a3d0465edd1b8f7b-BOS alt-svc: h3=":443"; ma=86400 {"result":{"tools":[{"name":"build_test","title":"Build a test","description":"Creates a LiveVariant test and returns every URL needed to run it, plus a freshly generated stats secret.\n\nPass `variants` to test one element, or `slots` to test several at once (hero image AND call-to-action, say). With slots the test optimizes the COMBINATION: one model learns how the elements interact, which two separate tests structurally cannot see. There is no algorithm to pick either way; every test runs the same joint model, sized from its shape.\n\nBy default, nothing is registered anywhere: the config IS the test, encoded into the URLs, and the test's identity is a hash of it. Pass `publishableKey` on an account-enabled deployment to also register the new test to that key's organization, so it appears under My tests; the config and URLs are still the test, and registration failure is returned as a warning rather than failing the build. Editing a variant later produces a DIFFERENT test with its own empty history, which is usually what you want per campaign but is worth saying out loud to whoever you are building this for.\n\nThe stats secret is returned once and never again. Only its hash goes into the config, so nobody, including this service, can recover it. Give it to the person who will read the results.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"variants":{"description":"Single-element test: two or more variants. The first is the control.","minItems":2,"maxItems":64,"type":"array","items":{"type":"object","properties":{"name":{"description":"Shown in stats and in the utm stamp. Defaults to v1, v2, …","type":"string","minLength":1},"url":{"description":"Destination for redirect serving.","type":"string","format":"uri"},"image":{"description":"Image URL, for email variants.","type":"string","format":"uri"},"html":{"description":"Inline HTML, served by the SDK.","type":"string"},"markdown":{"description":"Inline markdown, served by the SDK.","type":"string"},"text":{"description":"Inline text, served by the SDK.","type":"string"},"redirectUrl":{"description":"Where a click on this variant lands, if it differs per variant.","type":"string","format":"uri"}}}},"slots":{"description":"Multi-element test: variants per element, keyed by a short name like \"hero\" or \"cta\". The test serves and learns combinations.","type":"object","propertyNames":{"type":"string","pattern":"^[a-z][a-z0-9_-]{0,31}$"},"additionalProperties":{"minItems":1,"maxItems":64,"type":"array","items":{"type":"object","properties":{"name":{"description":"Shown in stats and in the utm stamp. Defaults to v1, v2, …","type":"string","minLength":1},"url":{"description":"Destination for redirect serving.","type":"string","format":"uri"},"image":{"description":"Image URL, for email variants.","type":"string","format":"uri"},"html":{"description":"Inline HTML, served by the SDK.","type":"string"},"markdown":{"description":"Inline markdown, served by the SDK.","type":"string"},"text":{"description":"Inline text, served by the SDK.","type":"string"},"redirectUrl":{"description":"Where a click on this variant lands, if it differs per variant.","type":"string","format":"uri"}}}}},"slotRedirects":{"description":"Where clicks on ONE element land, when elements point at different pages (a hero leading to the campaign landing page, a CTA below it to pricing). Keyed like `slots`. Falls back to `redirectUrl`; a variant's own redirectUrl still wins over both. Setting any of these means every click link must name its slot, which slotLinks does for you.","type":"object","propertyNames":{"type":"string","pattern":"^[a-z][a-z0-9_-]{0,31}$"},"additionalProperties":{"type":"string","format":"uri"}},"name":{"description":"A label for your own reference, and the one field worth spending a merge tag on in a recurring ESP template: it is part of the test's identity, so n={{campaign_name}} mints a separate, separately readable test per campaign, and the name is what list_tests searches.","type":"string","minLength":1},"context":{"description":"Dimensions to learn a separate winner for.","maxItems":8,"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"description":"Dimension name, e.g. country. Becomes ?c_= on serve URLs."},"values":{"description":"Allowed values, when they are enumerable. Anything else is rejected at serving time, which is what stops a crafted URL inventing buckets. It also makes the results readable: bucket keys are one-way hashes, and a declared list is what lets stats recover \"country=nl\" from one. Worth passing even for a `from` dimension, and worth getting right the first time, since `ctx` is inside the test identity and adding values later starts a new test.","minItems":2,"type":"array","items":{"type":"string","minLength":1}},"from":{"description":"Fill this dimension from a signal the server derives, so the caller never sends it. Network signals (country, device, …) are guessed from the connection and are suppressed for proxied email fetches; utm_* are read off the link and survive a proxy intact, which makes them the reliable choice for email.","type":"string","enum":["country","continent","region","city","timezone","device","language","organization","utm_source","utm_medium","utm_campaign","utm_content","utm_term"]}},"required":["key"]}},"redirectUrl":{"description":"Where clicks land when a variant does not say.","type":"string","format":"uri"},"variantParam":{"description":"Stamp the served combination into this parameter on redirect, e.g. \"utm_content\", so the test shows up in the customer's own analytics.","type":"string","minLength":1,"maxLength":32},"publishableKey":{"description":"Registers the new test to the organization identified by a publishable key the user provides for an organization they administer. Result access stays tied to this test's stats secret. Only works on account-enabled deployments; elsewhere a warning says so and the test still works.","type":"string","pattern":"^pk_[a-z0-9]{24}$"},"region":{"description":"Where the test's state lives. A placement hint (wnam, enam, sam, weur, eeur, apac, oc, afr, me) or \"eu\" for the EU jurisdiction (state guaranteed created and kept inside the EU). Defaults to the creator's own region when the host can tell; without any, state is born wherever the FIRST request comes from, which in email is routinely a mail provider's US datacenter.","type":"string","enum":["wnam","enam","sam","weur","eeur","apac","oc","afr","me","eu"]}}},"annotations":{"title":"Build a test","readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"execution":{"taskSupport":"forbidden"},"outputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"testId":{"type":"string"},"config":{"type":"string","description":"The encoded config: this is the test."},"statsSecret":{"type":"string","description":"Shown once. Store it now."},"slots":{"type":"array","items":{"type":"object","properties":{"slot":{"type":"string"},"variants":{"type":"array","items":{"type":"string"}}},"required":["slot","variants"],"additionalProperties":false},"description":"Canonical slot order with variant names, as stats reports them."},"combinations":{"type":"number","description":"How many distinct combinations the test chooses between."},"region":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Where the test's state will live; null means first-request placement."},"urls":{"type":"object","properties":{"serve":{"type":"string"},"click":{"type":"string"},"pixel":{"type":"string"},"manage":{"type":"string","description":"Opening this URL shows live results, and signed-in users can click 'Add to my account' to claim the test into their dashboard. It contains the stats secret in its #fragment, so share it only with people authorized to see results."},"serveNoAutoContext":{"type":"string"},"clickNoAutoContext":{"type":"string"}},"required":["serve","click","pixel","manage","serveNoAutoContext","clickNoAutoContext"],"additionalProperties":false},"slotLinks":{"description":"Multi-slot tests only: the serve/click URL per element. The bare urls.serve returns 400 for these tests, because a serve must say which element it renders. The bare urls.click works when the destination is uniform (a config redirectUrl or ?to=); per-slot clicks matter as soon as an element carries its own destination, via slotRedirects or a variant redirectUrl.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","properties":{"serve":{"type":"string"},"click":{"type":"string"}},"required":["serve","click"],"additionalProperties":false}},"emailTemplate":{"description":"Query-parameter spelling per slot for an ESP template: wire it once, then campaign managers fill only the merge fields. All links share one identical config string (names, ctx dims, kh and the landing r=/sr= included, so serve and click stay ONE test); image links add &slot= per element. The click link needs no slot unless the test sets slotRedirects, in which case each element's click link carries its own. Absent when a variant has inline content or its own redirectUrl, which the parameter form cannot express.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","properties":{"imageSrc":{"type":"string"},"linkHref":{"type":"string"}},"required":["imageSrc","linkHref"],"additionalProperties":false}},"warnings":{"type":"array","items":{"type":"string"}},"registeredTo":{"description":"The organization the test was registered to, when a publishableKey was given and accepted.","type":"string"},"destinations":{"description":"Redirect destinations and whether each is a verified domain. Unverified means visitors see a 'Redirecting you to…' continue screen before landing; relay the verification warning to the user when present.","type":"array","items":{"type":"object","properties":{"host":{"type":"string"},"verified":{"type":"boolean"}},"required":["host","verified"],"additionalProperties":false}}},"required":["testId","config","statsSecret","slots","combinations","region","urls","warnings"],"additionalProperties":false}},{"name":"inspect_test","title":"Inspect a test","description":"Decodes a test and describes it: slots, variants, context, and whether it can be served by redirect. Also lints it for the mistakes that only show up once a campaign is out, such as an email test whose context comes from geo (which a mail proxy answers about itself).\n\nUse this before sending anything, and to answer 'what is this link?'.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"test":{"type":"string","minLength":1,"description":"The test: an encoded config, or any LiveVariant URL containing one (serve, click, pixel, manage), or a query-parameter serve URL. Paste whatever you have."},"config":{"type":"string","minLength":1,"description":"Alias for `test`: the same value under the name build_test returns it as (`config`). Pass one or the other."}},"oneOf":[{"required":["test"]},{"required":["config"]}]},"annotations":{"title":"Inspect a test","readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"},"outputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"testId":{"type":"string"},"name":{"type":"string"},"slots":{"type":"array","items":{"type":"object","properties":{"slot":{"type":"string"},"variants":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"formats":{"type":"array","items":{"type":"string"}},"servesByRedirect":{"type":"boolean"}},"required":["name","formats","servesByRedirect"],"additionalProperties":false}}},"required":["slot","variants"],"additionalProperties":false}},"combinations":{"type":"number"},"region":{"anyOf":[{"type":"string"},{"type":"null"}]},"context":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"from":{"type":"string"},"values":{"type":"array","items":{"type":"string"}}},"required":["key"],"additionalProperties":false}},"resultsReadable":{"type":"boolean","description":"False when the config has no stats key, which is permanent."},"findings":{"type":"array","items":{"type":"object","properties":{"level":{"type":"string","enum":["error","warning","note"]},"message":{"type":"string"}},"required":["level","message"],"additionalProperties":false}}},"required":["testId","slots","combinations","region","context","resultsReadable","findings"],"additionalProperties":false}},{"name":"generate_priors","title":"Add warm-start priors","description":"Takes YOUR estimate of how each variant will perform and converts it into the prior the model starts from, so a test does not spend its first visitors rediscovering what you already suspect.\n\nYou supply the guess; this does the arithmetic and the capping. That capping is the point: a prior is expressed as pseudo-observations, and it is deliberately held weak enough that real data overrides it quickly. The response says exactly how many real visitors per variant it takes to wash your guess out, so you can judge whether you have been too confident. Being wrong here costs a little early traffic, not the test.\n\nPriors are outside the identity hash, so the test keeps its id, its URLs and any history it already has.\n\nPass `when` to make the belief hold for ONE segment only (\"image B is the one for the blue segment\"). Without it the belief is about every visitor, which is a different and much stronger claim.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"test":{"type":"string","minLength":1,"description":"The test: an encoded config, or any LiveVariant URL containing one (serve, click, pixel, manage), or a query-parameter serve URL. Paste whatever you have."},"config":{"type":"string","minLength":1,"description":"Alias for `test`: the same value under the name build_test returns it as (`config`). Pass one or the other."},"when":{"description":"Context this belief is limited to, as dimension key to value (e.g. {\"color\": \"blauw\"}). The keys must be dimensions the test declares. Omit it for a belief about every visitor.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"beliefs":{"minItems":1,"type":"array","items":{"type":"object","properties":{"slot":{"description":"Which slot the variant belongs to. Optional for single-slot tests.","type":"string"},"variant":{"anyOf":[{"type":"string"},{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}],"description":"Variant name or index within its slot."},"rate":{"type":"number","minimum":0,"maximum":1,"description":"Your estimate of its conversion rate, e.g. 0.04 for 4%."}},"required":["variant","rate"]}},"confidence":{"default":"medium","description":"How much your guess is worth in observations. low=5, medium=15, high=30, or give a number directly. Higher means the test trusts you for longer before the data takes over.","anyOf":[{"type":"string","enum":["low","medium","high"]},{"type":"number","exclusiveMinimum":0}]}},"required":["beliefs"],"oneOf":[{"required":["test"]},{"required":["config"]}]},"annotations":{"title":"Add warm-start priors","readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"execution":{"taskSupport":"forbidden"},"outputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"testId":{"type":"string"},"config":{"type":"string"},"manageUrl":{"type":"string"},"priors":{"type":"array","items":{"type":"object","properties":{"slot":{"type":"string"},"variant":{"type":"string"},"mean":{"type":"number"},"strength":{"type":"number"}},"required":["slot","variant","mean","strength"],"additionalProperties":false}},"washesOutAfter":{"type":"number","description":"Roughly this many real visitors per variant and your guess stops mattering."},"notes":{"type":"array","items":{"type":"string"}}},"required":["testId","config","manageUrl","priors","washesOutAfter","notes"],"additionalProperties":false}},{"name":"get_stats","title":"Read a test's results","description":"Fetches a test's results and works out what they mean.\n\nAlongside the raw counts it returns the probability that each combination is genuinely best and the expected cost of stopping now and keeping the leader. Use those rather than comparing conversion rates by eye: a variant ahead 2/10 to 1/10 looks twice as good and is very close to a coin flip, and that mistake is the single most common way an A/B test gets called wrong.\n\nMulti-slot tests also report per-slot marginals: how each variant did across every combination it appeared in.\n\nNeeds the stats secret. If you have the manage URL, its #fragment IS the secret and it will be used automatically.","inputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"test":{"type":"string","minLength":1,"description":"The test: an encoded config, or any LiveVariant URL containing one (serve, click, pixel, manage), or a query-parameter serve URL. Paste whatever you have."},"config":{"type":"string","minLength":1,"description":"Alias for `test`: the same value under the name build_test returns it as (`config`). Pass one or the other."},"statsSecret":{"description":"Omit when passing a manage URL that carries it in the fragment.","type":"string"}},"oneOf":[{"required":["test"]},{"required":["config"]}]},"annotations":{"title":"Read a test's results","readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true},"execution":{"taskSupport":"forbidden"},"outputSchema":{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"testId":{"type":"string"},"totalAssignments":{"type":"number"},"combinations":{"type":"array","items":{"type":"object","properties":{"choice":{"type":"array","items":{"type":"string"}},"pulls":{"type":"number"},"conversions":{"type":"number"},"conversionRate":{"anyOf":[{"type":"number"},{"type":"null"}]},"probabilityBest":{"type":"number"}},"required":["choice","pulls","conversions","conversionRate","probabilityBest"],"additionalProperties":false}},"slots":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"pulls":{"type":"number"},"conversions":{"type":"number"},"conversionRate":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["name","pulls","conversions","conversionRate"],"additionalProperties":false}}},"decision":{"type":"object","properties":{"leader":{"type":"string"},"canStop":{"type":"boolean"},"expectedLossIfStoppingNow":{"type":"number"},"relativeLoss":{"type":"number"},"advice":{"type":"string"}},"required":["leader","canStop","expectedLossIfStoppingNow","relativeLoss","advice"],"additionalProperties":false},"contextBuckets":{"type":"number"},"bySignal":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","properties":{"pulls":{"type":"number"},"conversions":{"type":"number"}},"required":["pulls","conversions"],"add ## 2. Protected-resource metadata, GET https://livevariant.com/.well-known/oauth-protected-resource/mcp (not named in the challenge; the path-aware well-known URI, the first fallback the specification names) HTTP/1.1 200 Connection Established HTTP/2 404 date: Fri, 18 Sep 2026 12:15:14 GMT content-type: text/plain; charset=UTF-8 content-length: 9 report-to: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=egTnL4%2B2zPvJ1Ie62AkGjDxQc4CeKX7ndcxIpvHWoBKmk1tPgwt3bpJ5OLAaFuwunQH8WPusCixXQsNSUo2SghSId8hpPtpl9%2BdO7XmNh9HSwzC0QGze81ue1F%2BvBG%2FhUUw%3D"}]} nel: {"report_to":"cf-nel","success_fraction":0.0,"max_age":604800} server: cloudflare cf-ray: a3d04663ab248480-BOS alt-svc: h3=":443"; ma=86400 not found ## 2b. Protected-resource metadata, GET https://livevariant.com/.well-known/oauth-protected-resource (the root well-known URI, the second fallback; tried because step 2 answered 404, not 200) HTTP/1.1 200 Connection Established HTTP/2 404 date: Fri, 18 Sep 2026 12:15:15 GMT content-type: text/plain; charset=UTF-8 content-length: 9 report-to: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=eBCm1A3yyYcfO%2Fk2dUlJPL8kwE8QAhLsK22eR8xNw0voUg%2FpOha1lJ2VfpkKmwp1J8BZgaZuCPbQqvg78viEKqwbiR26ipI0ozYnxWMy5u6C1hDYOSOeYyvTKCRwRcXod0E%3D"}]} nel: {"report_to":"cf-nel","success_fraction":0.0,"max_age":604800} server: cloudflare cf-ray: a3d046676d6fa5bb-BOS alt-svc: h3=":443"; ma=86400 not found ## 3. Authorization-server metadata: no authorization_servers in step 2 ## 4. REST, GET https://livevariant.com/openapi.json, no Authorization header HTTP/1.1 200 Connection Established HTTP/2 200 date: Fri, 18 Sep 2026 12:15:15 GMT content-type: application/json content-length: 33582 report-to: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=2nM6F0%2BXdL62OXfHl%2BYtj0ABIxcW%2FCZQtgi%2B%2BWKE4BTrQyqt9AecX6LjH6Tegaiy0Kdu7d6Av8f2pHu%2BZySxKdpC9ld69iyMZSp%2Fm2%2Fx4YvR7tkPTYgez%2B1GfLsnoy%2BaLPk%3D"}]} nel: {"report_to":"cf-nel","success_fraction":0.0,"max_age":604800} server: cloudflare cf-ray: a3d0466b4f907d19-BOS alt-svc: h3=":443"; ma=86400 {"openapi":"3.1.0","info":{"title":"LiveVariant API","version":"1.0.0","description":"Build, inspect and read bandit-driven A/B tests.\n\nThere are no accounts and no API keys. A test is its config, encoded into its own URLs, and its identity is a hash of that config. Reading results needs the stats secret generated when the test was built, sent in the request body; the server checks it against the hash stored inside the config itself.\n\nThese endpoints mirror the MCP tools of the same names exactly. Use MCP if your client supports it; use this if it does not.","license":{"name":"AGPL-3.0","url":"https://www.gnu.org/licenses/agpl-3.0.html"}},"servers":[{"url":"https://livevariant.com"}],"tags":[{"name":"authoring","description":"Build and check tests. No network, no state."},{"name":"results","description":"Read a running test. Needs its stats secret."}],"paths":{"/api/v1/build-test":{"post":{"operationId":"build_test","summary":"Turn variants (one element or several) into a ready-to-use test with URLs","description":"Creates a LiveVariant test and returns every URL needed to run it, plus a freshly generated stats secret.\n\nPass `variants` to test one element, or `slots` to test several at once (hero image AND call-to-action, say). With slots the test optimizes the COMBINATION: one model learns how the elements interact, which two separate tests structurally cannot see. There is no algorithm to pick either way; every test runs the same joint model, sized from its shape.\n\nBy default, nothing is registered anywhere: the config IS the test, encoded into the URLs, and the test's identity is a hash of it. Pass `publishableKey` on an account-enabled deployment to also register the new test to that key's organization, so it appears under My tests; the config and URLs are still the test, and registration failure is returned as a warning rather than failing the build. Editing a variant later produces a DIFFERENT test with its own empty history, which is usually what you want per campaign but is worth saying out loud to whoever you are building this for.\n\nThe stats secret is returned once and never again. Only its hash goes into the config, so nobody, including this service, can recover it. Give it to the person who will read the results.","tags":["authoring"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"variants":{"description":"Single-element test: two or more variants. The first is the control.","minItems":2,"maxItems":64,"type":"array","items":{"type":"object","properties":{"name":{"description":"Shown in stats and in the utm stamp. Defaults to v1, v2, …","type":"string","minLength":1},"url":{"description":"Destination for redirect serving.","type":"string","format":"uri"},"image":{"description":"Image URL, for email variants.","type":"string","format":"uri"},"html":{"description":"Inline HTML, served by the SDK.","type":"string"},"markdown":{"description":"Inline markdown, served by the SDK.","type":"string"},"text":{"description":"Inline text, served by the SDK.","type":"string"},"redirectUrl":{"description":"Where a click on this variant lands, if it differs per variant.","type":"string","format":"uri"}}}},"slots":{"description":"Multi-element test: variants per element, keyed by a short name like \"hero\" or \"cta\". The test serves and learns combinations