Apple Messages for Business

Apple Messages for Business is a channel built to reach customers through Messages on any Apple device. The channel prides itself on its rich set of messaging features including bot and AI capabilities, security, and ability to connect to the wide world of iOS apps and add-ons.

Channel overview

Apple Messages for Business is used for customer service interactions, scheduling tasks, and even payments. This means that customers interact with brands as easily as they message their friends and family. It’s discoverable from Apple Maps, Safari, and Search— or directly embedded into a brand’s website.

Accounts

Apple Business Register

Apple Messages for Business requires all businesses to register with Apple before rolling out Messages for Business. A business will need to submit brand information, including addresses and logos, for Apple’s approval. As part of this process, you’ll be prompted to select a Messaging Service Provider. Here is where Zendesk’s Sunshine Conversations comes into play— as a Messaging Service Provider, we are certified by Apple to provide services and solutions for your Messages for Business needs. At the end of the registration process, you’ll receive a unique Messages for Business ID that will be used to connect to Sunshine Conversations.

See Register Your Account for more information.

Apple Business Register

Setting up a Messages for Business Account

To set up your Messages for Business Account in the Apple Business Register:

  1. Sign into the Business Register and add a Messages for Business Account.

    • Go to register.apple.com.

      • Select sign in with your Apple ID.
      • Log in with your Apple ID. If you don’t have one, you’ll need to create one.
      • Accept the Terms & Conditions to continue.
    • You’ll be directed to a Apple Business Register page.
    • Click Manage connections.
    • Click Add next to Messages for Business Accounts and then click Done at the bottom of the page. Apple Messages for Business Account
  2. In the Apple Business Register page, click Messages for Business Accounts. Apple Messages for Business Manage
  3. Click the checkbox to agree to the Terms of Use and click Agree.
  4. Click Add New and then click Get Started. Apple Get Started
  5. Review the Messages for Business policies and click Next.

    • You’ll need to provide:

      • Messages for Business Account applicant details.
      • Account type (e.g. “Commercial”).
      • Technical contact.
  6. Fill in your Brand Identity details. - These are your square and wide logos, plus branding colors.
  7. Complete your Brand Information Card. - These details include your brand name, website, phone number, message response time, live agent response hours. This will be shown to customers in Messages.
  8. Select Zendesk- Sunshine Conversations as your Messaging Service Provider. - Start typing Zendesk and use the auto-complete to find us.

Finally, click Send for review to submit your application to Apple. You’ll be able to see the status of your application at the top of your Messages for Business Account page.

Messages for Business ID

After you’ve been approved by Apple for Messages for Business, you’ll be issued an ID.

You can find the ID by going to your Messages for Business Account page and scrolling down to the Messaging Service Provider section.

From there, click on Test your Messaging Service Provider connection.

After that, you’ll be directed to a page where you can copy your Messages for Business ID.

Capabilities

Apple supports a wide variety of capabilities as seen in the channel capabilities grid. Below is a detailed view of each capability.

Content Types

  • Text

    Full SupportAPI
  • Image

    Full SupportAPI
  • File

    Full SupportAPI
  • Emoji

    Full SupportAPI
  • GIF

    Full SupportAPI
  • Location

    Full SupportAPI

Action Types

  • Link

    Full SupportAPI
  • Postback

    Partial SupportAPI
  • Reply

    Full SupportAPI
  • Location Request

    Partial SupportAPI

Structured Messages

  • Compound Message

    Full SupportAPI
  • Carousel

    Partial SupportAPI

Indicators

  • Typing

    Partial SupportAPI

Delivery Events

Delivery events allow you to track deliveries of Sunshine Conversations messages to Apple Messages for Business by subscribing to the conversation:message:delivery:channel webhook. Failures to deliver a message to Apple Messages for Business can be detected by subscribing to the conversation:message:delivery:failure webhook.

Embed the Apple Messages for Business Button

Apple’s documentation can be found here.

You will need to do the following:

  1. Add Apple’s Messages for Business JS (javascript) library to your webpage headers.
  2. Add a <div> container to house the button.
  3. Customize the banner, fallback support, and button colour to meet your brand’s needs.

The Messages for Business button must contain the following, at minimum:

  • A class attribute to specify the type of container: banner, phone, or message. For more information, see Messages for Business Button Class and Data Attributes.
  • A data-apple-business-id attribute with the business ID you received when you registered your company with Messages for Business.

How to enable the channel

Using the Dashboard

