Skip to main content

How Multilanguage Works

Each formula can have one version of its content per language. These language versions are separate message-content records — each with its own structure and variants.
Formula
├── message-content (English — default)
│     ├── structure
│     └── variants: "Find your calm", "Breathe and begin", ...
└── message-content (German)
      ├── structure
      └── variants: "Finde deine Ruhe", "Atme und beginne", ...
When Aampe sends a message, it selects the message-content that matches the user’s language. Each language version is personalized independently — Aampe learns label preferences per language.

Step 1 — List Available Languages

import requests

BASE_URL = "https://composer.api.aampe.com/api"
headers  = {"X-API-KEY": "YOUR_API_KEY"}

response = requests.get(f"{BASE_URL}/languages", headers=headers)
response.raise_for_status()

for lang in response.json():
    default = " (default)" if lang["is_default"] else ""
    print(f"{lang['id']}  {lang['name']}{default}")
Response:
[
  {
    "id": "4abd0bdd-9d63-44de-b9d1-affcd3f61bfc",
    "name": "Default Language",
    "is_default": true,
    "status": "active"
  }
]

Step 2 — Create a Language (if it doesn’t exist)

response = requests.post(
    f"{BASE_URL}/languages",
    headers={**headers, "Content-Type": "application/json"},
    json={
        "name":        "German",
        "description": "German language",
    },
)
response.raise_for_status()
german_language_id = response.json()["id"]
FieldTypeRequiredDescription
namestringYesDisplay name for the language
descriptionstringNoOptional description

Step 3 — Create the Formula

Create the formula as normal. The API automatically creates a message-content for the default language. You will add the German message-content separately.
import uuid

CT_OFFERING          = "8e3f0698-7564-4522-9c07-49686667c0b4"
CT_VALUE_PROPOSITION = "72150aa9-6b20-4d95-9659-0c05701ef7de"

headers_json = {**headers, "Content-Type": "application/json"}

formula_resp = requests.post(f"{BASE_URL}/formulas", headers=headers_json, json={
    "name":         "My Multilanguage Formula",
    "message_type": "push",
    "structure":    [],
})
formula_resp.raise_for_status()
formula_id = formula_resp.json()["id"]

# Default language message-content is auto-created
mc_resp = requests.get(f"{BASE_URL}/formulas/{formula_id}/message-contents", headers=headers)
mc_resp.raise_for_status()
default_mc_id = mc_resp.json()[0]["id"]

Step 4 — Set the Default Language Content

Pre-generate component instance IDs. These identify the slots for the default language — each language uses its own component instance IDs.
en_header_cid = str(uuid.uuid4())
en_body_cid   = str(uuid.uuid4())

requests.put(
    f"{BASE_URL}/message-contents/{default_mc_id}",
    headers=headers_json,
    json={
        "id": default_mc_id,
        "structure": [
            {
                "kind": "section",
                "sectionType": "header",
                "children": [{
                    "id":          en_header_cid,
                    "kind":        "variant",
                    "variantType": "Offering",
                    "componentId": CT_OFFERING,
                    "labelId":     101,
                    "children":    [{"text": "Find your calm"}],
                }],
            },
            {
                "kind": "section",
                "sectionType": "body",
                "children": [{
                    "id":          en_body_cid,
                    "kind":        "variant",
                    "variantType": "ValueProposition",
                    "componentId": CT_VALUE_PROPOSITION,
                    "labelId":     103,
                    "children":    [{"text": "5 minutes a day reduces stress hormones 30%."}],
                }],
            },
        ],
        "deeplink": None,
        "deeplink_dataset_field_id": None,
    },
).raise_for_status()

# Add remaining English alternates
requests.post(f"{BASE_URL}/variants/create/bulk", headers=headers_json, json=[
    {"component_id": en_header_cid, "content": "Breathe and begin",              "label_id": 102},
    {"component_id": en_header_cid, "content": "A moment of stillness awaits",   "label_id": 101},
    {"component_id": en_body_cid,   "content": "Fall asleep faster and wake up restored.", "label_id": 103},
]).raise_for_status()

Step 5 — Add a New Language Version

Create a new message-content for German by posting with formula_id and language_id:
de_mc_resp = requests.post(
    f"{BASE_URL}/message-contents",
    headers=headers_json,
    json={
        "formula_id":  formula_id,
        "language_id": german_language_id,
    },
)
de_mc_resp.raise_for_status()
german_mc_id = de_mc_resp.json()["id"]
Then set its structure and variants the same way as the default language — using new component instance IDs:
de_header_cid = str(uuid.uuid4())
de_body_cid   = str(uuid.uuid4())

requests.put(
    f"{BASE_URL}/message-contents/{german_mc_id}",
    headers=headers_json,
    json={
        "id": german_mc_id,
        "structure": [
            {
                "kind": "section",
                "sectionType": "header",
                "children": [{
                    "id":          de_header_cid,
                    "kind":        "variant",
                    "variantType": "Offering",
                    "componentId": CT_OFFERING,
                    "labelId":     101,
                    "children":    [{"text": "Finde deine Ruhe"}],
                }],
            },
            {
                "kind": "section",
                "sectionType": "body",
                "children": [{
                    "id":          de_body_cid,
                    "kind":        "variant",
                    "variantType": "ValueProposition",
                    "componentId": CT_VALUE_PROPOSITION,
                    "labelId":     103,
                    "children":    [{"text": "5 Minuten täglich senken Stresshormone um 30%."}],
                }],
            },
        ],
        "deeplink": None,
        "deeplink_dataset_field_id": None,
    },
).raise_for_status()

requests.post(f"{BASE_URL}/variants/create/bulk", headers=headers_json, json=[
    {"component_id": de_header_cid, "content": "Atme und beginne",                          "label_id": 102},
    {"component_id": de_header_cid, "content": "Ein Moment der Stille erwartet dich",       "label_id": 101},
    {"component_id": de_body_cid,   "content": "Schlaf schneller ein und wache erholt auf.", "label_id": 103},
]).raise_for_status()

Reading Back All Language Versions

all_mc = requests.get(
    f"{BASE_URL}/formulas/{formula_id}/message-contents",
    headers=headers,
).json()

for mc in all_mc:
    lang_id  = mc["language_id"]
    mc_id    = mc["id"]
    variants = requests.get(f"{BASE_URL}/message-contents/{mc_id}/variants", headers=headers).json()
    print(f"Language: {lang_id}{len(variants)} variants")

Key Points

  • The default language’s message-content is auto-created with the formula — do not create it manually
  • Each language version uses its own component instance IDs (the UUIDs you generate per slot)
  • Labels and component types are shared across languages — you do not need to recreate them
  • Each language version is personalized independently by Aampe