Skip to main content

Conversation API

Sending Messages

Send a single message or reply to inbound

POST https://a.loopmessage.com/api/v1/message/send/

You can use a contact phone number/email address (depending on what the user provided you with when init a conversation).

Headers

NameTypeDescription
Authorization*StringAPI Key. Required*.
Content-Type*Stringapplication/json

Request Body

NameTypeDescription
contact*StringPhone number or iMessage email
text*StringYour message text
senderStringOptional. ID of your sender name. Send a message from a specific sender name. This parameter is required if you try to init a conversation with a new contact.
subjectStringOptional. Your message subject. A recipient will see this subject as a bold title before the text.
attachmentsArrayOptional. An array of strings. The string must be a full URL of your image. URL should start with https://. HTTP links (without SSL) are not supported. This must be a publicly accessible file URL: we will not be able to reach any URLs that are hidden or that require authentication. Max length of each URL: 256 characters, max elements in the array: 10.
effectStringOptional. Add effect to your message. Possible values: slam, loud, gentle, invisibleInk, echo, spotlight, balloons, confetti, love, lasers, fireworks, shootingStar, celebration You can check the Apple guide about expressive messages.
reply_to_idStringOptional. The message_id that you got from the webhook You can check the Apple guide about the reply to feature.
passthroughStringOptional. A string of metadata you wish to store with the checkout. Will be sent alongside all webhooks associated with the outbound message. Max length: 1000 characters.
channelStringOptional. You can choose which service to use to deliver the message. By default, the required channel will be determined automatically Possible values: imessage, sms , rcs, or whatsapp. Your sender name must have an active SMS, RCS, or WhatsApp feature SMS does not support subject, effect, or reply_to_id parameters. attachments in SMS - only support pictures (MMS). Use this parameter only in cases when you need to override the delivery channel for a specific request. DON’T use it as a default parameter for all requests.
contact_fileBoolOptional. Add a vCard (Contact file) as an attachment in your message. Use this parameter only in cases when you need to share a contact file. DON’T use it as a default parameter for all requests.

Response {.tabset .tabset-fade}

tab 200: Request accepted

{
    "message_id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
    "contact": "+13231112233",
    "text": "text"
}

Phone number will be converted to the next format +13231112233, without spaces and brackets. Email will be converted into a lowercase format.

tab 400: Request failed

{
    "message_id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
    "success": false,
    "message": "error description",
    "contact": "+13231112233",
    "text": "text"
}

tab 402: Payment Required

    "message_id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
    "success": false,
    "message": "error description",
    "contact": "+13231112233",
    "text": "text"
}

**Importan **! When you receive a successful response with code 200 from send request, it means that the server accepted your request for send and added it to the queue. But this does not mean that the message was delivered to the recipient or will be sent.

To handle message status for this request, need to observe Webhooks or use the API method to check the status by message ID, which you received in the JSON response.

We recommend using webhooks to track statuses, as you will receive a callback as soon as an event is fired.

Supported phone number formats

Recipient phone numbers should be only in international formats with a country code. Otherwise will be impossible to verify a phone number.

Plus prefix + is optional. Spaces, dashes ‘-’, brackets ‘(123)’ - also optional.

Valid phone number format examples:

  • 13231234567
  • +13231111111
  • +1 (323) 1111111
  • +1 323 123 4567
  • 1 (323)-123-4567

Send a single message to an iMessage group

Sender name

An example of how group chats look like in iMessage

POST https://a.loopmessage.com/api/v1/message/send/

Headers

NameTypeDescription
Authorization*StringAPI Key. Required*
Content-Type*Stringapplication/json

Request Body

NameTypeDescription
group*StringiMessage/RCS/WhatsApp group ID. You can only get this ID from the webhook: message_inbound.
text*StringYour message text
subjectStringOptional. Your message subject. A recipient will see this subject as a bold title before the text.
senderStringOptional. ID of your sender name. Send message from a specific sender name.
attachmentsArrayOptional. An array of strings. The string must be a full URL of your image. URL should start withhttps://…,**http links (without SSL) are not supporte **. This must be a publicly accessible URL: we will not be able to reach any URLs that are hidden or that require authentication. Max length of each URL: 256 characters, max elements in the array: 10.
effectStringOptional. Add effect to your message. Possible values: slam, loud, gentle, invisibleInk, echo, spotlight, balloons, confetti, love, lasers, fireworks, shootingStar, celebration You can check the Apple guide about expressive messages.
reply_to_idStringOptional. The message_id that you got from the webhook You can check the Apple guide about the reply to feature.
passthroughStringOptional. A string of metadata you wish to store with the checkout. Will be sent alongside all webhooks associated with the outbound message. Max length: 1000 characters.