If you don’t have a Sunshine Conversations account yet, contact us from the Test your Messaging Service Provider connection in the Business Register to continue the integration process. From that page, you can click on the Connect button to send you to the Sunshine Conversations site.

  1. Log into the Apple Business Register.

  2. In a separate tab, log into your Sunshine Conversations Dashboard.

  3. Copy your Messages for Business ID from the Test your Messaging Service Provider connection page in Apple Business Register.

  4. In the Sunshine Conversations Dashboard, select Apple Messages for Business from the list of channel integrations.

  5. Next, complete the following steps to connect your Apple Messages for Business integration.

    • Choose a name for this integration so you can find it easily within your Sunshine Conversations app
    • Paste your Messages for Business ID
    • Click Connect

Security and Messages for Business IDs

Since Messages for Business IDs are public, Sunshine Conversations has implemented a security measure to ensure your brand’s Messages for Business ID stays linked to your Sunshine Conversations app. This means that a Messages for Business ID cannot be migrated from one app to another through the dashboard or API. If you need to remove your Apple Messages for Business integration and migrate it to another app, please contact our team for assistance using the help widget in your dashboard. Our team will release the Messages for Business ID on your behalf.

Using the integration API as an MSP

There are 3 different IDs required in the payload:

  • MSP ID, a unique identifier for an Apple Messages for Business partner registered as a Messaging Service Provider through Apple Business Register
  • API secret, a key tied to the MSP
  • Messages for Business ID, tied to the brand using Apple Messages for Business

Tracking customer intent

Apple makes it possible to publish a URL for users to tap that will bring them into iMessage to chat with the business.

In order to provide some context to the business about which link was clicked by the user, the biz-intent-id and biz-group-id parameters can be included as querystring parameters on the URL:

https://bcrw.apple.com/urn:biz:{businessId}?biz-intent-id=TestingBizIntent&biz-group-id=TestingBizGroup

Group and intent are both optional. If both are left unspecified, the client.raw object will be absent and the message.source.group and message.source.intent fields will be absent.

Whenever Sunshine Conversations receives a group or intent attached to an Apple Messages for Business message, these values will be exposed in both the Sunshine Conversations message and client objects. For example, after a user clicks on such a link, the first message received by that user will trigger a message:appUser webhook like this:

{
    "trigger": "message:appUser",
    "app": { "_id": "599349ff5f753aecf2e151c9" },
    "messages": [
        {
            "authorId": "caf1dbe12cee751407bd53a6",
            "received": 1512587862.523,
            "type": "text",
            "text": "Hi",
            "name": "Glass Chameleon",
            "role": "appUser",
            "_id": "5a284256fbbc83ffb792e31c",
            "source": {
                "type": "apple",
                "group": "TestingBizGroup",
                "intent": "TestingBizIntent"
            }
        }
    ],
    "appUser": {
        "_id": "caf1dbe12cee751407bd53a6",
        "signedUpAt": "2017-12-06T16:59:11.355Z",
        "conversationStarted": true,
        "credentialRequired": true,
        "clients": [
            {
                "raw": {
                    "group": "TestingBizGroup",
                    "intent": "TestingBizIntent"
                },
                "id": "1da8d244-a389-4240-ae6e-4b6975c88236",
                "platform": "apple",
                "linkedAt": "2017-12-06T16:59:11.357Z",
                "lastSeen": "2017-12-06T19:17:42.476Z",
                "active": true,
                "primary": true
            }
        ]
    }
}

Client object

Any group or intent received from Apple will be persisted in the client object. Each subsequent message:appUser webhook payload will include those fields.

Message object

The last known group or intent will also be included under the message.source, and will be replayed in future messages coming from that user so long as neither changes.

Clients and messages can also be retrieved at a later date via the user API and messages API respectively.

Changing group or intent

A user can click a different Messages for Business link with different biz-* query parameters, thus changing the conversation’s group and intent. In this case, client.raw.group and client.raw.intent will be individually updated with any new values. Group and intent values that were received with previous messages will still be preserved in the message history under that message’s source.group and source.intent parameters.

Unsubscribe

If a user unsubscribes, the group and intent stored on the client will be cleared. If they later change their mind and send a new message to the business (without having clicked a Messages for Business link with query parameters) these parameters will be absent from the smooch client.

Passthrough API

The passthrough API is a way to send message types for which there is no corresponding Sunshine Conversations type or to leverage channel-specific features not folded into the Sunshine Conversations API (e.g. Apple list or time pickers.) To accomplish this, the developer provides Sunshine Conversations with the raw payload to send to the messaging provider’s API, and the Sunshine Conversations platform will “pass it through”.

To use the passthrough API, you first craft a valid Sunshine Conversations message of any type, then you specify an additional override parameter for the channels you would like to use passthrough. Under the channel name (in this case abc), the payload field contains the exact structure of a valid Apple Messages for Business Service API call to the Message endpoint.

