Use the Messaging API to upload, send and retrieve image attachments in existing conversations between guests and properties.
This guide explains how to:
- Upload an image and retrieve its attachment ID.
- Include uploaded images when sending messages.
- Retrieve attachment metadata.
- Download and decode image attachments.
The Messaging API supports image attachments in existing conversations.
Common scenarios include:
| Participant | Examples |
|---|---|
| Guest |
|
| Property |
|
Attachments are associated with an existing conversation, identified by its conversation ID and accommodation ID.
You can obtain these identifiers using /messages/latest or /messages/conversations.
The Messaging API supports attachments in existing conversations only.
You cannot create a new conversation using the attachment endpoints.
Use the following endpoints to manage attachments:
| Endpoint | Description |
|---|---|
| /messages/attachments/upload | Upload a base64-encoded image and retrieve its attachment ID. |
| /messages/attachments/metadata | Retrieve attachment information, including file name, MIME type and size. |
| /messages/attachments/download | Retrieve the base64-encoded content of an attachment. |
| /messages/send | Send a message containing one or more previously uploaded attachment IDs. |
Make sure you have:
- Valid Demand API credentials.
- Your affiliate identifier (
X-Affiliate-Id). - Access to the Messaging API.
- An existing conversation ID and its associated accommodation ID.
- An image that meets the supported file requirements.
All Messaging API requests require Bearer authentication and the X-Affiliate-Id header.
See Authentication for details.
Before uploading an attachment, validate the following requirements:
| Requirement | Description |
|---|---|
| Supported file types | PNG and JPEG images, including .png, .jpg and .jpeg files. |
| MIME type | Use the appropriate MIME type, such as image/png or image/jpeg. |
| Maximum file size | 1,048,576 bytes (1 MiB). |
| File encoding | Base64-encoded file content. |
| File size calculation | The file_size value must represent the original binary file size in bytes, before base64 encoding. |
| Conversation context | Provide the accommodation ID and conversation ID associated with the attachment. |
The 1 MiB limit applies to the original binary file, not the length of its base64-encoded representation.
Base64 encoding increases the size of the transmitted data. Always calculate file_size from the original file before encoding it.
→ Use /messages/attachments/upload to upload an image to an existing conversation.
The endpoint accepts the image as a base64-encoded string and returns an attachment ID.
Before uploading:
- Verify that the file is a supported PNG or JPEG image.
- Check that its original size does not exceed 1,048,576 bytes.
- Encode the file content in base64.
- Record the original file name, MIME type and binary file size.
You can encode the image locally using your preferred programming language or command-line tool.
For example, using Python:
import base64
from pathlib import Path
file_path = Path("example_image.png")
file_bytes = file_path.read_bytes()
file_size = len(file_bytes)
file_content = base64.b64encode(file_bytes).decode("ascii")
print("File size:", file_size)
print("Base64 content:", file_content)Use the resulting values in the upload request:
file_size: Original file size in bytes.file_content: Base64-encoded image content.
Encode attachments locally or within your application. Avoid using third-party encoding services for images containing guest information or other sensitive content.
Send a POST request to /messages/attachments/upload.
Request
POST messages/attachments/upload
The request requires the following fields:
| Field | Description |
|---|---|
accommodation | Unique identifier of the property associated with the conversation. |
conversation | Unique identifier of the existing conversation. |
file_name | Original file name, including its extension. |
file_type | MIME type of the image. |
file_size | Original binary file size in bytes. |
file_content | Base64-encoded content of the image. |
Example request
{
"accommodation": "6819547",
"conversation": "cc872746-77f2-5886-ba7c-17e0497241b5",
"file_name": "example_image.png",
"file_type": "image/png",
"file_size": 35,
"file_content": "iVBORw0KGgoAAAANSUhEUgAAADAAAABAgMAAADW0NTUAAAA"
}The file_content value above is an illustrative, shortened base64 string. In a real request, provide the complete encoded image and its actual binary size.
Example response
{
"request_id": "25539c17-59e6-4465-ad85-d0a517a474c5",
"data": {
"attachment": "c82a5350-19fe-11f0-959e-1373654fdef5"
}
}A successful request returns HTTP 200 OK.
The data.attachment field contains the unique identifier of the uploaded attachment.
Save this ID. You'll need it to send the attachment, retrieve its metadata or download it.
The image has been uploaded successfully.
To make it part of a message, include its attachment ID in a subsequent /messages/send request.
Uploading an image does not automatically send it to the guest or property.
→ Use /messages/send to send a message containing the uploaded attachment.
Request
POST /messages/send
Include the attachment ID in the attachments array.
{
"accommodation": "6819547",
"conversation": "cc872746-77f2-5886-ba7c-17e0497241b5",
"content": "Please see the attached image.",
"attachments": [
"c82a5350-19fe-11f0-959e-1373654fdef5"
]
}Example response
{
"request_id": "cdb0b154-2eae-481b-8fee-fb2725296e1f",
"data": {
"message": "3164e570-19e0-11f0-baca-e5019c8df435"
}
}The response returns the ID of the newly sent message.
To include multiple images in one message:
- Upload each image separately using /messages/attachments/upload.
- Collect the attachment IDs returned by the API.
- Include those IDs in the
attachmentsarray of the /messages/send request.
For example:
{
"accommodation": "6819547",
"conversation": "cc872746-77f2-5886-ba7c-17e0497241b5",
"content": "Here are the images you requested.",
"attachments": [
"c82a5350-19fe-11f0-959e-1373654fdef5",
"695b7f90-2c08-11f0-9cee-134ca9b067d1"
]
}For more information about sending messages, see Manage messages.
→ Use /messages/attachments/metadata to retrieve information about an existing attachment.
The endpoint returns the file name, MIME type and size.
Request
POST /messages/attachments/metadata
Provide the accommodation, conversation and attachment identifiers.
{
"accommodation": "6819547",
"conversation": "cc872746-77f2-5886-ba7c-17e0497241b5",
"attachment": "c82a5350-19fe-11f0-959e-1373654fdef5"
}Example response
{
"request_id": "4cf641d4-dc42-4970-a1e6-8f7fb6c8785f",
"data": {
"metadata": {
"file_size": 95299,
"file_name": "example_image.png",
"file_type": "image/png"
}
}
}The response contains:
| Field | Description |
|---|---|
data.metadata.file_size | Size of the attachment in bytes. |
data.metadata.file_name | Original file name. |
data.metadata.file_type | MIME type of the attachment. |
The metadata response contains basic file information only. It does not include the attachment's binary content.
Use /messages/attachments/download to retrieve the file content.
→ Use /messages/attachments/download to retrieve the content of an attachment associated with an existing conversation.
The API returns the file content as a base64-encoded string.
Request
POST /messages/attachments/download
{
"accommodation": "6819547",
"conversation": "cc872746-77f2-5886-ba7c-17e0497241b5",
"attachment": "c82a5350-19fe-11f0-959e-1373654fdef5"
}Example response
{
"request_id": "773e2c0d-1ab3-449b-b88a-3d6b5ce09ae7",
"data": {
"conversation": "cc872746-77f2-5886-ba7c-17e0497241b5",
"file_content": "/9j/4AAQSkZJRgABAQACWAJYAAD/2wCEAAgGBgc...",
"attachment": "c82a5350-19fe-11f0-959e-1373654fdef5"
}
}The response contains:
| Field | Description |
|---|---|
data.conversation | Identifier of the conversation associated with the attachment. |
data.attachment | Unique identifier of the downloaded attachment. |
data.file_content | Base64-encoded content of the attachment. |
The file_content value in this example is shortened for readability.
Decode the base64 string to restore the original image.
For example, using Python:
import base64
from pathlib import Path
encoded_content = response["data"]["file_content"]
file_bytes = base64.b64decode(encoded_content)
Path("downloaded_image.jpg").write_bytes(file_bytes)In this example, response represents the parsed JSON response returned by /messages/attachments/download.
Use the file name and MIME type returned by /messages/attachments/metadata to determine the appropriate file extension and how to handle the downloaded content.
Treat downloaded attachments as untrusted content.
Validate the file type and apply your application's security checks before storing, displaying or processing the file.
If an attachment request fails, validate the request fields and file requirements before retrying.
| Issue | Possible cause | Recommended action |
|---|---|---|
| File exceeds the maximum size | The original image is larger than 1,048,576 bytes. | Resize or compress the image before encoding and uploading it. |
| File size mismatch | file_size does not match the decoded binary content. | Calculate the original file size before base64 encoding and use that value in the request. |
| Unsupported file type | The file is not a supported PNG or JPEG image. | Convert the file to a supported format and use the appropriate MIME type. |
| Invalid base64 content | The encoded string is incomplete or incorrectly formatted. | Re-encode the original image and submit the complete base64 string. |
| Attachment cannot be retrieved | The attachment, conversation or accommodation identifier is incorrect. | Verify that all identifiers refer to the same conversation and attachment. |
| Authentication failure | The request uses invalid credentials or an incorrect affiliate identifier. | Verify the Bearer token, X-Affiliate-Id and API access. |
| Rate limit exceeded | Too many requests have been submitted. | Follow the applicable rate-limit guidance and retry according to the API response. |
For general error-handling guidance, see HTTP 4xx scenarios.
The following request declares a file size of 350 bytes, but the supplied base64 content does not represent a file of that size.
{
"accommodation": "6819547",
"conversation": "cc872746-77f2-5886-ba7c-17e0497241b5",
"file_content": "iVBORw0KGgoAAAANSUhEUgAAADAAAABAgMAAADW0NTUAAAA",
"file_name": "example_image.png",
"file_type": "image/png",
"file_size": 350
}If the API validates the declared file size against the decoded content, the mismatch can cause the request to fail.
To resolve the issue:
- Check that the base64 content is complete.
- Decode the content or inspect the original binary file to determine its actual size.
- Update
file_sizeto match the original binary size. - Retry the upload with valid file content and metadata.
Do not use the length of the base64 string as the value of file_size. The field must contain the size of the original binary file in bytes.
Follow these recommendations when managing attachments:
✅ Validate before uploading: Check the image format, MIME type and original file size before encoding.
✅ Use the correct conversation context: Include the accommodation and conversation identifiers associated with the attachment.
✅ Store attachment IDs: Retain the identifiers needed to send messages and retrieve attachments.
✅ Handle base64 securely: Avoid logging or exposing encoded file content, as it contains the complete attachment data.
✅ Process downloaded files safely: Validate downloaded content before storing or displaying it.
✅ Follow data-protection requirements: Apply appropriate access controls and retention policies to stored attachments.
✅ Handle errors appropriately: Validate requests before retrying and follow the applicable API rate limits.
- Messaging API quick guide – Test the Messaging API using the Demand API Messaging Test Hotel.
- Manage messages – Learn how to retrieve conversations, send messages and confirm receipt.
- Messaging best practices – Review recommendations for reliable messaging integrations.