> This page is part of the [Customer.io documentation](https://docs.customer.io). For the complete index, see [llms.txt](https://docs.customer.io/llms.txt).

# Set up a transactional SMS or WhatsApp message

Transactional SMS or WhatsApp messages are text messages that your audience implicitly opts-into, like order confirmations, password reset codes, or account verification messages. You can send transactional SMS messages programmatically through Customer.io.

New to transactional messaging?

Check out our [getting started](/messaging/send/transactional/api/) section to learn more about transactional concepts and how our transactional API works.

## Before you begin

Before you can send transactional SMS messages, you need to:

*   [Connect an SMS provider](/messaging/channels/sms/get-started/#connect-your-provider) and enable SMS in your workspace.
*   Get your [app API key](https://fly.customer.io/settings/api_credentials?keyType=app). This is the bearer token that you’ll use when you call the transactional API to trigger a message.

**We also recommend that you use different phone numbers for transactional and marketing SMS messages**. This helps maintain deliverability and ensures your critical transactional messages aren’t affected by marketing message reputation.

## Create a transactional SMS

Unlike transactional emails and push notifications, you cannot send a transactional SMS or WhatsApp message without a template. You *must* use a `transactional_message_id` when you send an SMS and you cannot override the body or image URL of your message at send time. This is true no matter which [SMS provider](/messaging/channels/sms/get-started/) delivers your messages.

How you write the message depends on your provider. With Twilio, you draft the message in the transactional composer, following the steps below. With other providers, you choose the SMS channel and link a message you’ve built in [Design Studio](/messaging/design-studio/)—the trigger, settings, and API call work the same way.

1.  Go to the **Transactional** page and click **Send your first message** or **Create message**—depending on whether there are already transactional messages in your workspace.

2.  Give your message a **Name** and a **Description** and then click **Next: Add Content**. The name and description help your team members understand what kind of message this is (like “Two-Factor Authentication” or “Password Reset Code”).

     ![The transactional message's first screen, with fields for name, description, and tags](https://docs.customer.io/images/transactional-sms-name.png)

3.  Select **SMS** and click **Add Content**.

4.  Draft your message. If you see an error in the upper-right when you try to write your message, it’s likely that you need to select a profile in your *Sample data* who has a `phone` [attribute](/journeys/people/manage/attributes/).

    Selecting a representative sample profile also helps you personalize your message. You can personalize messages using attributes (`{{customer.<attribute>}}`) or data from your transactional message’s `message_data` key ( in the format `{{trigger.<data-object-property>}}`).

     ![Transactional message content screen, with a sample profile selected, a text box for the message, and a preview of the message](https://docs.customer.io/images/transactional-sms-content.png)

5.  When you’re done writing your message, click **Save Changes** and then click **Next: Configure Settings**.

6.  Configure your message settings. In general, we recommend that you use our defaults and that you **Set a trigger name** so that it’s easier to send your message later.

    *   **Send to unsubscribed profiles?** Unsubscribed profiles probably still want to receive your important transactional messages like order confirmations and password resets.

    *   **Enable link tracking?** By default, we’ll track clicks on links in your transactional SMS messages. Disable this setting if you don’t use our [link shortening feature](/messaging/channels/sms/link-shortening/) or tracked links (which are longer than normal links) will likely exceed the 160 character limit for SMS messages.

    *   **Protect sensitive data by disabling message retention?** This setting prevents Customer.io from retaining your message content. You might want to do this to conceal sensitive messages, like password reset codes or verification tokens.

    *   **Queue messages as drafts?** This setting generates a draft for every message you trigger rather than sending them automatically. You can review these messages under the *Drafts* tab and decide whether to send or delete them.

    *   **Set a Trigger Name**: This is a friendly name for your message that you can use instead of the `transactional_message_id` when you send your message. It may help make your integration more human-readable if you use triggers that represent the kinds of messages you send—like `password_reset` or `order_confirmation`.

     ![SMS settings, with toggles for basic settings and a text box for the trigger name](https://docs.customer.io/images/transactional-sms-settings.png)

7.  Now you’re ready to send your message. You can adapt the code sample on the **Send Message** screen to your code—wherever you intend to trigger transactional messages—or use our API directly.

(Optional) Even if you don’t want to wire up your integration completely, we recommend that you call our API and send a test message to make sure that your message works the way you expect. You can even use an HTTP client like [Postman ↗](https://getpostman.com) or send a cURL request from your terminal to test your message and complete the setup process.

Try our Postman collection!

You can use our [Postman ↗](https://www.getpostman.com) collection and associated environment to get started with the Customer.io API. Our environment is based on our US endpoints; if you’re in our EU region, you’ll need to add `-eu` to `track_api_url` and `app_api_url` variables.

## Send a transactional SMS message

You’ll send your message using [our API](/integrations/api/app/#operation/sendSMS). To send a transactional SMS message, you need:

*   `transactional_message_id`: the numeric ID or trigger name for the SMS [message you created](#create-a-transactional-sms-message).
*   `identifiers`: an object containing a unique identifier for the recipient. This tells us who to send the message to.
*   `message_data` (optional): values you want to populate in the message using [liquid](/journeys/liquid/using-liquid) using `{{trigger.<property_name>}}`.

```
curl -X POST https://api.customer.io/v1/send/sms \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer APP-API-TOKEN' \
-d '
{
  "transactional_message_id": "confirmation_code",
  "identifiers": {
    "id": "123456"
  },
  "message_data": {
    "confirmation_code": "123456"
  }
}
'
```

## Identify your recipient

When you send a transactional message, you need to give us a phone number to send the message to *and* the identifiers of the profile you want to attribute the message to. This is because phone numbers aren’t unique identifiers for profiles in Customer.io.

You can set your audience’s phone number (typically using [liquid](/journeys/liquid/using-liquid)) when you [set up your message](#create-a-transactional-sms-message). You can override or set this value when you send your message using the `to` parameter. This parameter can be either a phone number in E.164 format (e.g. `+15551234567`) or a customer [attribute](/journeys/people/manage/attributes/) in [liquid](/journeys/liquid/using-liquid) syntax, like `{{customer.phone}}`.

You’ll also include an `identifiers` object in your request to specify the person you want to attribute the message to. The `identifiers` object accepts one of `id`, `email`, or `cio_id`.

```
{
  "transactional_message_id": "confirmation_code",
  "to": "+15551234567",
  "identifiers": {
    "id": "123456"
  },
  "message_data": {
    "confirmation_code": "123456"
  }
}
```

## Examples and API parameters

Below is a basic transactional SMS payload, followed by the full list of parameters. Your payload changes based on whether you reference a `transactional_message_id` (a template) or not. See our [REST API](/integrations/api/app/#operation/sendSMS) documentation for the full reference, including code samples in cURL and several languages.

```
{
  "transactional_message_id": "confirmation_code",
  "identifiers": {
    "id": "123456"
  },
  "message_data": {
    "confirmation_code": "123456",
    "account_name": "Jane Doe"
  }
}
```

*   transactional\_message\_idone ofrequired

    The transactional message template that you want to use for your message. You can call the template by its numerical ID or by the *Trigger Name* that you assigned to the template in the UI (case insensitive).

    One of:ID (integer)Trigger Name (string)

    The ID of the transactional message you want to send.

    integer

*   tostringrequired

    The phone number you want to send your SMS to. Use E.164 format, like `+15551234567`, or Liquid if you store phone numbers as attributes.

*   fromstring

    The phone number or sender ID your SMS is from. It must be verified in your Twilio account. This overrides the template's sender. Use E.164 format for a phone number.

*   trackedboolean

    Default: `true`

    Whether to track link clicks for this SMS. Defaults to the transactional message's own tracking setting.

*   languagestring

    Overrides language preferences for the person you want to send your transactional message to. Use one of our [supported two- or four-letter language codes](/journeys/channels/localization/getting-started/#supported-languages).

*   identifiersone ofrequired

    Identifies the person represented by your transactional message by one of, and only one of, `id`, `email`, or `cio_id`.

    One of:idemailcio\_id

    *   idstringrequired

        The identifier for the person represented by the transactional message. **NOTE**: If your workspace identifies people by email, use the `email` identifier instead.

*   message\_dataobject

    An object containing the key-value pairs referenced using liquid in your message.

    *   Liquid Data \*any type

        Insert key-values that you want to reference in your message here.

*   send\_atinteger

    A unix timestamp (seconds since epoch) determining when the message will be sent. The timestamp can be up to 90 days in the future. If this value is in the past, your message is sent immediately.

*   disable\_message\_retentionboolean

    Default: `false`

    If true, the message body is not retained in delivery history. Setting this value overrides the value set in the settings of your `transactional_message_id`.

*   send\_to\_unsubscribedboolean

    Default: `true`

    If false, your message is not sent to unsubscribed recipients. Setting this value overrides the value set in the settings of your `transactional_message_id`.

*   queue\_draftboolean

    Default: `false`

    If true, your transactional message is held as a draft in Customer.io and not sent directly to your audience. You must go to the Deliveries and Drafts page to send your message.

*   auto\_createboolean

    Default: `false`

    If `true` and your `transactional_message_id` doesn't match a record, Customer.io creates an empty record using that value as the *Trigger Name*. The ID must be a string. If the name already belongs to another channel, the request fails with `400`, and numeric IDs ignore this setting. See [details](/journeys/transactional-email/#auto-create-transactional-message-records).

©2026 Peaberry Software, Inc. [Status](https://status.customerio.com/) [Terms of Service](https://customer.io/legal/terms-of-service/) [Privacy Policy](https://customer.io/legal/privacy-policy/)

[](https://www.linkedin.com/company/customer-io)[](https://twitter.com/customerio)[](https://www.youtube.com/channel/UCkCaWdezRoa8ZyR9pEVaipA)[](https://www.instagram.com/customer.io/)