The passthrough API described below has been introduced so that it’s possible to send any message type to Apple Messages for Business.

While the passthrough API accepts payloads up to 100kb, building Messages for Business messages often result in payloads larger than 100kb. For instance, when sending a list picker with an image associated with each item, those images must be directly included inside the payload (using base64 encoding). To get past this limitation, Sunshine Conversations exposes new large message and large template APIs that handle payloads up to 10mb.

We recommend using templates where possible, to avoid crafting complex messages each time they’re sent and also to avoid network delays when sending large messages.

Using the passthrough API

To use the passthrough API, you first craft a valid message of any type, then you specify an additional override parameter for the channels you would like to use passthrough.

Example:

{
    "role": "appMaker",
    "text": "Hello there",
    "type": "text",
    "override": {
        "apple": {
            "payload": {
                "body": "goodbye",
                "type": "text"
            }
        }
    }
}

The above example depicts a simple override example, where the text message will render as “Hello there” on every channel except Apple, where it would render as “goodbye”. Note that type and body are Apple-specific fields, exactly as the Apple API would accept them.

Messages for Business requires images (aka large interactive data) to be embedded as base64 strings inside message JSON payloads. This tends to make JSON payloads large. However, our standard /messages API only supports payloads up to 100kb. We provide a large message and large template API to support payloads up to 10mb.

Optional Capability Parameter

Certain devices offer unique features or functionalities, such as time pickers or list pickers. You might want to send specific messages only if the user’s device supports certain features.

This is where the withCapabilities optional parameter comes in. It lets you specify which device capabilities are required for the special message.

Here are the values you can use:

  • LIST : for list picker
  • TIME : for time picker
  • FORM : for form Message
  • QUICK : for quick Reply
  • AUTH2 : for authentication
Example of Optional Parameter

Suppose you want to send a time picker message, but want a fallback message for devices that don’t support time pickers. Here’s how you can do it:

{
    "role": "appMaker",
    "text": "time picker fallback",
    "override": {
        "apple": {
            "withCapabilities": ["TIME"],
            "payload": {
                "interactiveData": {
                    "bid": "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.icloud.apps.messages.business.extension",
                    "data": {
                        "event": {
                            "identifier": "reservation-id",
                            "timeslots": [
                                {
                                    "duration": 3600,
                                    "identifier": "7-am",
                                    "startTime": "2018-10-24T07:00+0000"
                                },
                                {
                                    "duration": 3600,
                                    "identifier": "8-am",
                                    "startTime": "2018-10-24T08:00+0000"
                                }
                            ],
                            "timezoneOffset": 400,
                            "title": "Available Reservations"
                        },
                        "mspVersion": "1.0",
                        "requestIdentifier": "appointment-selector-1"
                    },
                    "receivedMessage": {
                        "style": "icon",
                        "title": "Make a reservation"
                    },
                    "replyMessage": {
                        "style": "icon",
                        "title": "Your reservation"
                    }
                },
                "type": "interactive"
            }
        }
    }
}

In this example:

  • If the user’s device supports time pickers, they will receive a specific reservation message with selectable time slots.
  • If it doesn’t, they will see the fallback message: “time picker fallback”.

Reserved fields

In order to ensure the message is correctly delivered, Sunshine Conversations will automatically set some fields in the payload for you. If you supply these fields, they will be ignored and replaced:

Reserved KeyReserved Behaviour
vSpecifies the version of the message schema to use. Sunshine Conversations will automatically set this to 1
idA unique identifier (in UUID format) for the message. Sunshine Conversations will automatically generate and populate this value
sourceIdThe unique identifier of the calling business. Sunshine Conversations will populate this value based on the configured integration
destinationIdThe unique identifier of the user. Sunshine Conversations will populate this value based on the target user

Sending Apple messages

A rich link is automatically built for text messages containing a single URL inside. However, you can manually define rich links using the passthrough API.

Rich links can contain an image or video preview. For the image, you must provide the image in Base64 encoding. You can obtain this through a library or 3rd party website.

Please note that considering the size of the payload with the base64 image, you will need to use the following endpoint to send a message:

POST v1/apps/{appId}/appusers/{appUserId}/messages/large

Example of a rich link with an image preview:

{
    "role": "appMaker",
    "type": "text",
    "text": "Hello there!",
    "override": {
        "apple": {
            "payload": {
                "body": "https://smooch.io/",
                "type": "richLink",
                "richLinkData": {
                    "url": "https://smooch.io/",
                    "title": "Title",
                    "assets": {
                        "image": {
                            "data": "put base64 encoded image here",
                            "mimeType": "image/jpg"
                        }
                    }
                }
            }
        }
    }
}

Example of a Rich link with a video preview:

