Overview
You can update a formula’s name, targeting settings, schedule, and more using the update endpoint. To replace the message structure or add new alternates, use the message-content endpoints.
POST /formulas/{formula_id}/update
All fields are optional — only include the fields you want to change.
| Field | Type | Description |
|---|
name | string | The display name of the formula |
deeplink | string | Deep link URL for the message CTA |
send_start | datetime | ISO 8601 datetime when delivery becomes eligible |
send_stop | datetime | ISO 8601 datetime when delivery stops |
send_start_date | date | Date-only version of send start |
send_stop_date | date | Date-only version of send stop |
is_controlled_message | boolean | Whether this is a controlled A/B test message |
timezone | string | IANA timezone string (e.g. "America/New_York") |
audience_id | uuid | Target audience segment |
topic_id | uuid | Topic association |
tags | array of uuids | Replace all tag associations |
labels | array | Replace formula-level label associations |
compound_trigger_id | uuid | Compound trigger rule for delivery |
dataset_id | integer | Dataset used for user-level personalization |
override_provider_frequency_limits | boolean | Bypass provider-level send frequency caps |
additional_metadata | object | Free-form metadata |
import requests
BASE_URL = "https://composer.api.aampe.com/api"
headers = {"X-API-KEY": "YOUR_API_KEY", "Content-Type": "application/json"}
FORMULA_ID = 215
response = requests.post(
f"{BASE_URL}/formulas/{FORMULA_ID}/update",
headers=headers,
json={
"name": "Welcome Back Campaign — Spring",
"send_start": "2026-04-10T09:00:00Z",
"send_stop": "2026-04-30T23:59:59Z",
"timezone": "America/New_York",
},
)
response.raise_for_status()
print(f"Updated: {response.json()['name']}")
Replacing the Message Structure
To replace what a formula’s message looks like — its slots and seed variants — update the message-content directly:
PUT /message-contents/{message_content_id}
This is a full replacement. Include every section and slot you want to keep — anything omitted will be removed.
Step 1 — Get the message-content ID
mc_resp = requests.get(
f"{BASE_URL}/formulas/{FORMULA_ID}/message-contents",
headers=headers,
)
mc_resp.raise_for_status()
message_content_id = mc_resp.json()[0]["id"]
Step 2 — Replace the structure
Pre-generate a component instance ID for each slot. The text in children[0].text becomes the seed variant (first alternate) for that slot.
import uuid
CT_OFFERING = "8e3f0698-7564-4522-9c07-49686667c0b4"
CT_CTA = "8c0b9b73-b305-4f93-b41f-bde62cebac98"
header_component_id = str(uuid.uuid4())
body_component_id = str(uuid.uuid4())
response = requests.put(
f"{BASE_URL}/message-contents/{message_content_id}",
headers=headers,
json={
"id": message_content_id,
"structure": [
{
"kind": "section",
"sectionType": "header",
"children": [
{
"id": header_component_id,
"kind": "variant",
"variantType": "Offering",
"componentId": CT_OFFERING,
"children": [{"text": "Spring is here, {{first_name}}!"}],
}
],
},
{
"kind": "section",
"sectionType": "body",
"children": [
{
"id": body_component_id,
"kind": "variant",
"variantType": "CallToAction",
"componentId": CT_CTA,
"children": [{"text": "Check out what's new."}],
}
],
},
],
"deeplink": None,
"deeplink_dataset_field_id": None,
},
)
response.raise_for_status()
After replacing the structure, add more alternates via POST /variants/create/bulk using the component instance IDs.
To add alternates to a formula without touching the structure, first fetch the existing component instance IDs from the message-content, then bulk-create:
# Get the existing structure to find component instance IDs
mc_detail = requests.get(
f"{BASE_URL}/message-contents/{message_content_id}",
headers={"X-API-KEY": "YOUR_API_KEY"},
)
mc_detail.raise_for_status()
structure = mc_detail.json()["structure"]
# Build a map: variantType → component instance ID
slot_ids = {}
for section in structure:
for child in section.get("children", []):
if child.get("kind") == "variant":
slot_ids[child["variantType"]] = child["id"]
# Add new alternates
requests.post(
f"{BASE_URL}/variants/create/bulk",
headers={"X-API-KEY": "YOUR_API_KEY", "Content-Type": "application/json"},
json=[
{"component_id": slot_ids["Offering"], "content": "New spring deals await.", "label_id": 104},
{"component_id": slot_ids["Offering"], "content": "Your seasonal picks are here.", "label_id": 105},
],
).raise_for_status()
Formulas are listed by lifecycle category and message type:
import requests
BASE_URL = "https://composer.api.aampe.com/api"
headers = {"X-API-KEY": "YOUR_API_KEY"}
for category in ("Draft", "Live"):
resp = requests.get(
f"{BASE_URL}/formulas/category/{category}",
headers=headers,
params={"message_type": "push"},
)
resp.raise_for_status()
for f in resp.json():
print(f"[{category}] ID: {f['id']} Name: {f['name']}")