---
title: "Add a variant, with optional hero/badge images (admin only)"
method: POST
path: "/api/admin/campaigns/{id}/variants"
tags: ["Admin - Campaigns"]
---

# Add a variant, with optional hero/badge images (admin only)

`POST /api/admin/campaigns/{id}/variants`

## Request

- Base URL: `https://api.rewritelifestyle.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.rewritelifestyle.ai/api/admin/campaigns/{id}/variants`
- Auth: HTTP bearer

## Path parameters

- `id` number, required

## Request body `multipart/form-data`

- CreateCampaignVariantDto
  - `name` string, required: Internal label, never shown
  - `priority` number: Highest matching variant wins
  - `is_active` boolean
  - `audience_all` string[]
  - `audience_any` string[]
  - `audience_none` string[]
  - `pill_text` object
  - `headline` string, required
  - `body` object
  - `primary_cta_label` object
  - `primary_cta_action_type` 'deeplink' | 'url' | 'in_app_route' | 'checkout' | 'dismiss' | 'none'
  - `primary_cta_action_value` object
  - `secondary_cta_label` object
  - `secondary_cta_action_type` 'deeplink' | 'url' | 'in_app_route' | 'checkout' | 'dismiss' | 'none'
  - `secondary_cta_action_value` object
  - `footnote` object
  - `terms_label` object
  - `terms_url` object
  - `extra_media` CampaignExtraMediaDto[]: Extra images beyond hero/badge, as JSON. Keys must already be uploaded.
    - `role` string, required
    - `s3_key` string, required
    - `alt` object
  - `extra` object: Template-specific passthrough, as JSON. Sent to the client verbatim.

## Response `201`

---

[API](https://skmtc.dev/rewritelifestyle/apis/rewrite-lifestyle-api.md) - [All operations](https://skmtc.dev/rewritelifestyle/apis/rewrite-lifestyle-api/llms.txt) - [OpenAPI document](https://skmtc.dev/rewritelifestyle/apis/rewrite-lifestyle-api/revisions/28695827f27a?raw)