{
    "role": "appMaker",
    "type": "text",
    "text": "Hello there",
    "override": {
        "apple": {
            "payload": {
                "body": "https://smooch.io/",
                "type": "richLink",
                "richLinkData": {
                    "url": "https://smooch.io/",
                    "title": "Title",
                    "assets": {
                        "video": {
                            "url": "https://images.apple.com/media/us/homepod/2018/98e6cc1a_37ec_4e69_b717_9e58c71e1937/films/expand/homepod-expand-tpl-cc-us-20180306_1280x720h.mp4",
                            "mimeType": "video/mp4"
                        }
                    }
                }
            }
        }
    }
}

Attachments

For some message types, it might be necessary to send attachments. In such cases, you should refer to the Apple documentation for instructions on how to upload those resources to Apple, and pass the object reference to Sunshine Conversations using the passthrough API.

For more information on attachments, see File Validation.

Example:

{
    "role": "appMaker",
    "text": "Hello there",
    "type": "image",
    "mediaType": "image/png",
    "mediaUrl": "https://marketplace-cdn.smooch.io/apple/icon.png",
    "override": {
        "apple": {
            "payload": {
                "attachments": [
                    {
                        "decryption-key": "00260450bb05cd4597a8ae706199f685c0f6fafee4b6c3e1375771c472f4149e29",
                        "file-size": "10159",
                        "mime-type": "image/png",
                        "mmcs-owner": "M39303332653438322d396338342d313165372d613330332d633735336231626666366661.C01USN00",
                        "mmcs-signature-base64": "AXG58GIo7xWZz7gRXZH2liWuzVah",
                        "mmcs-url": "https://p97-content.icloud.com",
                        "name": "icon.png"
                    }
                ],
                "body": "goodbye \ufffc",
                "type": "text"
            }
        }
    }
}

List picker

A sample list picker payload sent through the passthrough API:

{
    "role": "appMaker",
    "text": "Hello there",
    "override": {
        "apple": {
            "payload": {
                "interactiveData": {
                    "bid": "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.icloud.apps.messages.business.extension",
                    "data": {
                        "images": [],
                        "listPicker": {
                            "multipleSelection": true,
                            "sections": [
                                {
                                    "items": [
                                        {
                                            "identifier": "taco-appetizer",
                                            "order": 0,
                                            "style": "default",
                                            "subtitle": "Great tacos",
                                            "title": "Tacos"
                                        },
                                        {
                                            "identifier": "burrito-appetizer",
                                            "order": 1,
                                            "style": "default",
                                            "subtitle": "Good burritos",
                                            "title": "Burritos"
                                        }
                                    ],
                                    "order": 0,
                                    "title": "Appetizers"
                                },
                                {
                                    "items": [
                                        {
                                            "identifier": "taco-meal",
                                            "order": 0,
                                            "style": "default",
                                            "subtitle": "Great tacos",
                                            "title": "Tacos"
                                        },
                                        {
                                            "identifier": "burrito-meal",
                                            "order": 1,
                                            "style": "default",
                                            "subtitle": "Good burritos",
                                            "title": "Burritos"
                                        }
                                    ],
                                    "order": 1,
                                    "title": "Meals"
                                }
                            ]
                        },
                        "mspVersion": "1.0",
                        "requestIdentifier": "food-picker-1"
                    },
                    "receivedMessage": {
                        "style": "small",
                        "subtitle": "Let's eat!",
                        "title": "FoodPicker"
                    },
                    "replyMessage": {
                        "style": "large",
                        "subtitle": "Nutrition",
                        "title": "Selected food"
                    }
                },
                "type": "interactive"
            }
        }
    }
}

Time picker

A sample time picker payload sent through the passthrough API:

{
    "role": "appMaker",
    "text": "Hello there",
    "override": {
        "apple": {
            "payload": {
                "interactiveData": {
                    "bid": "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.icloud.apps.messages.business.extension",
                    "data": {
                        "event": {
                            "identifier": "reservation-id",
                            "timeslots": [
                                {
                                    "duration": 3600,
                                    "identifier": "7-am",
                                    "startTime": "2018-10-24T07:00+0000"
                                },
                                {
                                    "duration": 3600,
                                    "identifier": "8-am",
                                    "startTime": "2018-10-24T08:00+0000"
                                }
                            ],
                            "timezoneOffset": 400,
                            "title": "Available Reservations"
                        },
                        "mspVersion": "1.0",
                        "requestIdentifier": "appointment-selector-1"
                    },
                    "receivedMessage": {
                        "style": "icon",
                        "title": "Make a reservation"
                    },
                    "replyMessage": {
                        "style": "icon",
                        "title": "Your reservation"
                    }
                },
                "type": "interactive"
            }
        }
    }
}