Response {.tabset .tabset-fade}

tab 200: Request accepted

{
    "message_id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
    "group": {
        "id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
        "name": "String",  // Optional field
        "participants": ["+13231112233", "+13232223344"]
    },
    "text": "text"
}

tab 400: Request failed

{
    "message_id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
    "success": false,
    "message": "error description",
    "group": {
        "group_id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
        "name": "String",  # Optinal field
        "participants": ["+13231112233", "+13232223344"]
    },
    "text": "text"
}

tab 402: Payment Required

    "message_id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
    "success": false,
    "message": "error description",
    "group": {
        "group_id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
        "name": "String",  # Optinal field
        "participants": ["+13231112233", "+13232223344"]
    },
    "text": "text"
}

You can’t create an iMessage Group, change its name, or add/remove participants to it via the API. You can only receive and reply to incoming messages/attachments.

Send a voice message

Sender name

An example of how voice/audio messages look in iMessage

POST https://a.loopmessage.com/api/v1/message/send/

Headers

NameTypeDescription
Authorization*StringAPI Key. Required*.
Content-Type*Stringapplication/json

Request Body

NameTypeDescription
contact*StringPhone number or Email.
media_url*String

The string must be a full URL of your audio file. URL should start with https://…, http links (without SSL) are not supported. This must be a publicly accessible URL: we will not be able to reach any URLs that are hidden or that require authentication. Max length of each URL: 256 characters.

Audio files of the following formats are supported: mp3, wav, m4a, caf, aac.

senderStringOptional. Your dedicated sender name. This parameter will be ignored if you send a request to a recipient who is added as a sandbox contact. DON’T use a phone number as a value for this parameter.
passthroughStringA string of metadata you wish to store in the request. Will be sent alongside all webhooks associated with the outbound message. Max length: 1000 characters.

Response {.tabset .tabset-fade}

tab 200: Request accepted

{
    "message_id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
    "recipient": "+13231112233",
    "text": "text"
}

Phone number will be converted to the next format +13231112233, without spaces and brackets. Email will be converted into a lowercase format.

tab 400: Request failed

{
    "message_id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
    "success": false,
    "message": "error description",
    "recipient": "+13231112233",
    "text": "text"
}

tab 402: Payment Required

    "message_id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
    "success": false,
    "message": "error description",
    "recipient": "+13231112233",
    "text": "text"
}

To send a voice message to an iMessage group, you need to use the group field instead contact.

Send a reaction

Sender name

An example of how tapback reactions looks like in iMessage

POST https://a.loopmessage.com/api/v1/message/send/

Headers

NameTypeDescription
Authorization*StringAPI Key. Required*.
Content-Type*Stringapplication/json

Request Body

NameTypeDescription
contact*StringPhone number or Email.
message_id*StringThe message_id that you got from the webhook.
reaction*StringPossible values:love, like, dislike, laugh, emphasize, question, -love, -like, -dislike, -laugh, -emphasize, -question. Reactions that started with - mean “remove” it from the message You can check the Apple guide about reactions and tapbacks.

Show typing indicator

Sender name

POST https://a.loopmessage.com/api/v1/message/show-typing/

Headers

NameTypeDescription
Authorization*StringAPI Key. Required*.
Content-Type*Stringapplication/json

Request Body

NameTypeDescription
message_id*StringThe message_id that you got from the webhook.
typingIntegerThis value means how long in the seconds we will show typing indicator. The max value is 60.
readBoolMark conversation as read

Alternatively, you can use the “contact” and “sender” parameters:

NameTypeDescription
contact*StringPhone number or Email.
sender*StringID of your sender name.
typingIntegerThis value means how long in the seconds we will show typing indicator. The max value is 60.
readBoolMark conversation as read. Default true if presenting typing indicator.

The indicator will be automatically hidden as soon as you send an outbound message

Typing indicator limitations

