> For the complete documentation index, see [llms.txt](https://developers-apps-in-toss.toss.im/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers-apps-in-toss.toss.im/documentation/api-and-sdk-en/common/growth/smart-message.md).

# Smart Sending

Like payment complete, delivery notification, etc. **Functional messages required to use the service**is used when sending directly from the partner company's server. You can effectively achieve goals such as improving retention and increasing service usage.

Console [Smart Delivery Setup Guide](https://developers-apps-in-toss.toss.im/guide/marketing/smart-message)Please refer to it.

***

### Preliminary preparations

#### Console setup is required

Before calling the API, you need to complete the steps below first.

1. Create a functional campaign in the Console and issue a template code (`templateSetCode`).
2. If the message requires a notification agreement, create the notification agreement first before creating the campaign, and link it to the functional campaign.
3. You must receive copy review approval. Before approval, even test messages cannot be sent.

For setup instructions, please refer to the Smart Delivery introduction document.

<details>

<summary>Check whether a notification agreement is required</summary>

Before sending a message **Whether a notification agreement is required**depends on the nature of the message.

**Cases where you can send immediately without an agreement**

Information essential for service use can be sent without user consent.

* Payment complete, delivery started, delivery complete, refund complete
* Information change notice, terms and conditions change notice

**Cases where an agreement is required**

When the user chooses to receive a specific notification, you must [Request a notification agreement](#_4-알림-동의문-요청하기-requestnotificationagreement)to obtain consent first.

* Request restock notification
* Request event start notification
* Request price change notification
* Request reservation opening notification

</details>

#### Identify the user to send to

The Smart Delivery API identifies recipients using one of the two methods below. Do not pass both values at the same time; choose only one.

| Category  | Issuance method                                                                                                                               |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `userKey` | [Toss Login](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login)is used to receive it.                    |
| `anonKey` | [Issue a user identification key](https://developers-apps-in-toss.toss.im/documentation/common/authentication/hash-key)is used to receive it. |

Please choose according to your purpose.

* If you have already integrated Toss Login, or want to manage it together with member information such as name and email, `userKey`use it.
* If you want to identify only the user lightly without login integration, `anonKey`use it.

The delivery location differs by API.

* Test message, message: in the request header, `x-toss-user-key` or `x-anon-key`pass it.
* Bulk message: in the request body `contextList` item `userKey` or `anonKey`pass it.

`x-anon-key`If you want to check in advance whether the (hash) is a valid value, [Use the key verification API](https://developers-apps-in-toss.toss.im/documentation/common/authentication/hash-key#식별키-검증하기) please.

***

### Basic information

| Item                  | Value                              |
| --------------------- | ---------------------------------- |
| Base URL              | `https://apps-in-toss-api.toss.im` |
| Server authentication | mTLS (client certificate)          |
| Content-Type          | `application/json`                 |

{% hint style="info" %}
**mTLS certificates are required for server-to-server communication**

The Smart Delivery API is server-to-server communication where the partner server calls the Apps in Toss server. For security, set up an mTLS certificate on the server before calling it. For how to issue a certificate, [How to issue an mTLS certificate](https://developers-apps-in-toss.toss.im/documentation/integration/getting-started)please refer to it.
{% endhint %}

***

### 1. Send a test message

Create a functional campaign in the Console and receive copy review approval, then use this to check whether the bundle works properly before actual deployment.

* Content-Type: `application/json`
* Method: `POST`
* URL: `/api-partner/v1/apps-in-toss/messenger/send-test-message`

**Request headers**

Use one of the two headers below to identify the recipient. Do not send both headers at the same time.

| Name              | Type   | Required | Description                                                                                                                                                                                                                                                                               |
| ----------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `x-toss-user-key` | string | Choose 1 | [Toss Login](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login)received with `userKey`value. [Receive user information](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login#_4-사용자-정보-받기)can be obtained through. |
| `x-anon-key`      | string | Choose 1 | [Issue a user identification key](https://developers-apps-in-toss.toss.im/documentation/common/authentication/hash-key)received with `hash` value.                                                                                                                                        |

**Request body**

| Name            | Type   | Required | Description                                                                                                                        |
| --------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| templateSetCode | string | Y        | Template code for the message to use. Enter the template code registered in the Console.                                           |
| deploymentId    | string | Y        | Identifier of the bundle to use for testing. It is in UUID format and can be seen in the bundle uploaded in Console → App Release. |
| context         | object | Y        | These are template variable values. Enter the values that go into the template, such as user name and verification code.           |

```json
{
  "templateSetCode": "ALERT_OTP_TEMPLATE",
  "deploymentId": "019abfe8-fd68-7021-9cdc-30d6053cc009",
  "context": {
    "userName": "Hong Gil-dong",
    "otp": "123456"
  }
}
```

**Success response**

| Name                | Type    | Description                                                       |
| ------------------- | ------- | ----------------------------------------------------------------- |
| msgCount            | integer | Total number of messages sent.                                    |
| sentPushCount       | integer | Number of messages sent via Push.                                 |
| sentInboxCount      | integer | Number of messages sent via Inbox.                                |
| sentSmsCount        | integer | Number of messages sent via SMS.                                  |
| sentAlimtalkCount   | integer | Number of messages sent via Alimtalk.                             |
| sentFriendtalkCount | integer | Number of messages sent via Friend Talk.                          |
| detail              | object  | Detailed list by channel of messages that were sent successfully. |
| fail                | object  | Detailed list by channel of messages that failed to send.         |

`detail` / `fail` Common subfields:

| Name           | Type  | Description                                       |
| -------------- | ----- | ------------------------------------------------- |
| sentPush       | array | List of send results for the Push channel.        |
| sentInbox      | array | List of send results for the Inbox channel.       |
| sentSms        | array | List of send results for the SMS channel.         |
| sentAlimtalk   | array | List of send results for the Alimtalk channel.    |
| sentFriendtalk | array | List of send results for the Friend Talk channel. |

Item fields in each channel array:

| Name              | Type   | Description                                                    |
| ----------------- | ------ | -------------------------------------------------------------- |
| contentId         | string | Unique ID of the sent message.                                 |
| reachedFailReason | string | If message delivery fails, the reason for failure is included. |

```json
{
  "resultType": "SUCCESS",
  "success": {
    "msgCount": 1,
    "sentPushCount": 1,
    "sentInboxCount": 0,
    "sentSmsCount": 0,
    "sentAlimtalkCount": 0,
    "sentFriendtalkCount": 0,
    "detail": {
      "sentPush": [{ "contentId": "MSG_ABC123" }],
      "sentInbox": [],
      "sentSms": [],
      "sentAlimtalk": [],
      "sentFriendtalk": []
    },
    "fail": {
      "sentPush": [],
      "sentInbox": [],
      "sentSms": [],
      "sentAlimtalk": [],
      "sentFriendtalk": []
    }
  }
}
```

**Failure response**

```json
{
  "resultType": "FAIL",
  "error": {
    "errorCode": "INVALID_PARAMETER",
    "reason": "The request failed."
  }
}
```

| HTTP status code | Description                                                |
| ---------------- | ---------------------------------------------------------- |
| 400              | The request is invalid or required information is missing. |
| 401              | You are an unauthenticated user.                           |
| 403              | You do not have permission to send messages.               |

***

### 2. Send a message

Send a functional message to a specific user. After copy review approval, the partner server can call it directly at the desired time.

* Content-Type: `application/json`
* Method: `POST`
* URL: `/api-partner/v1/apps-in-toss/messenger/send-message`

{% hint style="info" %}
**Call limit**

You can call it up to 10 times per minute per user identification key. If exceeded, an error is returned.
{% endhint %}

**Request headers**

Use one of the two headers below to identify the recipient. Do not send both headers at the same time.

| Name              | Type   | Required | Description                                                                                                                                                                                                                                                                               |
| ----------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `x-toss-user-key` | string | Choose 1 | [Toss Login](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login)received with `userKey`value. [Receive user information](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login#_4-사용자-정보-받기)can be obtained through. |
| `x-anon-key`      | string | Choose 1 | [Issue a user identification key](https://developers-apps-in-toss.toss.im/documentation/common/authentication/hash-key)received with `hash` value.                                                                                                                                        |

**Request body**

| Name            | Type   | Required | Description                                                                                                              |
| --------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------ |
| templateSetCode | string | Y        | Template code for the message to use. Enter the template code registered in the Console.                                 |
| context         | object | Y        | These are template variable values. Enter the values that go into the template, such as user name and verification code. |

```json
{
  "templateSetCode": "ALERT_OTP_TEMPLATE",
  "context": {
    "userName": "Hong Gil-dong",
    "otp": "123456"
  }
}
```

```bash
curl --location 'https://apps-in-toss-api.toss.im/api-partner/v1/apps-in-toss/messenger/send-message' \
--header 'Content-Type: application/json' \
--header 'x-toss-user-key: {{userKey}}' \
--data '{
  "templateSetCode": "ALERT_OTP_TEMPLATE",
  "context": {
    "userName": "Hong Gil-dong",
    "otp": "123456"
  }
}'
```

`anonKey`When sending to `x-anon-key` use the header.

```bash
curl --location 'https://apps-in-toss-api.toss.im/api-partner/v1/apps-in-toss/messenger/send-message' \
--header 'Content-Type: application/json' \
--header 'x-anon-key: {{anonKey}}' \
--data '{
  "templateSetCode": "ALERT_OTP_TEMPLATE",
  "context": {
    "userName": "Hong Gil-dong",
    "otp": "123456"
  }
}'
```

**Success response**

The response structure is [Send test message](#_1-테스트-메시지-발송하기)the same as.

```json
{
  "resultType": "SUCCESS",
  "success": {
    "msgCount": 1,
    "sentPushCount": 1,
    "sentInboxCount": 0,
    "sentSmsCount": 0,
    "sentAlimtalkCount": 0,
    "sentFriendtalkCount": 0,
    "detail": {
      "sentPush": [{ "contentId": "MSG_ABC123" }],
      "sentInbox": [],
      "sentSms": [],
      "sentAlimtalk": [],
      "sentFriendtalk": []
    },
    "fail": {
      "sentPush": [],
      "sentInbox": [],
      "sentSms": [],
      "sentAlimtalk": [],
      "sentFriendtalk": []
    }
  }
}
```

**Failure response**

```json
{
  "resultType": "FAIL",
  "error": {
    "errorCode": "INVALID_PARAMETER",
    "reason": "The request failed."
  }
}
```

| HTTP status code | Description                                                |
| ---------------- | ---------------------------------------------------------- |
| 400              | The request is invalid or required information is missing. |
| 401              | You are an unauthenticated user.                           |
| 403              | You do not have permission to send messages.               |

***

### 3. Send bulk messages

Send the same functional message template to multiple users at once. Used for sending 50 or more messages, and up to 2,500 messages can be sent per request.

* Content-Type: `application/json`
* Method: `POST`
* URL: `/api-partner/v1/apps-in-toss/messenger/send-bulk-message`

**Request body**

| Name            | Type   | Required | Description                                                                                |
| --------------- | ------ | -------- | ------------------------------------------------------------------------------------------ |
| templateSetCode | string | Y        | Template code for the message to use. Enter the template code registered in the Console.   |
| contextList     | array  | Y        | This is the list of users who will receive the message. Minimum 1 and maximum 2,500 items. |

`contextList` Item fields:

| Name    | Type             | Required      | Description                                                                                                                                                                                                                                                                                                                         |
| ------- | ---------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| userKey | string \| number | Conditional Y | [Toss Login](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login)received with `userKey`value. [Receive user information](https://developers-apps-in-toss.toss.im/documentation/common/authentication/toss-login#_4-사용자-정보-받기)can be obtained through. `x-anon-key`cannot be used together with. |
| anonKey | string           | Conditional Y | Received through user identification key issuance `hash` value. `userKey`cannot be used together with.                                                                                                                                                                                                                              |
| context | object           | Y             | These are template variable values. Enter the values that go into the template, such as user name and verification code.                                                                                                                                                                                                            |

Each `contextList` item `userKey`and `anonKey` you must pass one of them.

```json
{
  "templateSetCode": "ALERT_OTP_TEMPLATE",
  "contextList": [
    {
      "userKey": {{userKey1}},
      "context": {
        "userName": "Hong Gil-dong",
        "otp": "123456"
      }
    },
    {
      "userKey": {{userKey2}},
      "context": {
        "userName": "Kim Cheol-soo",
        "otp": "654321"
      }
    }
  ]
}
```

`anonKey`When sending to `anonKey`put

```json
{
  "templateSetCode": "ALERT_OTP_TEMPLATE",
  "contextList": [
    {
      "anonKey": "{{anonKey1}}",
      "context": {
        "userName": "Hong Gil-dong",
        "otp": "123456"
      }
    },
    {
      "anonKey": "{{anonKey2}}",
      "context": {
        "userName": "Kim Cheol-soo",
        "otp": "654321"
      }
    }
  ]
}
```

```bash
curl --location 'https://apps-in-toss-api.toss.im/api-partner/v1/apps-in-toss/messenger/send-bulk-message' \
--header 'Content-Type: application/json' \
--data '{
  "templateSetCode": "ALERT_OTP_TEMPLATE",
  "contextList": [
    {
      "userKey": 12345678,
      "context": { "userName": "Hong Gil-dong", "otp": "123456" }
    },
    {
      "userKey": 87654321,
      "context": { "userName": "Kim Cheol-soo", "otp": "654321" }
    }
  ]
}'
```

**Success response**

The response structure is [Send test message](#_1-테스트-메시지-발송하기)the same as.

```json
{
  "resultType": "SUCCESS",
  "success": {
    "msgCount": 2,
    "sentPushCount": 2,
    "sentInboxCount": 0,
    "sentSmsCount": 0,
    "sentAlimtalkCount": 0,
    "sentFriendtalkCount": 0,
    "detail": {
      "sentPush": [{ "contentId": "MSG_ABC123" }, { "contentId": "MSG_DEF456" }],
      "sentInbox": [],
      "sentSms": [],
      "sentAlimtalk": [],
      "sentFriendtalk": []
    },
    "fail": {
      "sentPush": [],
      "sentInbox": [],
      "sentSms": [],
      "sentAlimtalk": [],
      "sentFriendtalk": []
    }
  }
}
```

***

### 4. Request notification agreement (`requestNotificationAgreement`)

`requestNotificationAgreement`is Smart Delivery's **functional message**function that requests the user's consent UI for receiving notifications before sending.

When the user chooses to receive a specific notification, consent must be obtained first. The consent result is `onEvent` passed as a callback, and you can decide whether to send the notification based on the result.

{% hint style="info" %}
**Notification agreement registration is required**

Before development, you need to complete the following steps first.

1. Create a notification agreement.
2. Create a functional campaign and link the registered notification agreement.
3. Once copy review approval is received, you can use the template code of the registered functional campaign.
4. Use this template code `templateCode`pass it.

For setup instructions, please refer to the Smart Delivery introduction document.
{% endhint %}

**Signature**

```typescript
function requestNotificationAgreement(params: RequestNotificationAgreementOptions): () => void;
```

**Parameters**

* params required

  These are the parameters used for the notification agreement request. See the detailed type below `RequestNotificationAgreementOptions`for details.

**Return value**

* () => void

  Returns the App Bridge cleanup function. After receiving the consent result, you must call this function to release resources.

**Example**

{% tabs %}
{% tab title="React" %}

```tsx
import { requestNotificationAgreement } from '@apps-in-toss/web-framework';

function NotificationAgreementButton() {
  const handleRequestAgreement = () => {
    const cleanup = requestNotificationAgreement({
      options: {
        templateCode: 'your-template-code',
      },
      onEvent: ({ type }) => {
        if (type === 'newAgreement') {
          console.log('You have agreed to receive notifications.');
        } else if (type === 'alreadyAgreed') {
          console.log('Already in an agreed state.');
        } else if (type === 'agreementRejected') {
          console.log('You declined to receive notifications.');
        }
        cleanup();
      },
      onError: (error) => {
        console.error('Failed to request notification agreement:', error);
        cleanup();
      },
    });
  };

  return <button onClick={handleRequestAgreement}>Get notifications</button>;
}
```

{% endtab %}

{% tab title="React Native" %}

```tsx
import { Button } from 'react-native';
import { requestNotificationAgreement } from '@apps-in-toss/framework';

function NotificationAgreementButton() {
  const handleRequestAgreement = () => {
    const cleanup = requestNotificationAgreement({
      options: {
        templateCode: 'your-template-code',
      },
      onEvent: ({ type }) => {
        if (type === 'newAgreement') {
          console.log('You have agreed to receive notifications.');
        } else if (type === 'alreadyAgreed') {
          console.log('Already in an agreed state.');
        } else if (type === 'agreementRejected') {
          console.log('You declined to receive notifications.');
        }
        cleanup();
      },
      onError: (error) => {
        console.error('Failed to request notification agreement:', error);
        cleanup();
      },
    });
  };

  return <Button title="Get notifications" onPress={handleRequestAgreement} />;
}
```

{% endtab %}
{% endtabs %}

**`RequestNotificationAgreementOptions`**

`requestNotificationAgreement` This is the parameter type passed to the function.

```typescript
interface RequestNotificationAgreementOptions {
  options: {
    templateCode: string;
  };
  onEvent: (result: { type: NotificationAgreementResult }) => void;
  onError: (error: unknown) => void | Promise<void>;
}
```

* options required

  This is the options object used for the notification agreement request.

  * options.templateCode required

    This is the template code of the functional campaign linked to the notification agreement. Enter the template code registered in the Console.
* onEvent required

  This is the callback executed when the consent result is finalized. `NotificationAgreementResult` type `type` value is passed.
* onError required

  This is the callback executed when an unexpected error occurs. The error object has the type `unknown`.

**`NotificationAgreementResult`**

`onEvent` This is the consent result type passed as a callback.

```typescript
type NotificationAgreementResult = 'newAgreement' | 'alreadyAgreed' | 'agreementRejected';
```

| Value               | Description                                                                         |
| ------------------- | ----------------------------------------------------------------------------------- |
| `newAgreement`      | When the user newly completes consent.                                              |
| `alreadyAgreed`     | When the result is returned with consent already given, without additional consent. |
| `agreementRejected` | When the user declines consent.                                                     |

**Error code**

The error code is `onError`received via or caught in the `try/catch`of the error caught in `error.code` value.

| Value                           | Description                                                                                                                                                                                                                                               |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `UNSUPPORTED_APP_VERSION`       | If the currently running Toss app version does not support this feature, it occurs immediately upon invocation. `Notification.requestAgreement.isSupported()`Check in advance with, and when it occurs `error.message`(update guidance text) to the user. |
| `NOTIFICATION_AGREEMENT_FAILED` | <p>Occurs when the functional push template code is incorrect.<br>The template code must start with <code>{appName}-</code> .</p>                                                                                                                         |
| `TERMS_DISAGREED_MEMBER`        | <p>This is the case when the user has refused consent.<br>Go to Settings > Terms and Privacy Policy Consent > User-optimized Product Consent Settings.</p>                                                                                                |

**Notes**

* `onEvent` or `onError` Be sure to call the cleanup function returned by the callback.
* Before re-calling the function in the same component, run the previous cleanup first. Otherwise, the previous event listener may remain duplicated.
* For how to register a notification consent statement and the flow for sending functional messages, please refer to the Smart Send introduction document.
* To send messages after user consent, on the partner company's server [Send Message](#_2-메시지-발송하기)please call it.
* Users can directly control whether to receive notifications in the Toss app → All tab → Settings button → Notifications → Service notifications.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers-apps-in-toss.toss.im/documentation/api-and-sdk-en/common/growth/smart-message.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