Authentication Message

A sample authentication message payload sent through the passthrough API:

{
    "role": "appMaker",
    "type": "text",
    "text": "Hello there!",
    "override": {
        "apple": {
            "payload": {
                "type": "interactive",
                "v": 1,
                "locale": "en_us",
                "interactiveData": {
                    "bid": "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.icloud.apps.messages.business.extension",
                    "data": {
                        "version": "2.0",
                        "requestIdentifier": "1a50ecd2-a0bb-467c-a77c-1932033e8309",
                        "authenticate": {
                            "oauth2": {
                                "responseType": "code",
                                "scope": ["r_liteprofile"],
                                "redirectURI": "https://example.com/auth/linkedin/callback"
                            }
                        }
                    },
                    "receivedMessage": {
                        "title": "Lets Sign In"
                    },
                    "replyMessage": {
                        "title": "Sign In Completed"
                    }
                }
            }
        }
    }
}
Business flow
  • Businesses must supply authentication details about the OAuth provider, including authentication endpoint URLs, client identifier, and business information to their AMB account.
  • Create an integration with a authenticationMessageSecret value. This value will be used by Sunshine Conversations to sign the state. The state is a value required by Apple to perform the authentication flow. Securely store this value as it cannot be retrieved by the API.
  • In order to perform the authentication flow, the business needs to expose an endpoint that will be the same route as the redirectURI.
  • After the end-user authenticates, the endpoint created by the business will be called and they will be responsible for validating the state value. This can be done by decoding the state value using the authenticationMessageSecret. The state value is a JWT containing the conversationId. Use the conversationId to get their user ID and merge the user using the v1 merge users api. If using Zendesk, this will merge a user with an existing one in your Zendesk Agent Workspace.
  • Redirect the end-user to the following URL scheme after the auth flow is complete in order to close the webview. See Finishing the New Authentication Flow for more details.
// URL Schema
message-auth://?

Examples:
messages-auth://?status=success
messages-auth://?status=failure&error_code=400
  • The authentication webhook event is sent when closing the window with the status as success or failure. Sunshine Conversations will publish the webhook via passthrough:apple:interactive containing the status of the authentication.

Custom extension

A sample custom extension (e.g. iMessage App) payload sent through the passthrough API:

{
    "role": "appMaker",
    "type": "text",
    "text": "Hello there",
    "override": {
        "apple": {
            "payload": {
                "attachments": [
                    {
                        "decryption-key": "00260450bb05cd4597a8ae706199f685c0f6fafee4b6c3e1375771c472f4149e29",
                        "file-size": "10159",
                        "mime-type": "image/png",
                        "mmcs-owner": "M39303332653438322d396338342d313165372d613330332d633735336231626666366661.C01USN00",
                        "mmcs-signature-base64": "AXG58GIo7xWZz7gRXZH2liWuzVah",
                        "mmcs-url": "https://p97-content.icloud.com",
                        "name": "icon.png"
                    }
                ],
                "interactiveData": {
                    "URL": "?options=tacos,burritos",
                    "appId": 34554,
                    "appName": "Your App Name",
                    "bid": "com.apple.messages.MSMessageExtensionBalloonPlugin:ABCD5678:com.yourDomain.MessagesExtension",
                    "receivedMessage": {
                        "imageSubtitle": "Image Subtitle",
                        "imageTitle": "Image Title",
                        "secondarySubtitle": "Trailing Caption",
                        "subtitle": "Subcaption",
                        "tertiarySubtitle": "Trailing Subcaption",
                        "title": "Caption"
                    },
                    "useLiveLayout": false
                },
                "type": "interactive"
            }
        }
    }
}

Apple Pay payment requests

Prerequisites for sending ApplePay payment requests include:

  • Apple Pay Merchant ID including:

    • signed certificate (developer.apple.com)
    • a verified Merchant Domain
  • Apple Pay Merchant ID configured on the Messages for Business account (register.apple.com)
  • Valid MerchantSession object, obtained from Apple’s API

    • More details on MerchantSessions are available here

Sent using passthrough API, according to the Apple specification here

Responses are sent to the function-specific URL(s) specified in the request (in the interactiveData.data.payment.endpoints object)

App Clips

An App Clip is a small, lightweight version of a full application. It allows users to quickly access and use specific functionalities of an app without needing to download and install the entire application.

Prerequisites for sending App Clips include:

  • A valid URL has App Clips elements on its web page. See details here.

Ensure the version property is a string with at least one decimal precision. Otherwise, the Apple Messages for Business API will return an error.

If the App Clip is not available in the US App Store, add an optional storeRegion link property. See the construct payload API for more details.