This feature has important limitation!
If there is no two-way conversation for more than 5 minutes, then any attempts to show the animation will fail. You should use this feature in active conversations only. In the video below, you can see examples with these limitations.

Send “Read” status

Sender name

To let your contacts know that you’ve accepted a message, you can mark a conversation as read. Todo it, just add “read” to your JSON Body. Example:

{ 
  "typing": 5, // It's optional to show typing indicator here
  "read": true 
}

Init a conversation with a new contact

POST https://a.loopmessage.com/api/v1/message/send/

Please note that this feature is working only if your sender name has an option to init a conversation with a new contact.

Init conversation with a new contact who hasn’t communicated with your sender before.

Headers

NameTypeDescription
Authorization*StringAPI Key. Required*.
Content-Type*Stringapplication/json

Request Body

NameTypeDescription
contact*StringPhone number or iMessage email
text*StringYour message text. An initial message must never contain any of the following: marketing, junk, phishing, scam, links, emails, phone numbers, currencies, or attachments.
sender*StringID of your sender name. Need to specify from which sender name init a conversation.
subjectStringOptional. Your message subject. A recipient will see this subject as a bold title before the text.
passthroughStringOptional. A string of metadata you wish to store with the checkout. Will be sent alongside all webhooks associated with the outbound message. Max length: 1000 characters.
channelStringOptional. You can choose which service to use to deliver the message. By default, the required channel will be determined automatically Possible values: imessage, sms , rcs, or whatsapp. Your sender name must have an active SMS, RCS, or WhatsApp feature SMS does not support subject. Use this parameter only in cases when you need to override the delivery channel for a specific request. DON’T use it as a default parameter for all requests.

Failed responses

Please note that in most cases, handling failed responses can be far more important than handling successful ones. If something goes wrong, it may help to quickly take further action.

If your request has a failed status, you will receive a JSON response with the following content:

{
    "success": false,
    "code": 100,
    "message": "string"
}

It is important to implement handling the “code” field. It helps to understand how to manage your further actions according to the error code.

The message field is optional and briefly describes the reason for the error. Please do not pass this to the destination users/recipients. Use the “code” field to map errors and show localized error text to them.

Response example

Response {.tabset .tabset-fade}

tab 200: Request accepted

{
    "message_id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
    "success": true,
    "recipient": "+13231112233",
    "text": "text"
}

Phone number will be converted to the next format +13231112233, without spaces and brackets. Email will be converted into a lowercase format.

tab 400: Request failed

{
    "message_id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
    "success": false,
    "message": "error description",
    "recipient": "+13231112233",
    "text": "text"
}

tab 402: Payment Required

    "message_id": "2BC4FD6A-CE49-439F-81DF-E895C09CA49C",
    "success": false,
    "message": "error description",
    "recipient": "+13231112233",
    "text": "text"
}

Limits

Sendings

  • If you need to send messages to a few contacts who haven’t recently sent you any inbound messages, you must keep a minimal interval of 2 minutes between each such message. Otherwise, your request may be rejected.
  • If you have a feature for init a conversation with new contacts, you will need to keep an interval of 15 minutes between each sending. Also, you need to take into account warm-up limitations.
  • If you receive an inbound message, you can reply without any intervals. Even if you receive an inbound message from a few contacts simultaneously.

Content

  • Max text length in each message must be less than 10000 characters. Otherwise, all extra characters will be truncated. If you have larger requirements, we recommend breaking the message up into several smaller messages.

    You can use characters from any language, emojis, and \n for new lines. HTML tags aren’t supported.

Best Practices

Sending attachments

  • It’s highly recommended to use a CDN, an S3 Bucket, or another similar storage service for your attachments. If our server is unable to access and download the file or handle its extension, the attachment will not be sent.
  • When you send an attachment file for the first time, it takes a while for it to download into the cache before it’s sent to the recipient. If your attachments are large (more than a couple of megabytes), they will take a while to reach your contact.
    If you update your file, but it still has the same URL, the cached version will still be used. To avoid a cached version, you need to change the file URL (for example, by renaming the file name).

Handling failed cases

It’s recommended to implement handling of the next failed/error cases:

  • If the response code for sending a message is NOT equal 200. In most cases, it means that something is wrong with your parameters.
  • You receive a webhook with the type message_failed or message status is failed.

    This means that the message can’t be delivered to this recipient. Check the error_code JSON field to better understand your case.