---
title: "Create A/B test"
method: POST
path: "/ab-tests"
tags: ["A/B Tests"]
---

# Create A/B test

`POST /ab-tests`

Creates a draft campaign A/B test or converts a sequence email node to action_ab_test. Provide exactly one owner. Variant A is copied into an independent email for sequences; sequence conversions require at least one extra variant.

## Request body

- object
  - `campaignId` string — Campaign to attach the test to. Must be in draft or rejected status. Mutually exclusive with automationNodeId.
  - `automationNodeId` string — Sequence action_email node to convert. Mutually exclusive with campaignId.
  - `confirmLiveChange` boolean — Must be true when converting an email node in an active sequence.
  - `name` string — Test name. Defaults to "A/B Test for <campaign name>".
  - `testPercentage` integer — Campaign-only share of the audience that receives test sends. Sequence tests use winnerThreshold.
  - `testDurationMinutes` integer — Campaign-only duration before winner selection. Sequence tests select after winnerThreshold recipients.
  - `winnerCriteria` 'open_rate' | 'click_rate' — Metric used to pick the winner. For sequence tests, an explicit value overrides the testType default.
  - `testType` 'subject' | 'content' — Sequence variant strategy. Subject defaults to open_rate and content defaults to click_rate unless winnerCriteria is explicit.
  - `winnerThreshold` integer — Number of sequence recipients in the test sample.
  - `variants` object[] — Extra variants beyond the control. Required (min 1) when converting with automationNodeId. Total variants cannot exceed 5.
    - `subject` string, required
    - `previewText` string
    - `blocks` EmailBlock[]
      - `id` string
      - `type` 'text' | 'html' | 'heading' | 'list' | 'button' | 'spacer' | 'divider' | 'image' | 'columns' | 'conditional-group' | 'repeat' | 'card' | 'cta' | 'social' | 'logo' | 'header' | 'footer' | 'video' | 'product' | 'discount-code' | 'code' | 'countdown' | 'hero' | 'testimonial' | 'gallery' | 'badge' | 'table' | 'features' | 'image-card' | 'pricing' | 'author' | 'article' | 'rating' | 'stats' | 'steps' | 'product-grid' | 'poll', required
      - `content` string — Content for text, html, and heading-like blocks.
      - `styles` object — Per-block visual styles. For compatibility, style fields such as backgroundColor, backgroundOpacity, borderColor, borderWidth, and borderRadius can also be supplied at the block top level and are normalized into this object.
        - `paddingTop` number
        - `paddingBottom` number
        - `paddingLeft` number
        - `paddingRight` number
        - `backgroundColor` string
        - `backgroundOpacity` number — Background opacity percentage from 0 to 100.
        - `textColor` string
        - `textAlign` 'left' | 'center' | 'right'
        - `borderRadius` number
        - `borderColor` string
        - `borderWidth` number
        - `bleed` boolean — Stretch the block edge-to-edge across the email container. Top-level blocks only.
      - `conditions` object[] — Optional per-block display rules. The block renders only when every rule matches. The same shape is used for a conditional-group block's top-level `conditions`.
        - `id` string, required
        - `field` 'variable' | 'attribute' | 'email' | 'firstName' | 'lastName', required — `variable` resolves a merge-tag path from the transactional send `variables` or an automation `event` payload (nested paths like `order.total` or `event.plan` work). `attribute` reads a stored subscriber attribute. `email`, `firstName`, and `lastName` read core subscriber fields.
        - `operator` 'is' | 'is_not' | 'contains' | 'not_contains' | 'gt' | 'gte' | 'lt' | 'lte' | 'is_empty' | 'is_not_empty', required
        - `value` string, required — For `variable` and `attribute`, use `name:value` - the part before the colon is the variable path or attribute name, and the part after it is the comparison value. For `email`, `firstName`, and `lastName`, provide the plain comparison string.

## Response `200`

A/B test created