{
    "role": "appMaker",
    "text": "Hello there",
    "override": {
        "apple": {
            "payload": {
                "type": "link",
                "link": {
                    "url": "https://smooch.io/",
                    "storeRegion": "US" // optional
                },
                "version": "1.0"
            }
        }
    }
}

Receiving Apple messages

Passthrough webhooks

To receive passthrough messages, subscribe to one of the passthrough webhook triggers through the Sunshine Conversations API. Note that these triggers must be explicitly subscribed for via the Sunshine Conversations API; they are not included in the * trigger.

TriggerUsage
passthrough:apple:extensionTriggered when a custom extension message is received
passthrough:apple:interactiveTriggered when a list picker, time picker, or other interactiveDataRef is received

Example payload

The passthrough webhook payload includes the associated app, appUser, source, and raw payload received from Apple.

Here is an example passthrough payload for a list picker selection:

{
    "app": { "_id": "59a8866f19ac1e893d8f39fe" },
    "appUser": { "_id": "12130c355cf163c2dca397a9" },
    "payload": {
        "apple": {
            "destinationId": "9032e482-9c84-11e7-a303-c753b1bff6fa",
            "id": "45e36836-fa85-41a1-8c25-359e6c941d40",
            "interactiveData": {
                "bid": "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.icloud.apps.messages.business.extension",
                "data": {
                    "listPicker": {
                        "multipleSelection": true,
                        "sections": [
                            {
                                "items": [
                                    {
                                        "identifier": "taco-appetizer",
                                        "order": 0,
                                        "style": "default",
                                        "subtitle": "Great tacos",
                                        "title": "Tacos"
                                    },
                                    {
                                        "identifier": "taco-meal",
                                        "order": 0,
                                        "style": "default",
                                        "subtitle": "Great tacos",
                                        "title": "Tacos"
                                    }
                                ],
                                "order": 0,
                                "title": "You Selected"
                            },
                            {
                                "items": [
                                    {
                                        "identifier": "burrito-appetizer",
                                        "order": 1,
                                        "style": "default",
                                        "subtitle": "Good burritos",
                                        "title": "Burritos"
                                    },
                                    {
                                        "identifier": "burrito-meal",
                                        "order": 3,
                                        "style": "default",
                                        "subtitle": "Good burritos",
                                        "title": "Burritos"
                                    }
                                ],
                                "order": 1,
                                "title": "Others"
                            }
                        ]
                    },
                    "mspVersion": "1.0",
                    "requestIdentifier": "food-picker-1"
                }
            },
            "sourceId": "urn:mbid:AQAAY5fm8C1h9GM7PJdHm1px6YYbfTH7R5Psfj0Lhh9dYbswZ+zfZekvmh6j1zuXMs7bovQJZ4d1Mw3TssgRy7mu1dXyTAY2uFrMhLt2HQILH5E6Jyq7VhpncbbIm58Ow4J6PbwgyaShPuccYT67n2TzF98KNOs=",
            "type": "interactive",
            "v": 1
        }
    },
    "source": { "type": "apple" },
    "trigger": "passthrough"
}

Identifying features supported by the end-user’s device

Apple includes a capability-list HTTP header when sending and receiving messages that identifies the Messages for Business features supported by the user’s device. We support the following capabilities:

  • QUICK - supports Quick Reply Messages. Quick Reply Messages provide users a list of choices. For example, they can select from a list of numbers from 1 to 5 to rate their customer satisfaction. You must use the Passthrough API for Quick Reply Messages.

  • LIST - supports List Picker Messages. List Picker Messages let users select from a list of items. Each item contains the item name and optionally a description or image. For example, a list of knowledge base articles is displayed to the user who then chooses the one they want to view. You must use the Passthrough API for List Picker Messages.

  • TIME - supports Time Picker Messages. Time Picker Messages let users pick a time slot for scheduling an event. For example, a user might select a time slot for a dentist visit from the list of available times. You must use the Passthrough API for Time Picker Messages.

  • FORM - support Forms Messages. Forms Message are interative flows and are supported only on iOS and iPadOS devices. For example, an interactive flow might be troubleshooting steps for debugging a computer firewall issue. You must use the Passthrough API for Form Messages.

  • AUTHENTICATION - support Authentication Messages. Authentication Messages allow users to validate their identity from within the conversation. You must use the Passthrough API for Authentication Messages.

For more information and examples of the above message types, see Interactive Message Types and Rich Link Messages. For more information and examples of how to send these types of messages, see Sending Apple messages.

Each time a new message is received from Apple Messages for Business, Sunshine Conversations includes the capability list in client.raw.capabilityList so that you can prevent unsupported message types from being sent to the end-user’s device.

