> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tracklysms.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Update a Creative

> Update an existing creative. Only provided fields are modified.

Updates an existing creative in your account. Fields such as `name`, `status`, `creative_type`, `list_control_mode`, and `list_control_ids` can be updated independently -- omitted fields remain unchanged.

`message` and `offer_links` are the exception: they are re-validated together from the request body alone, so to change either one you must send **both** in the same request. Sending only `message` (without `offer_links`) or only `offer_links` (without `message`) fails validation -- the omitted field is treated as empty, not as its stored value. When both are sent, `character_count` and `segment_count` are automatically recalculated.

<Warning>
  `message` and `offer_links` are validated as a pair from the request body only. Always send both together when changing either -- sending one alone fails with `missing_link_placeholder` or `missing_offer_links_for_placeholders`, since the omitted field defaults to empty rather than falling back to the stored value.
</Warning>

## Path Parameters

<ParamField path="id" type="integer" required>
  The unique identifier of the creative to update.
</ParamField>

## Body Parameters

All body parameters are optional, except that `message` and `offer_links` must be sent together (see below). Only include the fields you want to change.

<ParamField body="name" type="string">
  Updated display name. Maximum 255 characters.
</ParamField>

<ParamField body="message" type="string">
  Updated message template. Maximum 1600 characters. Must contain at least one `{{linkN}}` placeholder. Must be sent together with `offer_links`; sending `message` without `offer_links` fails, because `offer_links` is read from the request body alone (defaulting to empty) rather than from the stored value.
</ParamField>

<ParamField body="offer_links" type="array">
  Updated array of offer link objects. Every `{{linkN}}` placeholder in the message must have a matching entry. Must be sent together with `message`; sending `offer_links` without `message` fails with `missing_link_placeholder`, because `message` is read from the request body alone (defaulting to empty) rather than from the stored value.

  <Expandable title="Offer link properties">
    <ParamField body="offer_links[].key" type="string" required>
      The placeholder key (e.g. `link1`).
    </ParamField>

    <ParamField body="offer_links[].offer_id" type="string" required>
      The ID of the offer to associate with this link. Must be a valid 24-character hexadecimal ObjectId, and the offer must exist and belong to your account.
    </ParamField>

    <ParamField body="offer_links[].url" type="string" optional>
      Optional URL override.
    </ParamField>

    <ParamField body="offer_links[].url_params" type="object" optional>
      Optional additional query parameters.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="status" type="string">
  Updated status. Accepted values: `active`, `paused`, `archived`. Note that unlike creation, you can set the status to `archived` during an update.
</ParamField>

<ParamField body="creative_type" type="string">
  Updated creative type. Accepted values: `automated`, `one_time`, `welcome`.
</ParamField>

<ParamField body="list_control_mode" type="string">
  List targeting control mode. Accepted values: `all`, `include`, `exclude`.
</ParamField>

<ParamField body="list_control_ids" type="array">
  List IDs (integers) to include or exclude when `list_control_mode` is `include` or `exclude`.
</ParamField>

## Response Fields

The response is the full updated creative object (flat, not wrapped).

<Expandable title="Creative object properties">
  <ResponseField name="id" type="integer">
    Unique identifier for the creative.
  </ResponseField>

  <ResponseField name="slug" type="string">
    Auto-generated unique identifier (e.g. `cre_summer-sale-promo_a1b2c3`).
  </ResponseField>

  <ResponseField name="name" type="string">
    Display name of the creative.
  </ResponseField>

  <ResponseField name="message" type="string">
    The message template with `{{linkN}}` placeholders.
  </ResponseField>

  <ResponseField name="offer_links" type="array">
    Array of offer link objects.
  </ResponseField>

  <ResponseField name="offers" type="array">
    Array of offer ID strings referenced by this creative.
  </ResponseField>

  <ResponseField name="status" type="string">
    Current status of the creative.
  </ResponseField>

  <ResponseField name="creative_type" type="string">
    The type of creative.
  </ResponseField>

  <ResponseField name="character_count" type="integer">
    Estimated character count (recalculated if message or offer\_links changed).
  </ResponseField>

  <ResponseField name="segment_count" type="integer">
    Estimated SMS segment count (recalculated if message or offer\_links changed).
  </ResponseField>

  <ResponseField name="created_at" type="datetime">
    ISO 8601 timestamp of when the creative was originally created.
  </ResponseField>

  <ResponseField name="list_control_mode" type="string">
    List targeting control mode. One of: `all` (default), `include`, `exclude`.
  </ResponseField>

  <ResponseField name="list_control_ids" type="array">
    List IDs used when `list_control_mode` is `include` or `exclude`.
  </ResponseField>
</Expandable>

## Examples

