smartchat

Edit landing page draft

Applies edit operations to the draft of the landing page, never to the live page. Free pages and pages in the page model take different operations: see get_landing_catalog. If one operation is rejected nothing changes.

POST /v1/landing-page/operations

Permissionlanding:write (all permissions)
RiskWrite (no outside effect)
Idempotency-KeyRequired (how it works)
Safe to repeatSafe to repeat with the same Idempotency-Key: the first answer comes back and nothing is done twice.
Rate limit classwrite (120 requests per minute per key)
ConfirmationNone
MCP toolapply_landing_page_ops
Since version2026-10-25

#What it does

  • Changes data in your account. It does not send messages to contacts.
  • Safe to repeat with the same Idempotency-Key.

#Request

Header

NameRequiredDescription
AuthorizationyesBearer <key>
Idempotency-KeyyesA unique value for this operation, for example a UUID (1 to 255 visible ASCII characters).

Body (JSON)

NameTypeRequiredDescription
operationsarray of objectyesThe operations, applied in this order. up to 50 items
operations[].typestringyesKind of operation. See get_landing_catalog. one of: replace_text, set_page_title, set_page_description, set_design_token, add_section, update_section_data, change_variant, move_section, delete_section, set_style, set_settings, replace_media
operations[].findstringnoreplace_text: the text to find. It must occur exactly once in the page. up to 2000 characters
operations[].replacestringnoreplace_text: the new text (plain text). up to 2000 characters
operations[].textstringnoset_page_title (up to 160 characters), set_page_description (up to 300), replace_text in the page model (the new text). up to 2000 characters
operations[].tokenstringnoset_design_token: name of an existing design value, for example --brand-color. up to 41 characters
operations[].valuestringnoset_design_token: a color (#hex, rgb(), hsl()) or a length (px, rem, em, %). up to 60 characters
operations[].idstringnoPage model: id of the section or element (from get_landing_page include=sections). up to 40 characters
operations[].fieldstringnoPage model: field name, for example title or items[0].title. up to 100 characters
operations[].sectionobjectnoadd_section: the new section. kind block with type, variant and data, or kind free with layout and elements. See get_landing_catalog.
operations[].positionobjectnoadd_section: where the section goes. Default: at the end.
operations[].position.atstringnoThe start or the end of the page. one of: start, end
operations[].position.indexintegernoPlace number, counted from 0. 0 to 100
operations[].position.afterstringnoId of the section it goes after. up to 40 characters
operations[].position.beforestringnoId of the section it goes before. up to 40 characters
operations[].toobjectnomove_section: the new place.
operations[].to.atstringnoThe start or the end of the page. one of: start, end
operations[].to.indexintegernoPlace number, counted from 0. 0 to 100
operations[].to.afterstringnoId of the section it goes after. up to 40 characters
operations[].to.beforestringnoId of the section it goes before. up to 40 characters
operations[].dataobjectnoupdate_section_data: fields to change. A value null removes the field.
operations[].variantstringnochange_variant: the new variant of the section. up to 40 characters
operations[].styleobjectnoset_style: style values to change, for example palette or mood.
operations[].settingsobjectnoset_settings: settings to change. language sets the one language of the page.
operations[].urlstringnoreplace_media: address of the new image (https, from the media library of the account). up to 2000 characters
operations[].altstringnoreplace_media: short description of the image. up to 200 characters
operations[].decorativebooleannoreplace_media: true if the image only decorates.
operations[].originstringnoreplace_media: origin of the image. Always own. one of: own
dry_runbooleannoTrue: check and show the changes, write nothing.

#Examples

curl -X POST "https://api.smartchat.marketing/v1/landing-page/operations" \
  -H "Authorization: Bearer $SMARTCHAT_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "operations": [
    {
      "type": "replace_text",
      "find": "Fresh bread every morning",
      "replace": "Fresh bread from 6 o'\''clock"
    }
  ]
}'
import os
import uuid
import requests

response = requests.post(
    "https://api.smartchat.marketing/v1/landing-page/operations",
    headers={
        "Authorization": "Bearer " + os.environ["SMARTCHAT_API_KEY"],
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "operations": [
            {
                "type": "replace_text",
                "find": "Fresh bread every morning",
                "replace": "Fresh bread from 6 o'clock",
            },
        ],
    },
)
response.raise_for_status()
print(response.json())
const response = await fetch("https://api.smartchat.marketing/v1/landing-page/operations", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SMARTCHAT_API_KEY}`,
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "operations": [
      {
        "type": "replace_text",
        "find": "Fresh bread every morning",
        "replace": "Fresh bread from 6 o'clock"
      }
    ]
  }),
});
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());

Response (200):

{
  "object": "landing_page_operations",
  "applied": 1,
  "dry_run": false,
  "diff": [
    {
      "operation": 0,
      "field": "text",
      "before": "Fresh bread every morning",
      "after": "Fresh bread from 6 o'clock"
    }
  ],
  "has_draft": true
}

#Response

Status 200. Every response has the headers Request-Id, SmartChat-Version and X-RateLimit-*.

NameTypeDescription
objectstringAlways "landing_page_operations". always landing_page_operations
appliedintegerNumber of operations applied. 0 to 1000
dry_runbooleanTrue if nothing was written.
diffarray of objectBefore and after of every change. up to 1000 items
diff[].operationintegerIndex of the operation (free pages). 0 to 1000
diff[].kindstringKind of change (page model). one of: added, removed, changed, moved
diff[].fieldstringWhat changed. up to 200 characters
diff[].beforestringBefore. up to 600 characters
diff[].afterstringAfter. up to 600 characters
has_draftbooleanTrue if there is a draft after the call.

#Errors

CodeStatusWhen
idempotency_key_invalid400The 'Idempotency-Key' header must be 1 to 255 visible ASCII characters.
idempotency_key_required400This call needs an 'Idempotency-Key' header.
api_key_expired401This API key has expired.
api_key_invalid401This API key is not valid.
api_key_revoked401This API key was revoked.
authentication_required401No API key was sent. Send 'Authorization: Bearer <key>'.
insufficient_scope403This key lacks a required permission.
ip_not_allowed403This IP address is not allowed for this key.
not_found404This path does not exist.
idempotency_in_progress409A request with this idempotency key is still running.
idempotency_key_reused422This idempotency key was already used with a different request.
landing_language_single422A landing page has exactly one language.
landing_ops_rejected422Some operations were rejected. Nothing was changed.
validation_failed422A field is not valid.
rate_limited429Too many requests. Wait and try again.
internal_error500Something went wrong on our side.

All errors use one format.