"appUser": {
    "signedUpAt": "2022-05-31T18:09:59.116Z",
    "hasPaymentInfo": false,
    "_id": "bf5704bac22637ddea64fad3",
    "conversationStarted": true,
    "clients": [
        {
            "integrationId": "6296550888891d0c2263db32",
            "id": "d3ab5219-16f7-403f-a19d-701fbca40dd7",
            "status": "active",
            "raw": {
                "locale": "en_CA",
                "capabilityList": "AUTH,LIST,TIME,QUICK"
            },
            ...
        },
    ],
    ...
}

Receiving large interactive messages

If a user’s reply includes a large attachment or payload, Apple will provide an interactiveDataRef in the response rather than the complete response. For more information, see Receiving an interactive messages in Apple’s developer documentation. To download this reference and access the complete response, you can use the API below and pass the interactiveDataRef response obtained through your passthrough webhooks.

curl $SUNSHINE_CONV_ROOT/v2/apps/$APP_ID/conversations/$CONVERSATION_ID/download \
     -X POST \
     -H 'content-type: application/json' \
     -H 'authorization: Bearer your-account-jwt' \
     -d '{
            "userId": $USER_ID,
            "apple": {
                "interactiveDataRef": {
                    "url": "https://p61-content.icloud.com/M58C0A1A2EB62B6E899B4F28996E8DA229E1914295299C39944B2F2CA7482AE50.C01USN00",
                    "bid": "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.icloud.apps.messages.business.extension",
                    "key": "00c0d1827fdc858fe7b42421de1fb289c2ee0a9463d787ce4f118506f970bd6e38",
                    "signature": "81a619c81da5a01c6139219a5d20e17430c631e1eb",
                    "owner": "M58C0A2A1EB62B4E859B4F28996E8DA229E1914295299C39944B2F2CA7482AE50.C01USN00",
                }
            }
        }'

Closed conversations

Users can opt out from receiving further messages. When a customer deletes a conversation in Messages, a dialog appears that asks if they want to stop receiving messages from the business. If the customer chooses to stop receiving messages, Messages for Business considers the conversation closed and sends a message of type close to the Sunshine Conversations. You can read more about this in Apple’s Developer Docs.

Upon receiving a close message, Sunshine Conversations will set client.status: blocked on the client with platform: "apple" of the corresponding appUser.

A client:block event will also be POSTed to subscribed webhooks.

Large Apple Messages for Business message payloads

The existing Sunshine Conversations /messages and /templates APIs will not accept payloads larger than 100kb.

In order to remain compatible with Apple’s large payloads, Sunshine Conversations offers separate APIs designed specifically for handling large Apple Messages for Business override payloads. The existing Sunshine Conversations /messages and /templates API accept the override parameter inside JSON payloads smaller than 100kb while a separate set of APIs will be offered that are designed to accept much larger payloads, up to 10mb.

Standard Sunshine Conversations API (v1)Large Apple paylaods equivalent
POST /v1/apps/:appId/appusers/:userId/messagesPOST /v1/apps/:appId/appusers/:userId/messages/large
POST /v1/apps/:appId/templatesPOST /v1/apps/:appId/templates/large
PUT /v1/apps/:appId/templates/:templateIdPUT /v1/apps/:appId/templates/:templateId/large

The large payload APIs may only be used for apps that have a valid Apple Messages for Business integration configured.

We strongly recommend using templates for sending large Messages for Business messages whenever possible as constantly transferring the same large payload when sending the same content to multiple users generates unnecessary network traffic, which may cause message delivery latency.

If your quick reply requires the use of interactive data because the reply is too large, please use the passthrough API to send that message.

Key differences

The large payload APIs behave the same as their conventional equivalents, except for two key differences:

  1. override.apple.payload (or message.override.apple.override for templates) is required in the request body
  2. Processing of the API calls are deferred to a queue (see section below for success confirmation and error handling)

Introducing requestId and webhooks for large payloads

Large message and template processing is deferred to a processing queue and therefore large payload APIs return 202 Accepted along with a requestId. For example:

{"requestId":"dkgSujU2R62HF3W9PnRIGy8K"}

This requestId can be used to track the success or failure of the request (message delivery or template creation/update) via two new webhook triggers: request:success and request:failure. The request body of request:success webhooks have a response key, whose value matches the structure returned from the associated standard API. request:failure webhooks have an “error” key mapping to an object containing error details. Possible error codes can be found here.

Example for POST /v1/apps/:appId/appusers/:userId/messages/large:

request:success example:

