Skip to main content

Conversation API

Webhooks/Callbacks

Through webhooks, you can receive notifications when an event is fired. In most cases, it is a good idea to start processing inbound messages and then process the statuses of outbound messages.

Registering and processing webhooks

For each organization, you can specify separate webhook URLs and headers for events.

Our server will send POST requests to your server, in which the body will be a JSON representation of the notification. Your server should return a 200 status code. Any other status code will be considered a failure by our backend. Our server will retry later (up to 30 times) with an increasing delay. First 10 retries every 30 seconds, the next 10 retries every 3 mins, and the last 10 retries every 15 mins. After 30 retries, we will stop sending notifications.

If your service/app doesn’t return a response within 15 seconds, our server will disconnect and reschedule a webhook for retry. It’s highly recommended that your apps/services defer processing until return a response with a status code 200.

Webhook Events

Sample Webhook Events

These are some representative samples of webhooks you might receive from LoopMessage. Keep in mind that webhooks can include additional fields to what’s shown here.

Response {.tabset .tabset-fade}

tab Inbound

{
    "event": "message_inbound",
    "contact": "+13231112233",
    "text": "text",
    "message_type": "text",
    "message_id": "59c55Ce8-41d6-43Cc-9116-8cfb2e696D7b",
    "webhook_id": "ab5Ae733-cCFc-4025-9987-7279b26bE71b",
    "api_version": "1.0"
}

tab Scheduled

{
    "event": "message_scheduled",
    "contact": "+13231112233",
    "text": "text",
    "message_id": "59c55Ce8-41d6-43Cc-9116-8cfb2e696D7b",
    "webhook_id": "ab5Ae733-cCFc-4025-9987-7279b26bE71b",
    "api_version": "1.0"
}

tab Failed

{
    "event": "message_failed",
    "contact": "+13231112233",
    "text": "text",
    "error_code": 100,
    "message_id": "59c55Ce8-41d6-43Cc-9116-8cfb2e696D7b",
    "webhook_id": "ab5Ae733-cCFc-4025-9987-7279b26bE71b",
    "api_version": "1.0"
}

tab Delivered

{
    "event": "message_delivered",
    "contact": "+13231112233",
    "text": "text",
    "message_id": "59c55Ce8-41d6-43Cc-9116-8cfb2e696D7b",
    "webhook_id": "ab5Ae733-cCFc-4025-9987-7279b26bE71b",
    "api_version": "1.0"
}

tab Reaction

{
    "event": "message_reaction",
    "contact": "+13231112233",
    "text": "text",
    "reaction": "like",
    "message_id": "59c55Ce8-41d6-43Cc-9116-8cfb2e696D7b",
    "webhook_id": "ab5Ae733-cCFc-4025-9987-7279b26bE71b",
    "api_version": "1.0"
}

Possible JSON fields in webhooks

FieldTypeDescription
message_idStringUnique identifier of your request/message.
webhook_idStringUnique identifier of the event.
eventStringCheck the Event Types section for possible values.
contactStringThe contact to which the event relates. Contact can be a phone number or email address. A phone number will be in the E164 format: +13231112233, without spaces and brackets. Email will be in lowercase format.
textStringText in the message.
subjectStringOptional Field. Message subject.
attachmentsArrayOptional Field with an array of strings. This field will only be for the event: message_inbound. Each element of the array is the URL to download the file.
message_typeStringThis field will only be for events: message_inbound or message_reaction.
Possible values: text, reaction, audio, attachments, sticker, location.
channelStringHow the message was sent/received. Possible values: imessage, sms, rcs.
reactionStringIndicates if a contact reacted to your message This field will only be for the event: message_reaction Possible values: love, like, dislike, laugh, emphasize, question, unknown.
senderStringDedicated sender name ID.
thread_idStringOptional field. If the contact tapped reply-to it will create a conversation thread in the iMessage. This identifier will help you understand to which thread the message is related.
error_codeIntegerError code that occurred while processing the request This field will only be for the event: message_failed.
languageObjectThe dominant language that is used in the text. Check the language section for details.
groupObjectData related to the iMessage group. Check the group section for details.
speechObjectOptional field. Transcription of an inbound audio message. Will be contained in the JSON only if the speech section for details.
parametersObjectOptional field. This field will only be for the event: message_inbound. Additional parameters were included by using the opt-in API or sign-up forms. Parameters may vary depending on what you set up to include there.

