A/B Tests
Add A/B Test Variant
Add a variant to a draft campaign or sequence A/B test
POST
/
api
/
v1
/
ab-tests
/
{abTestId}
/
variants
Add A/B Test Variant
curl --request POST \
--url https://api.sequenzy.com/api/v1/ab-tests/{abTestId}/variants \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"subject": "<string>",
"previewText": "<string>",
"blocks": [
{}
],
"confirmLiveChange": true
}
'import requests
url = "https://api.sequenzy.com/api/v1/ab-tests/{abTestId}/variants"
payload = {
"subject": "<string>",
"previewText": "<string>",
"blocks": [{}],
"confirmLiveChange": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
subject: '<string>',
previewText: '<string>',
blocks: [{}],
confirmLiveChange: true
})
};
fetch('https://api.sequenzy.com/api/v1/ab-tests/{abTestId}/variants', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sequenzy.com/api/v1/ab-tests/{abTestId}/variants",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'subject' => '<string>',
'previewText' => '<string>',
'blocks' => [
[
]
],
'confirmLiveChange' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sequenzy.com/api/v1/ab-tests/{abTestId}/variants"
payload := strings.NewReader("{\n \"subject\": \"<string>\",\n \"previewText\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"confirmLiveChange\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sequenzy.com/api/v1/ab-tests/{abTestId}/variants")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"subject\": \"<string>\",\n \"previewText\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"confirmLiveChange\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sequenzy.com/api/v1/ab-tests/{abTestId}/variants")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"subject\": \"<string>\",\n \"previewText\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"confirmLiveChange\": true\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"abTest": {
"id": "ab_abc123",
"campaignId": "camp_abc123",
"status": "draft",
"variants": [
{ "id": "var_a", "label": "A", "subject": "A quick update" },
{ "id": "var_b", "label": "B", "subject": "Alternative subject line" },
{ "id": "var_c", "label": "C", "subject": "Third subject idea" }
]
}
}
{
"success": false,
"error": "Cannot add variants after test has started"
}
{
"success": false,
"error": "Adding a variant to an A/B test in an active sequence requires confirmLiveChange=true"
}
{
"success": false,
"error": "Maximum of 5 variants allowed"
}
{
"success": false,
"error": "Unauthorized"
}
{
"success": false,
"error": "A/B test not found"
}
{
"success": false,
"error": "Failed to create A/B test variant"
}
Add a variant to a draft campaign or sequence A/B test. The next variant label (B, C, …) is assigned automatically. A test can have at most 5 variants, and variants cannot be added after the test has started. Sequence variants receive their own editable email template; when the parent sequence is active, pass
confirmLiveChange: true because the new variant immediately enters the live rotation.
Request
string
required
A/B test ID.
string
required
Variant subject line.
string
Variant preview text.
array
Variant body blocks. Defaults to the campaign or sequence control email blocks when omitted.
boolean
Required as
true when the A/B test belongs to an active sequence.curl -X POST "https://api.sequenzy.com/api/v1/ab-tests/ab_abc123/variants" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"subject": "Third subject idea"}'
Responses
{
"success": true,
"abTest": {
"id": "ab_abc123",
"campaignId": "camp_abc123",
"status": "draft",
"variants": [
{ "id": "var_a", "label": "A", "subject": "A quick update" },
{ "id": "var_b", "label": "B", "subject": "Alternative subject line" },
{ "id": "var_c", "label": "C", "subject": "Third subject idea" }
]
}
}
{
"success": false,
"error": "Cannot add variants after test has started"
}
{
"success": false,
"error": "Adding a variant to an A/B test in an active sequence requires confirmLiveChange=true"
}
{
"success": false,
"error": "Maximum of 5 variants allowed"
}
{
"success": false,
"error": "Unauthorized"
}
{
"success": false,
"error": "A/B test not found"
}
{
"success": false,
"error": "Failed to create A/B test variant"
}
⌘I
Add A/B Test Variant
curl --request POST \
--url https://api.sequenzy.com/api/v1/ab-tests/{abTestId}/variants \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"subject": "<string>",
"previewText": "<string>",
"blocks": [
{}
],
"confirmLiveChange": true
}
'import requests
url = "https://api.sequenzy.com/api/v1/ab-tests/{abTestId}/variants"
payload = {
"subject": "<string>",
"previewText": "<string>",
"blocks": [{}],
"confirmLiveChange": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
subject: '<string>',
previewText: '<string>',
blocks: [{}],
confirmLiveChange: true
})
};
fetch('https://api.sequenzy.com/api/v1/ab-tests/{abTestId}/variants', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sequenzy.com/api/v1/ab-tests/{abTestId}/variants",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'subject' => '<string>',
'previewText' => '<string>',
'blocks' => [
[
]
],
'confirmLiveChange' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sequenzy.com/api/v1/ab-tests/{abTestId}/variants"
payload := strings.NewReader("{\n \"subject\": \"<string>\",\n \"previewText\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"confirmLiveChange\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sequenzy.com/api/v1/ab-tests/{abTestId}/variants")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"subject\": \"<string>\",\n \"previewText\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"confirmLiveChange\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sequenzy.com/api/v1/ab-tests/{abTestId}/variants")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"subject\": \"<string>\",\n \"previewText\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"confirmLiveChange\": true\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"abTest": {
"id": "ab_abc123",
"campaignId": "camp_abc123",
"status": "draft",
"variants": [
{ "id": "var_a", "label": "A", "subject": "A quick update" },
{ "id": "var_b", "label": "B", "subject": "Alternative subject line" },
{ "id": "var_c", "label": "C", "subject": "Third subject idea" }
]
}
}
{
"success": false,
"error": "Cannot add variants after test has started"
}
{
"success": false,
"error": "Adding a variant to an A/B test in an active sequence requires confirmLiveChange=true"
}
{
"success": false,
"error": "Maximum of 5 variants allowed"
}
{
"success": false,
"error": "Unauthorized"
}
{
"success": false,
"error": "A/B test not found"
}
{
"success": false,
"error": "Failed to create A/B test variant"
}