π‘ AI Bot Integration
Important: This documentation describes the integration with our test environment. Before moving to production, please test your integration thoroughly in this environment. Contact api-support@likemagic.tech to get onboarded and receive your test environment credentials.
Mainflow
- Guest contacts hotel
- LIKE MAGIC receives incoming message through Bird
- LIKE MAGIC matches the message to a guest identity and potential existing reservation
- LIKE MAGIC request an automated answer from the AI partner and provides guest & reservation context
- AI partner can ask for additional information from the LIKE MAGIC platform if needed (e.g. booked additional services)
- AI partner provides a response to LIKE MAGIC
- LIKE MAGIC send the response through Bird to the guest
Matching a message to a guest identity does not always succeed, and the identity of a conversation can change later. See Guest identity and conversation history before you design how you store guest state.
sequenceDiagram
participant Bird
participant "LIKE MAGIC"
participant "AI partner"
Bird->>"LIKE MAGIC": 1: Incoming guest message
activate "LIKE MAGIC"
"LIKE MAGIC"->>"LIKE MAGIC": 2: Find corresponding guest identity & reservation
"LIKE MAGIC"->>"AI partner": 3: Guest message with guest identity & reservation context
activate "AI partner"
"AI partner"->>"AI partner": 4: Create answer
opt Fetch additional information
"AI partner"->>"LIKE MAGIC": 5: Additional information
"LIKE MAGIC"-->>"AI partner": response
end
"AI partner"-->>"LIKE MAGIC": 6: Guest response via Webhook
deactivate "AI partner"
"LIKE MAGIC"->>Bird: 7: Respond to guest
deactivate "LIKE MAGIC"
Information for AI partner
All the events from the AI partner are to be posted (POST) on a webhook provided by LIKE MAGIC.
Whatsapp Number (Test Environment)
+1 (226) 640-5907 (Test environment only - in production you will use the dedicateds number of the hotel)
URL
The webhook URLs below use your tenant-specific Base URL (see Prerequisites & Configuration) - shown as a pattern on the central docs and filled in automatically on your own environment.
Open this page on your own environment
We strongly suggest heading over to your tenant's own copy of this page now, to see your real URLs instead of the patterns below and eliminate any guessing:
https://monitoring.<your-domain>/api-doc/use-case/partner/ai-bot-integration/
Just swap in your <your-domain>.
| Environment | Endpoint |
|---|---|
| Test Environment | /api/integration-service/webhook/unified-messaging/<tenant>/callback |
| Test BaseUrl | |
| Test Tenant | likemagic-test |
Task API Integration
For the best possible integration experience, we recommend integrating with our Task API. This allows your AI bot to: - Create tasks based on guest requests - Track task status and progress - Handle service requests efficiently - Manage hotel operations seamlessly
For detailed Task API documentation and integration guidelines, refer to our Manage Tasks Guide.
Security
All incoming webhooks are secured with a lm-webhook-secret header. Contact api-support@likemagic.tech to get your test environment secret key.
AI Events description
| Property | Type | Contract | Description |
|---|---|---|---|
| event | Enum | required | Defines the type of the event ai.response |
| conversationId | UUID | optional | Required for type ai.response, ai.action Is shared by LM when receiving the initial guest message |
| messageId | UUID | optional | Required for type ai.response Unique identifier defined by the AI partner, e.g. 42827c8e-0354-4b13-9319-5093b83886fe |
| type | Enum | required | Defines in more detail the event |
| content | Object | optional | Required for type ai.response Answer from the AI partner. The content of this object is dynamic and depends on the type of the message. |
AI Message Response
A response from the AI to be sent to the guest.
{
"event": "ai.response",
"conversationId": "367fecba-bc23-418b-aef2-7943180860d4",
"messageId": "U-1",
"type": "text",
"content": "Chatbot response to the conversation"
}
Sample CURL
curl -X 'POST' \
'{{monitoringUrl}}/api/integration-service/webhook/unified-messaging/<tenant>/callback' \
-H 'accept: */*'
-H 'Content-Type: application/json' \
-d '{
"event": "ai.response",
"conversationId": "367fecba-bc23-418b-aef2-7943180860d4",
"messageId": "U-1",
"type": "text",
"content": "Chatbot response to the conversation"
}'
Human intervention needed
Informing LM that a human needs to take over the conversation
{
"event": "ai.action",
"conversationId": "367fecba-bc23-418b-aef2-7943180860d4",
"type": "HUMAN_INTERVENTION_NEEDED",
}
Sample CURL
curl -X 'POST' \
'{{monitoringUrl}}/api/integration-service/webhook/unified-messaging/<tenant>/callback' \
-H 'accept: */*'
-H 'Content-Type: application/json' \
-d '{
"event": "ai.action",
"conversationId": "367fecba-bc23-418b-aef2-7943180860d4",
"type": "HUMAN_INTERVENTION_NEEDED",
}'
Webhook to be provided by AI Partner
LIKE MAGIC requires the AI partner to provide an webhook endpoint so the partner can consume events from LM.
Please share the URL with your technical contact person from LM
Security
All outgoing webhooks are secured with a lm-webhook-secret header. Please contact your technical contact person from LM to get the secret.
Webhook Description
| Property | Type | Contract | Description |
|---|---|---|---|
| event | Enum | required | Defines the type of the event lm.action |
| type | Enum | required | Defines in more detail the event whatsapp |
| tenantName | String | required | Name of the LIKE MAGIC customer |
| conversationId | UUID | required | Required for type whatsapp | HUMAN_TAKE_OVER |AI_TAKE_OVER unique identifier for a conversation which can contain multiple messages |
| messageId | UUID | optional | Required for type whatsapp unique identifier of the specific message |
| pmsReservationId | String | optional | Required for type whatsapp If available the linked reservation id from the PMS will be set |
| pmsPropertyId | String | optional | Required for type whatsapp If available the linked property id from the PMS will be set. If no property id can be determined the field is not sent |
| content | Object | optional | Required for type whatsapp | sms | booking_dot_com Message of the guest |
| String | required | if event = lm.message | |
| Image object | required | if event =lm.image | |
| File object | required | if event = lm.file | |
| Notification object | required | if event = lm.notification | |
| createdAt | DateTime String (ISO-8601) |
required | DateTime String when the message was created |
| guestActor | GuestActor object | optional | Guest details. Sent for lm.message, lm.image, lm.file and lm.notification. Not sent for lm.action, which is a conversation level signal |
Guest Actor
| Property | Type | Contract | Description |
|---|---|---|---|
| guestIdentityId | Long | optional | Durable identifier of the guest across conversations and channels within one tenant. Empty while the contact is not yet identified, see Guest identity and conversation history |
| userProfileId | Long | optional | Identifier of the guest profile. Use it to load conversation history and profile data. Set whenever guestIdentityId is set and a profile exists |
| firstName | String | optional | First name of guest if available |
| lastName | String | optional | Last name of guest if available |
| phone | String | optional | Phone number if available |
| String | optional | Email of guest if available |
Image
| Property | Type | Contract | Description |
|---|---|---|---|
| mediaUrl | String | required | URL of the image, to be fetched from LM |
| caption | String | optional | Optional caption provided by the guest |
File
| Property | Type | Contract | Description |
|---|---|---|---|
| mediaUrl | String | required | URL of the file, to be fetched from LM |
| contentType | String | required | File contentType e.g. video/mp4 |
| caption | String | optional | Optional caption provided by the guest |
Notification
| Property | Type | Contract | Description |
|---|---|---|---|
| text | String | required | Text of the trigger based template message |
| templateName | Enum | required | Name of the LIKE MAGIC template: COMPANION_ADDED, PRE_CHECKIN_REMINDER, RESERVATION_CREATED, CHECKIN, CHECKED_IN, CHECKIN_INTRODUCTION, CHECKIN_REMINDER, CHECKOUT_ALERT, CHECKOUT_FOLLOW_UP, CHECKOUT_INTRODUCTION, ID_CHECK_DECLINED, INVOICE, RESERVATION_CANCELED |
| language | Enum | required | Language used of the template, e.g. DE or EN |
Guest identity and conversation history
Four identifiers appear in these events and they serve different purposes.
| Identifier | Use it for | Stability |
|---|---|---|
guestIdentityId |
Grouping a guest's conversations over time | Durable, but can be superseded |
userProfileId |
Loading conversation history and profile data through our APIs | Stable in normal operation. Can change when two profiles are merged |
conversationId |
Correlating events within one conversation | Not durable, can change |
messageId |
Matching a specific message across changes | Stable, preserved in all cases |
When guestIdentityId is empty
We set guestIdentityId once we have matched the sender's phone number or email to a known guest. It is empty when:
- the guest writes from a phone number or email we have never linked to a reservation
- the contact belongs to an OTA placeholder address rather than to the guest
- our person record matching could not resolve the contact unambiguously
While it is empty we cannot tell you which other conversations belong to the same person, and neither history endpoint helps. Use guestActor.phone if you need a best effort grouping on your side.
The value fills in on its own once a reservation carrying that contact reaches us. It is not guaranteed to ever fill in. A contact that never appears on a reservation stays unidentified.
Loading a guest's conversation history
With the userProfileId from the event:
| Endpoint | Returns |
|---|---|
GET /guest-conversations/by-user-profile-id/{userProfileId} |
Paginated conversations of that guest, newest first |
GET /guest-conversations/{conversationId}/messages |
Paginated messages of one conversation |
If you only hold a guestIdentityId, resolve the profile first with GET /user-profiles/by-guest-identity-id/{guestIdentityId}. The id in the response is the userProfileId. A guest identity almost always has a profile, but the call can return 404, so handle that case.
Do not swap the two ids
Do not pass a guestIdentityId where a userProfileId is expected. They are separate id spaces. The call usually returns 404 and can in rare cases return a different guest's conversations.
When a conversation is re-keyed
When a contact that was not identified later becomes identified, or an operator resolves an identity conflict, we move the affected messages onto the identified guest and the conversationId changes.
Plan for the following:
- A
conversationIdyou hold can change. The next event for that guest carries the new one. - A conversation can be re-keyed more than once.
- We delete a conversation once a move leaves it empty, so a
GETon thatconversationIdreturns 404. Treat that as superseded rather than invalid and resolve the guest again. guestIdentityIdcan also be superseded. When an operator merges several identities we create a new one, so two values you have seen can both be replaced by a third.- A conversation can hold messages for more than one contact address of the same guest, for example a phone number and an email. A move covers the messages of the contact that was linked, so a conversation can be split.
Because of the last point, do not assume that every message you received under the old conversationId belongs to the newly resolved guest. Match on messageId, which we preserve. Messages you saw under the old conversation reappear under the new one with the same message ids.
We do not currently push an event when a conversation is re-keyed. You can derive it from the events you already receive. If the guestIdentityId for a conversationId you know changes, or a conversation you know appears under a new id, re-read that guest's history through the endpoints above.
Guest message
Message of a guest
{
"event": "lm.message",
"type": "whatsapp",
"tenantName": "LIKE MAGIC",
"conversationId": "CONVERSATION_ID_LIKEMAGIC",
"messageId": "MESSAGE_ID_LIKEMAGIC",
"pmsReservationId": "PMS_RESERVATION_ID",
"pmsPropertyId": "PMS_PROPERTY_ID",
"content": "An incomming message from a guest",
"createdAt": "2025-01-14T15:55:59.547Z",
"guestActor": {
"guestIdentityId": 12345,
"userProfileId": 67890,
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@example.com",
"phone": "+15550100000"
}
}
Sample CURL
curl -X 'POST' \
'https://AI_PARTNER_URL/webhook' \
-H 'accept: */*'
-H 'Content-Type: application/json' \
-d '{
"event": "lm.message",
"type": "whatsapp",
"tenantName": "LIKE MAGIC"
"conversationId": "CONVERSATION_ID_LIKEMAGIC",
"messageId": "MESSAGE_ID_LIKEMAGIC",
"pmsReservationId": "PMS_RESERVATION_ID",
"pmsPropertyId": "PMS_PROPERTY_ID",
"content": "An incomming message from a guest",
"createdAt": "2025-01-14T15:55:59.547Z",
"guestActor": {
"guestIdentityId": 12345,
"userProfileId": 67890,
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@example.com",
"phone": "+15550100000"
}
}'
Guest image
Message of a guest containing an image.
{
"event": "lm.image",
"type": "whatsapp",
"tenantName": "LIKE MAGIC",
"conversationId": "CONVERSATION_ID_LIKEMAGIC",
"messageId": "MESSAGE_ID_LIKEMAGIC",
"pmsReservationId": "PMS_RESERVATION_ID",
"pmsPropertyId": "PMS_PROPERTY_ID",
"content": {
"mediaUrl": "https://media.likemagic.tech/VgYYE0oT",
"caption": "Image caption"
},
"createdAt": "2025-01-14T15:55:59.547Z",
"guestActor": {
"guestIdentityId": 12345,
"userProfileId": 67890,
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@example.com",
"phone": "+15550100000"
}
}
Guest file
Message of a guest containing a file. Check the contentType to understand the file Type
The contentType can be
video/mp4audio/oggapplication/pdfand more
{
"event": "lm.file",
"type": "whatsapp",
"tenantName": "LIKE MAGIC",
"conversationId": "CONVERSATION_ID_LIKEMAGIC",
"messageId": "MESSAGE_ID_LIKEMAGIC",
"pmsReservationId": "PMS_RESERVATION_ID",
"pmsPropertyId": "PMS_PROPERTY_ID",
"content": {
"mediaUrl": "https://media.likemagic.tech/VgYYE0oT",
"contentType": "video/mp4",
"caption": "File caption"
},
"createdAt": "2025-01-14T15:55:59.547Z",
"guestActor": {
"guestIdentityId": 12345,
"userProfileId": 67890,
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@example.com",
"phone": "+15550100000"
}
}
Fetching data from LM based on mediaUrl
To fetch information based on the mediaUrl in the test environment, the AI partner must call:
GET /api/unified-messaging/guest-conversations/attachments?mediaUrl={mediaUrl}
API Reference
For complete API documentation including all endpoints, request/response schemas and interactive testing:
π Unified Messaging API - Live Docs
Trigger based LIKE MAGIC notification
If you are interest in LIKE MAGICs' trigger based configuration please consume the lm.notification events. These contain the content of the templates used with the guest.
{
"event": "lm.notification",
"type": "whatsapp",
"tenantName": "LIKE MAGIC",
"conversationId": "CONVERSATION_ID_LIKEMAGIC",
"messageId": "MESSAGE_ID_LIKEMAGIC",
"pmsReservationId": "PMS_RESERVATION_ID",
"pmsPropertyId": "PMS_PROPERTY_ID",
"content": {
"text": "Hey Johnπ\nGrossartig, du bist nun Teil der LIKE MAGIC Familie!π\nMit unserer Mobile-Check-in LΓΆsung hast du deinen Aufenthalt in der eigenen Hand. Keine langwierigen Prozesse mehr",
"templateName"="CHECKIN_REMINDER",
"language"="DE"
},
"createdAt": "2025-08-19T03:36:11.344091Z",
"guestActor": {
"guestIdentityId": 12345,
"userProfileId": 67890,
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@example.com",
"phone": "+15550100000"
}
}
Sample CURL
curl -X 'POST' \
'https://AI_PARTNER_URL/webhook' \
-H 'accept: */*'
-H 'Content-Type: application/json' \
-d '{
"event": "lm.notification",
"type": "whatsapp",
"tenantName": "LIKE MAGIC"
"conversationId": "CONVERSATION_ID_LIKEMAGIC",
"messageId": "MESSAGE_ID_LIKEMAGIC",
"pmsReservationId": "PMS_RESERVATION_ID",
"pmsPropertyId": "PMS_PROPERTY_ID",
"content": {
"text": "A template based notification",
"templateName"="CHECKIN_REMINDER",
"language"="DE"
},
"createdAt": "2025-01-14T15:55:59.547Z",
"guestActor": {
"guestIdentityId": 12345,
"userProfileId": 67890,
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@example.com",
"phone": "+15550100000"
}
}'
Human take over
LM informs the AI partner that the conversation is taken over by a human
{
"event": "lm.action",
"type": "HUMAN_TAKE_OVER",
"tenantName": "LIKE MAGIC"
"pmsPropertyId": "PMS_PROPERTY_ID",
"conversationId": "CONVERSATION_ID_LIKEMAGIC"
}
Sample CURL
curl -X 'POST' \
'https://AI_PARTNER_URL/webhook' \
-H 'accept: */*'
-H 'Content-Type: application/json' \
-d '{
"event": "lm.action",
"type": "HUMAN_TAKE_OVER",
"tenantName": "LIKE MAGIC"
"pmsPropertyId": "PMS_PROPERTY_ID",
"conversationId": "CONVERSATION_ID_LIKEMAGIC"
}'
AI take over
LM informs the AI partner that the conversation should be taken over by them
{
"event": "lm.action",
"type": "AI_TAKE_OVER",
"tenantName": "LIKE MAGIC"
"pmsPropertyId": "PMS_PROPERTY_ID",
"conversationId": "CONVERSATION_ID_LIKEMAGIC"
}
Sample CURL
curl -X 'POST' \
'https://AI_PARTNER_URL/webhook' \
-H 'accept: */*'
-H 'Content-Type: application/json' \
-d '{
"event": "lm.action",
"type": "AI_TAKE_OVER",
"tenantName": "LIKE MAGIC"
"pmsPropertyId": "PMS_PROPERTY_ID",
"conversationId": "CONVERSATION_ID_LIKEMAGIC"
}'
Interacting with a guest-conversation
We provide option to do following changes to a guest-conversation
- resolve a conversation
- change the associated pmsPropertyId
both endpoints return the current guest conversation object.
API Reference
For complete API documentation including all endpoints, request/response schemas and interactive testing:
π Unified Messaging API - Live Docs
Integration Certification
Before moving your integration to production, you'll need to complete a certification process with LIKE MAGIC. This ensures your integration meets our quality standards and follows best practices.
Certification Process
- Complete your integration development and testing in the test environment
- Ensure all required endpoints are implemented and working correctly
- Verify error handling and edge cases are properly managed
- Test all message types and interactions thoroughly
Schedule Certification Call
When you're ready to certify your integration: 1. Email api-support@likemagic.tech with subject "Integration Certification Request" 2. Include your test environment tenant name and a brief summary of your integration and the supported use cases 3. Provide your availability for a certification call 4. Our team will review your integration and schedule a certification meeting
During the certification call, we'll verify your integration's functionality and provide any necessary feedback before approving it for production use.