{
    "trigger": "request:success",
    "app": { "_id": "564f56151d195e2100c49f13" },
    "appUser": { "_id": "4f75e8d7c26953e0df65bb40" },
    "requestId": "dkgSujU2R62HF3W9PnRIGy8K",
    "timestamp": 1534173863.84,
    "response": {
        "message": {
	    "_id": "5b71beb728ef8677a427c769",
	    ...
        },
        "conversation": {
    	    "_id": "1f706345a613e803962dfe54",
	    ...
        }
    }
}

request:failure example:

{
    "trigger": "request:failure",
    "app": { "_id": "564f56151d195e2100c49f13" },
    "appUser": { "_id": "4f75e8d7c26953e0df65bb40" },
    "requestId": "dkgSujU2R62HF3W9PnRIGy8K",
    "error": {
        "code": "bad_request",
        "message": "Invalid JSON"
    },
    "timestamp": 1534173863.84
}

Example of a large message request

SUNSHINE_CONV_ROOT='https://api.smooch.io'
APP_ID='your_app_id'
APP_USER_ID='app_user_id'
MESSAGE=$(cat <<-END
{
  "type": "text",
  "text": "Hello non-apple channel",
  "role": "appMaker",
  "override": {
    "apple": {
      "payload": {
        "type": "interactive",
        "interactiveData": {
          "bid": "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.icloud.apps.messages.business.extension",
          "data": {
            "version": "1.0",
            "requestIdentifier": "",
            "images": [
              {
                "data": "base64encoded-image-file",
                "identifier": "1"
              },
              {
                "data": "base64encoded-image-file",
                "identifier": "2"
              },
              {
                "data": "base64encoded-image-file",
                "identifier": "3"
              }
            ],
            "listPicker": {
              "sections": [
                {
                  "title": "Appetizers",
                  "order": 0,
                  "items": [
                    {
                      "title": "Tacos",
                      "order": 0,
                      "identifier": "taco-appetizer",
                      "imageIdentifier": "2"
                    },
                    {
                      "title": "Burritos",
                      "order": 1,
                      "identifier": "burrito-appetizer",
                      "imageIdentifier": "3"
                    }
                  ]
                },
                {
                  "title": "Meals",
                  "order": 1,
                  "items": [
                    {
                      "title": "Tacos",
                      "order": 0,
                      "identifier": "taco-meal",
                      "imageIdentifier": "2"
                    },
                    {
                      "title": "Burritos",
                      "order": 1,
                      "identifier": "burrito-meal",
                      "imageIdentifier": "3"
                    }
                  ]
                }
              ]
            }
          },
          "receivedMessage": {
            "style": "small",
            "title": "Food Picker",
            "subtitle": "Let\"s eat!",
            "imageIdentifier": "1"
          },
          "replyMessage": {
            "style": "small",
            "title": "Selected food",
            "subtitle": "Nutrition"
          }
        }
      }
    }
  }
}
END
)

curl $SUNSHINE_CONV_ROOT/v1/apps/$APP_ID/appusers/$APP_USER_ID/messages/large \
     -X POST \
     -H 'content-type: application/json' \
     -H 'authorization: Bearer your-account-jwt' \
     -d "$MESSAGE"

curl $SUNSHINE_CONV_ROOT/v1/apps/$APP_ID/templates/large \
     -X POST \
     -H 'content-type: application/json' \
     -H 'authorization: Bearer your-account-jwt' \
     -d '{
            "name": "test-template-1234",
            "message":'"$MESSAGE"'
        }'

TEMPLATE_ID='your_template_id'
curl $SUNSHINE_CONV_ROOT/v1/apps/$APP_ID/templates/$TEMPLATE_ID/large \
     -X PUT \
     -H 'content-type: application/json' \
     -H 'authorization: Bearer your-account-jwt' \
     -d '{
            "name": "new-template-name",
            "message":'"$MESSAGE"'
        }'

Large messages considerations

Just like the traditional /messages API, /messages/large can be used to send messages to users on channels other than Apple Messages for Business. If you wish to target a user’s Apple client specifically you can do so via channel targeting.

Large templates considerations

Sending a large template is done using the standard /messages API, as described here.

It’s possible to convert a standard template to a large one by calling the PUT /templates/:templateId/large endpoint. Converting a large template to a standard one is also possible by calling the PUT /templates/:templateId endpoint and providing the message in the request body.

Large templates are deleted the same way as standard templates, by calling the DELETE /templates/:templateId endpoint.

Fetching large templates can be achieved by using the same APIs as for standard templates (GET /templates and GET /templates/:templateId). An isLarge property set to true will be included only for large templates (it won’t be present for standard templates.) Note that when retrieving a large template, the response will not include the Apple override section.

Apple Reading Materials

Getting Started Guide

Design Guidelines

Messages for Business Policies and Best Practices

Adding a Messages for Business Button to Your Website