Skip to content

Save the content as a new version (autosave)

PUT
/api/v1/workspaces/{workspace}/campaigns/{campaignId}/content
curl --request PUT \
--url https://reputecast.example.com/api/v1/workspaces/acme-newsletter/campaigns/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/content \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "abTest": { "bestTime": true, "durationHours": 1, "kind": "subject", "metric": "human_opens", "testPercent": 1, "variants": [ { "html": "example", "key": "A", "mjml": "example", "preheader": "example", "sendTime": "example", "subject": "example" } ], "winner": "example" }, "baseVersion": 1, "force": true, "html": "example", "label": "example", "mjml": "example", "preheader": "example", "source": "autosave", "subject": "example" }'

Permission: campaigns:edit

Fails with 409 version_conflict when someone saved a newer version since baseVersion; the problem’s meta says who, when and which sections each side changed. Send force: true to keep yours on top.

workspace
required

Workspace slug

string
/^[a-z0-9][a-z0-9-]{1,62}$/

Workspace slug

campaignId
required
string format: uuid
language

Save a language version (its code, such as de); empty saves the source

string
<= 16 characters

Save a language version (its code, such as de); empty saves the source

Media typeapplication/json
object
abTest
object
bestTime
boolean
durationHours
required
integer format: int64
>= 1 <= 72
kind
required
string
Allowed values: subject content send_time
metric
required
string
Allowed values: human_opens clicks manual
testPercent
required

Share of the audience in the test

integer format: int64
>= 5 <= 50
variants
required
Array<object>
>= 2 items <= 3 items
object
html
string
<= 2000000 characters
key
required

Variant A is the campaign itself

string
Allowed values: A B C
mjml
string
<= 2000000 characters
preheader
string
<= 500 characters
sendTime
string
/^([01]\d|2[0-3]):[0-5]\d$/
subject
string
<= 998 characters
winner
string
baseVersion
required
integer format: int64
>= 1
force
boolean
html
string
<= 2500000 characters
label
string
<= 200 characters
mjml
string
<= 2000000 characters
preheader
string
<= 500 characters
source
string
default: autosave
Allowed values: autosave manual import template
subject
string
<= 998 characters

OK

Media typeapplication/json
object
contentHash
required
string
html
required
string
plainText
required
string
savedAt
required
string format: date-time
sizeBytes
required
integer format: int64
version
required
integer format: int64

Example generated

{
"contentHash": "example",
"html": "example",
"plainText": "example",
"savedAt": "2026-04-15T12:00:00Z",
"sizeBytes": 1,
"version": 1
}

Error

Media typeapplication/problem+json
object
code

Stable error code, e.g. permission_denied

string
detail

A human-readable explanation specific to this occurrence of the problem.

string
errors

Optional list of individual error details

Array<object>
object
location

Where the error occurred, e.g. ‘body.items[3].tags’ or ‘path.thing-id’

string
message

Error message text

string
value

The value at the given location

helpers

Members who hold the missing permission

Array<string>
instance

A URI reference that identifies the specific occurrence of the problem.

string format: uri
meta
object
key
additional properties
permission

The missing permission key

string
status

HTTP status code

integer format: int64
title

A short, human-readable summary of the problem type. This value should not change between occurrences of the error.

string
type

A URI reference to human-readable documentation for the error.

string format: uri
default: about:blank

Example

{
"detail": "Property foo is required but is missing.",
"instance": "https://example.com/error-log/abc123",
"status": 400,
"title": "Bad Request",
"type": "about:blank"
}