<RequestExample>
  ```bash cURL theme={null}
  curl -X PUT "https://api.tracklysms.com/api/v2/creatives/101" \
    -H "X-Api-Key: trk_your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Summer Sale Promo v2",
      "message": "Exclusive summer deals! Shop now: {{link1}} Browse more: {{link2}} Reply STOP to opt out.",
      "offer_links": [
        {
          "key": "link1",
          "offer_id": "665f1a2b3c4d5e6f70819201",
          "url_params": {"sub1": "sms"}
        },
        {
          "key": "link2",
          "offer_id": "665f1a2b3c4d5e6f70819204"
        }
      ]
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.put(
      "https://api.tracklysms.com/api/v2/creatives/101",
      headers={
          "X-Api-Key": "trk_your_api_key_here",
          "Content-Type": "application/json"
      },
      json={
          "name": "Summer Sale Promo v2",
          "message": "Exclusive summer deals! Shop now: {{link1}} Browse more: {{link2}} Reply STOP to opt out.",
          "offer_links": [
              {
                  "key": "link1",
                  "offer_id": "665f1a2b3c4d5e6f70819201",
                  "url_params": {"sub1": "sms"}
              },
              {
                  "key": "link2",
                  "offer_id": "665f1a2b3c4d5e6f70819204"
              }
          ]
      }
  )

  data = response.json()
  print(f"Updated: {data['name']}")
  print(f"New segment count: {data['segment_count']}")
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    "https://api.tracklysms.com/api/v2/creatives/101",
    {
      method: "PUT",
      headers: {
        "X-Api-Key": "trk_your_api_key_here",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        name: "Summer Sale Promo v2",
        message:
          "Exclusive summer deals! Shop now: {{link1}} Browse more: {{link2}} Reply STOP to opt out.",
        offer_links: [
          {
            key: "link1",
            offer_id: "665f1a2b3c4d5e6f70819201",
            url_params: { sub1: "sms" },
          },
          {
            key: "link2",
            offer_id: "665f1a2b3c4d5e6f70819204",
          },
        ],
      }),
    }
  );

  const data = await response.json();
  console.log(`Updated: ${data.name}`);
  ```
</RequestExample>

<ResponseExample>
  ```json 200 — Success theme={null}
  {
    "id": 101,
    "slug": "cre_summer-sale-promo-v2_a1b2c3",
    "name": "Summer Sale Promo v2",
      "message": "Exclusive summer deals! Shop now: {{link1}} Browse more: {{link2}} Reply STOP to opt out.",
      "offer_links": [
        {
          "key": "link1",
          "offer_id": "665f1a2b3c4d5e6f70819201",
          "url": null,
          "url_params": {"sub1": "sms"}
        },
        {
          "key": "link2",
          "offer_id": "665f1a2b3c4d5e6f70819204",
          "url": null,
          "url_params": {}
        }
      ],
      "offers": ["665f1a2b3c4d5e6f70819201", "665f1a2b3c4d5e6f70819204"],
      "status": "active",
      "creative_type": "automated",
      "character_count": 151,
      "segment_count": 1,
      "created_at": "2025-06-10T12:00:00",
      "list_control_mode": "all",
      "list_control_ids": []
  }
  ```

  ```json 400 — Validation Error theme={null}
  {
    "error": "Missing offer_links for placeholders: link2",
    "code": "missing_offer_links_for_placeholders"
  }
  ```

  ```json 404 — Not Found theme={null}
  {
    "error": "Creative not found",
    "code": "not_found"
  }
  ```

  ```json 401 — Unauthorized theme={null}
  {
    "error": "Invalid credentials",
    "code": "invalid_credentials"
  }
  ```
</ResponseExample>

## Error Codes

| HTTP Status | Error Code                             | Description                                                                                        |
| ----------- | -------------------------------------- | -------------------------------------------------------------------------------------------------- |
| 400         | `name_too_long`                        | The `name` exceeds 255 characters.                                                                 |
| 400         | `message_too_long`                     | The `message` exceeds 1600 characters.                                                             |
| 400         | `invalid_status`                       | The provided `status` is not `active`, `paused`, or `archived`.                                    |
| 400         | `invalid_creative_type`                | The provided `creative_type` is not `automated`, `one_time`, or `welcome`.                         |
| 400         | `invalid_list_control_mode`            | The provided `list_control_mode` is not `all`, `include`, or `exclude`.                            |
| 400         | `invalid_list_control_ids`             | `list_control_ids` is not a list of integers.                                                      |
| 400         | `missing_link_placeholder`             | The updated message must contain at least one `{{linkN}}` placeholder.                             |
| 400         | `missing_offer_links_for_placeholders` | One or more `{{linkN}}` placeholders in the message do not have a matching entry in `offer_links`. |
| 400         | `missing_offer_link_key`               | An entry in `offer_links` is missing the required `key` field.                                     |
| 400         | `missing_offer_link_offer_id`          | An entry in `offer_links` is missing the required `offer_id` field.                                |
| 400         | `invalid_offer_link_offer_id`          | An `offer_id` in `offer_links` is not a valid 24-character hexadecimal ObjectId.                   |
| 401         | `invalid_credentials`                  | API key is missing or invalid.                                                                     |
| 403         | `account_suspended`                    | Your account is suspended. Resolve outstanding billing or contact support.                         |
| 429         | `rate_limited`                         | Request throttled; retry with exponential backoff after the window resets.                         |
| 404         | `not_found`                            | No creative exists with the given ID.                                                              |
| 400         | `offer_not_found`                      | An offer referenced in `offer_links` does not exist or does not belong to your account.            |

## Next Steps

<CardGroup cols={2}>
  <Card title="Creative Templates" icon="paintbrush" href="/guides/creatives/templates">
    Template best practices
  </Card>

  <Card title="Create Schedule" icon="calendar" href="/api-reference/v2/schedules/create-schedule">
    Use creatives in campaigns
  </Card>
</CardGroup>