- object
  - `success` boolean
  - `abTest` ABTest
    - `id` string
    - `companyId` string
    - `kind` 'campaign' | 'sequence' — Identifies which settings model applies to this test.
    - `campaignId` string, nullable
    - `automationNodeId` string, nullable
    - `name` string, nullable
    - `status` string
    - `testPercentage` integer — Campaign test audience percentage. Sequence tests retain the legacy internal sentinel value 100; use settings instead.
    - `testDurationMinutes` integer — Campaign test duration. Sequence tests retain the legacy internal sentinel value 0; use settings instead.
    - `winnerCriteria` string
    - `testType` 'subject' | 'content' — Effective sequence variant strategy. Present for sequence tests.
    - `winnerThreshold` integer — Effective sequence recipient threshold. Present for sequence tests.
    - `settings` object — Effective settings for this test kind. Campaign tests return testPercentage, testDurationMinutes, and winnerCriteria; sequence tests return testType, winnerThreshold, and winnerCriteria.
    - `winningVariantId` string, nullable
    - `winnerSelectedAt` string, date-time, nullable
    - `testStartedAt` string, date-time, nullable
    - `testEndsAt` string, date-time, nullable
    - `createdAt` string, date-time
    - `updatedAt` string, date-time
    - `variants` ABTestVariant[]
      - `id` string
      - `variantId` string
      - `abTestId` string
      - `label` string
      - `variantLabel` string
      - `emailId` string
      - `subject` string
      - `previewText` string, nullable
      - `blocks` EmailBlock[]
        - `id` string
        - `type` 'text' | 'html' | 'heading' | 'list' | 'button' | 'spacer' | 'divider' | 'image' | 'columns' | 'conditional-group' | 'repeat' | 'card' | 'cta' | 'social' | 'logo' | 'header' | 'footer' | 'video' | 'product' | 'discount-code' | 'code' | 'countdown' | 'hero' | 'testimonial' | 'gallery' | 'badge' | 'table' | 'features' | 'image-card' | 'pricing' | 'author' | 'article' | 'rating' | 'stats' | 'steps' | 'product-grid' | 'poll', required
        - `content` string — Content for text, html, and heading-like blocks.
        - `styles` object — Per-block visual styles. For compatibility, style fields such as backgroundColor, backgroundOpacity, borderColor, borderWidth, and borderRadius can also be supplied at the block top level and are normalized into this object.
          - `paddingTop` number
          - `paddingBottom` number
          - `paddingLeft` number
          - `paddingRight` number
          - `backgroundColor` string
          - `backgroundOpacity` number — Background opacity percentage from 0 to 100.
          - `textColor` string
          - `textAlign` 'left' | 'center' | 'right'
          - `borderRadius` number
          - `borderColor` string
          - `borderWidth` number
          - `bleed` boolean — Stretch the block edge-to-edge across the email container. Top-level blocks only.
        - `conditions` object[] — Optional per-block display rules. The block renders only when every rule matches. The same shape is used for a conditional-group block's top-level `conditions`.
          - `id` string, required
          - `field` 'variable' | 'attribute' | 'email' | 'firstName' | 'lastName', required — `variable` resolves a merge-tag path from the transactional send `variables` or an automation `event` payload (nested paths like `order.total` or `event.plan` work). `attribute` reads a stored subscriber attribute. `email`, `firstName`, and `lastName` read core subscriber fields.
          - `operator` 'is' | 'is_not' | 'contains' | 'not_contains' | 'gt' | 'gte' | 'lt' | 'lte' | 'is_empty' | 'is_not_empty', required
          - `value` string, required — For `variable` and `attribute`, use `name:value` - the part before the colon is the variable path or attribute name, and the part after it is the comparison value. For `email`, `firstName`, and `lastName`, provide the plain comparison string.
      - `testSends` integer
      - `testOpens` integer
      - `testClicks` integer
      - `isWinner` boolean
      - `localizations` object[]
      - `createdAt` string, date-time
  - `warnings` string[] — Non-blocking advisories about a successful write. Present when an input was discarded or did not take effect as requested. This includes block fields that do not render as their names suggest, sequence email-step formatting restored on top of submitted blocks, and sender-identity conflicts such as a replyToName that differs from the saved profile. Each message identifies the affected input and gives recovery guidance. Absent when there is nothing to report.

## Other responses

- `400` — Validation error, invalid owner, or non-draft campaign
- `401` — Unauthorized
- `404` — Campaign, sequence node, or email not found
- `409` — A/B test already exists for this campaign or sequence node
- `500` — A/B test could not be created

---

[API](https://skmtc.net/sequenzy/apis/sequenzy-api.md) · [All operations](https://skmtc.net/sequenzy/apis/sequenzy-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/sequenzy/sequenzy-api/versions/af1cf9620482/schema)
