Campaigns
Edit Campaign Variation with AI
Change one variation with AI and save it
POST
/
api
/
v1
/
campaigns
/
{campaignId}
/
variations
/
{variationId}
/
edit
Edit Campaign Variation with AI
curl --request POST \
--url https://api.sequenzy.com/api/v1/campaigns/{campaignId}/variations/{variationId}/edit \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"prompt": "<string>",
"sectionIds": [
"<string>"
]
}
'import requests
url = "https://api.sequenzy.com/api/v1/campaigns/{campaignId}/variations/{variationId}/edit"
payload = {
"prompt": "<string>",
"sectionIds": ["<string>"]
}
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({prompt: '<string>', sectionIds: ['<string>']})
};
fetch('https://api.sequenzy.com/api/v1/campaigns/{campaignId}/variations/{variationId}/edit', 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/campaigns/{campaignId}/variations/{variationId}/edit",
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([
'prompt' => '<string>',
'sectionIds' => [
'<string>'
]
]),
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/campaigns/{campaignId}/variations/{variationId}/edit"
payload := strings.NewReader("{\n \"prompt\": \"<string>\",\n \"sectionIds\": [\n \"<string>\"\n ]\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/campaigns/{campaignId}/variations/{variationId}/edit")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"prompt\": \"<string>\",\n \"sectionIds\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sequenzy.com/api/v1/campaigns/{campaignId}/variations/{variationId}/edit")
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 \"prompt\": \"<string>\",\n \"sectionIds\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"variation": {
"id": "var_9xk2",
"emailId": "email_abc123",
"parentId": null,
"label": "V2",
"name": "Warm and personal",
"summary": "Rewrote the opening in a friendlier voice and shortened the body.",
"prompt": "Three warmer, shorter versions",
"style": "fresh",
"status": "ready",
"error": null,
"subject": "A quick note about our pricing",
"previewText": null,
"blocks": [
{ "id": "h1", "type": "heading", "content": "Pricing, simplified", "level": 1 }
],
"emailTheme": null,
"fontFamily": null,
"position": null,
"inUse": false,
"usedAt": null,
"createdAt": "2026-10-14T09:12:00.000Z",
"updatedAt": "2026-10-15T08:02:13.000Z"
},
"summary": "Made the headline shorter and punchier."
}
{
"error": "I couldn't make that change without rewriting your copy, so I left the email unchanged."
}
{
"error": "This variation changed while the AI was editing it. Try again."
}
Changes one
ready variation with AI and saves the result over it, like an edit in the editor. Say what should change in prompt, in any language. With sectionIds, only those top-level blocks change and everything else stays exactly as it is. A whole-variation edit can also give the variation its own emailTheme and fontFamily, for example when you ask for a darker look.
The request runs synchronously and can take up to a minute. The campaign email does not change; use the variation for that. To compare several alternatives before choosing, use Generate Section Options or Generate Variations instead.
If the variation changes while the AI is working on it (another request updates it), the edit is not saved and you get a 409: send the request again.
Request
string
required
Campaign ID. Email campaigns only.
string
required
Variation ID. It must be
ready.string
required
What should change, 1 to 2,000 characters, in any language.
string[]
Only change these top-level blocks (up to 50). Omit to change the whole
variation.
curl -X POST "https://api.sequenzy.com/api/v1/campaigns/camp_abc123/variations/var_9xk2/edit" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "prompt": "Make the headline punchier", "sectionIds": ["h1"] }'
Response
object
The variation, changed and saved. See List
Variations for its fields.
string
What the edit changed, in a sentence.
{
"success": true,
"variation": {
"id": "var_9xk2",
"emailId": "email_abc123",
"parentId": null,
"label": "V2",
"name": "Warm and personal",
"summary": "Rewrote the opening in a friendlier voice and shortened the body.",
"prompt": "Three warmer, shorter versions",
"style": "fresh",
"status": "ready",
"error": null,
"subject": "A quick note about our pricing",
"previewText": null,
"blocks": [
{ "id": "h1", "type": "heading", "content": "Pricing, simplified", "level": 1 }
],
"emailTheme": null,
"fontFamily": null,
"position": null,
"inUse": false,
"usedAt": null,
"createdAt": "2026-10-14T09:12:00.000Z",
"updatedAt": "2026-10-15T08:02:13.000Z"
},
"summary": "Made the headline shorter and punchier."
}
{
"error": "I couldn't make that change without rewriting your copy, so I left the email unchanged."
}
{
"error": "This variation changed while the AI was editing it. Try again."
}
Errors
| Status | Meaning |
|---|---|
400 | The AI changed nothing (the error says why), a section is not in the variation, or the campaign is not an email campaign. |
401 | Missing or invalid API key. |
404 | The campaign or variation was not found. |
409 | The variation is still generating or failed, or it changed while the AI was editing it. |
500 | The edit failed. Send the request again. |
⌘I
Edit Campaign Variation with AI
curl --request POST \
--url https://api.sequenzy.com/api/v1/campaigns/{campaignId}/variations/{variationId}/edit \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"prompt": "<string>",
"sectionIds": [
"<string>"
]
}
'import requests
url = "https://api.sequenzy.com/api/v1/campaigns/{campaignId}/variations/{variationId}/edit"
payload = {
"prompt": "<string>",
"sectionIds": ["<string>"]
}
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({prompt: '<string>', sectionIds: ['<string>']})
};
fetch('https://api.sequenzy.com/api/v1/campaigns/{campaignId}/variations/{variationId}/edit', 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/campaigns/{campaignId}/variations/{variationId}/edit",
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([
'prompt' => '<string>',
'sectionIds' => [
'<string>'
]
]),
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/campaigns/{campaignId}/variations/{variationId}/edit"
payload := strings.NewReader("{\n \"prompt\": \"<string>\",\n \"sectionIds\": [\n \"<string>\"\n ]\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/campaigns/{campaignId}/variations/{variationId}/edit")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"prompt\": \"<string>\",\n \"sectionIds\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sequenzy.com/api/v1/campaigns/{campaignId}/variations/{variationId}/edit")
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 \"prompt\": \"<string>\",\n \"sectionIds\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"variation": {
"id": "var_9xk2",
"emailId": "email_abc123",
"parentId": null,
"label": "V2",
"name": "Warm and personal",
"summary": "Rewrote the opening in a friendlier voice and shortened the body.",
"prompt": "Three warmer, shorter versions",
"style": "fresh",
"status": "ready",
"error": null,
"subject": "A quick note about our pricing",
"previewText": null,
"blocks": [
{ "id": "h1", "type": "heading", "content": "Pricing, simplified", "level": 1 }
],
"emailTheme": null,
"fontFamily": null,
"position": null,
"inUse": false,
"usedAt": null,
"createdAt": "2026-10-14T09:12:00.000Z",
"updatedAt": "2026-10-15T08:02:13.000Z"
},
"summary": "Made the headline shorter and punchier."
}
{
"error": "I couldn't make that change without rewriting your copy, so I left the email unchanged."
}
{
"error": "This variation changed while the AI was editing it. Try again."
}