Event Types

All values will be in lowercase and in snake_case format

Event typeDescription
message_failedFailed to send or deliver a message. Further events related to your request will no longer be fired.
message_deliveredThe message has been delivered.
message_inboundContact sent you an inbound message.
message_reactionContact put a reaction to your text. For example Like, Love and etc.
inbound_callYour contact attempted to call via FaceTime.
unknownAn unknown event has occurred

Language

KeyValue
codeISO 639-1 code. Examples: en, fr, de, ja, zh.
nameExamples: English, French, German, Japanese, Chinese.
scriptOptional field. Supported only two values for the Chinese language:-Hans: Simplified Chinese script-Hant: Traditional Chinese script

The dominant language in the text. These values are approximate and may be incorrect if the message is less than 100 characters long or contains text in several languages.

Group

KeyValue
idUnique ID of iMessage group. You can use this value as the contact/recipient value in the send messages requests.
nameOptional field. Custom name for this group (if named).
participantsAn array of strings (participants) in this group. Values in the array can be a phone number (in E164 format) or email (in lowercase format).

Speech

KeyValue
textText transcription from audio message
languageLanguage object. The dominant language that is used in the text. Check the language section for details.
metadataOptional field. The metadata of speech in the audio message. Check the speech metadata section for details.

These values are approximate and may be incorrect if the voice is too long, unclear, or in several languages.

Speech metadata

Any field in this object can be optional. All values are float type.

KeyValue
speaking_rateMeasures the number of words spoken per minute.
average_pause_durationMeasures average pause between words (in seconds).
speech_start_timestampTimestamp of start of speech in audio.
speech_durationDuration of speech in audio.
jitterJitter measures vocal stability and is measured as an absolute difference between consecutive periods, divided by the average period. It is expressed as a percentage.
shimmerShimmer measures vocal stability and is measured in decibels.
pitchPitch measures the highness and lowness of tone and is measured in logarithm of normalized pitch estimates.
voicingVoicing measures the probability of whether a frame is voiced or not and is measured as a probability.

Parameters

Parameters may vary depending on what you set up to include there.
If you are using the opt-in API, it will include all parameters you passed when generating an opt-in URL.

If you are using sign-up forms, they may include all the fields that you set up in your form.

An example of fields if you’re using sign-up forms:

{
    ...
    "parameters": {
      "pool": "your-pool-id",
      "timezone": "America/New_York",
      "form_elements": {
        "first_name": "John",
        "last_name": "Smith",
        "email": "[email protected]",
        "country": "US",
        "company": "String",
        "company_website": "https://secrect-company.ai",
        "zip": "10001",
        "custom1": "Custom field"
      }
    }
}

Headers

All webhooks will contain the following headers

KeyValue
Content-Typeapplication/json
User-AgentLoopMessage
Connectionclose

Best practices

Authorization

You can configure the authorization header used for webhook requests via the dashboard. Your server should verify the validity of the authorization header for every event. This will help you make sure that a webhook was sent from our service.

IP Whitelisting
The webhook IP range is variable, so we don’t recommend hardcoding our server’s IP. To authenticate requests, you can add an authorization token to the webhook that you can then verify on your server.

Response Duration

Try to return a response immediately so as not to accidentally reach the timeout duration.

If this happens, you can use webhook_id as a unique identifier to avoid processing the same event twice. But even in this case, you need to return a response with code 200 to stop firing a webhook.

Please note that if you are using ngrok or similar services, the timeout time will be much shorter to prevent abuse by keeping many dummy connections.

Security and encryption

It is highly recommended to use HTTPS URLs for webhooks. If you use HTTP URLs (without SSL), requests to your server will not be encrypted and the contents of your requests/messages may be intercepted. In some cases, webhooks for HTTP URLs (without SSL) may not be delivered.

Future-Proofing

You should be able to handle webhooks that include all important fields to what’s shown here, including new event types. We may add new fields or event types in the future without changing the API version. We won’t remove fields or events without proper API versioning and deprecation.