Sending Media Messages
Complete guide to sending images, videos, documents, and other media through WhatsApp Business API. Learn how to enhance your messaging with rich media content.
What You'll Learn
- • How to send different types of media messages
- • File size and format requirements
- • Media upload and storage best practices
- • Error handling for media messages
- • Advanced media features and capabilities
Supported Media Types
WhatsApp Business API supports various media types to enhance your messaging capabilities. Each type has specific requirements and use cases.
Images
Supported Formats
JPG, JPEG, PNG, GIF (static)
Max Size
5 MB
Use Cases
Product photos, screenshots, infographics
Videos
Supported Formats
MP4, 3GPP, MOV
Max Size
16 MB
Use Cases
Product demos, tutorials, marketing content
Documents
Supported Formats
PDF, DOC, DOCX, PPT, PPTX, XLS, XLSX
Max Size
100 MB
Use Cases
Invoices, contracts, reports, presentations
Audio
Supported Formats
AAC, M4A, AMR, MP3, OGG
Max Size
16 MB
Use Cases
Voice messages, audio notes, music
Media Upload Process
Sending media messages involves a two-step process: uploading the media file and then sending the message with a reference to the uploaded media.
Step 1: Upload Media
curl -X POST "https://api.cmzon.com/v1/media" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -F "file=@/path/to/your/image.jpg" \ -F "type=image/jpeg"
Prepare Your File
Ensure your media file meets the size and format requirements for the media type.
Upload to CMzon
Use the media upload endpoint to upload your file. You'll receive a media ID in response.
Store Media ID
Save the media ID returned from the upload response. You'll use this to send the message.
Step 2: Send Media Message
curl -X POST "https://api.cmzon.com/v1/messages" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": "+1234567890",
"type": "image",
"image": {
"id": "MEDIA_ID_FROM_UPLOAD",
"caption": "Check out this amazing product!"
}
}'Media ID Usage
Media IDs are valid for 30 days and can be reused multiple times. This allows you to send the same media to different recipients without re-uploading.
Implementation Examples
Node.js Example
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
class CMzonMediaAPI {
constructor(apiToken) {
this.apiToken = apiToken;
this.baseURL = 'https://api.cmzon.com/v1';
}
async uploadMedia(filePath, mediaType) {
const form = new FormData();
form.append('file', fs.createReadStream(filePath));
form.append('type', mediaType);
try {
const response = await axios.post(`${this.baseURL}/media`, form, {
headers: {
...form.getHeaders(),
'Authorization': `Bearer ${this.apiToken}`
}
});
return response.data.id;
} catch (error) {
throw new Error(`Media upload failed: ${error.message}`);
}
}
async sendImageMessage(to, mediaId, caption = '') {
try {
const response = await axios.post(`${this.baseURL}/messages`, {
to: to,
type: 'image',
image: {
id: mediaId,
caption: caption
}
}, {
headers: {
'Authorization': `Bearer ${this.apiToken}`,
'Content-Type': 'application/json'
}
});
return response.data;
} catch (error) {
throw new Error(`Message send failed: ${error.message}`);
}
}
async sendMediaMessage(to, filePath, mediaType, caption = '') {
// Upload media first
const mediaId = await this.uploadMedia(filePath, mediaType);
// Send message with media
const messageType = this.getMediaMessageType(mediaType);
return await this.sendMessage(to, mediaId, messageType, caption);
}
getMediaMessageType(mediaType) {
if (mediaType.startsWith('image/')) return 'image';
if (mediaType.startsWith('video/')) return 'video';
if (mediaType.startsWith('audio/')) return 'audio';
return 'document';
}
}
// Usage
const api = new CMzonMediaAPI(process.env.CMZON_API_TOKEN);
// Send an image
api.sendMediaMessage('+1234567890', './product.jpg', 'image/jpeg', 'Check out our new product!')
.then(result => console.log('Image sent:', result))
.catch(error => console.error('Error:', error.message));Python Example
import requests
import os
from typing import Dict, Any, Optional
class CMzonMediaAPI:
def __init__(self, api_token: str):
self.api_token = api_token
self.base_url = 'https://api.cmzon.com/v1'
self.headers = {
'Authorization': f'Bearer {api_token}'
}
def upload_media(self, file_path: str, media_type: str) -> str:
"""Upload media file and return media ID"""
url = f'{self.base_url}/media'
with open(file_path, 'rb') as file:
files = {'file': file}
data = {'type': media_type}
try:
response = requests.post(url, files=files, data=data, headers=self.headers)
response.raise_for_status()
return response.json()['id']
except requests.exceptions.RequestException as e:
raise Exception(f"Media upload failed: {e}")
def send_media_message(self, to: str, media_id: str,
message_type: str, caption: str = '') -> Dict[str, Any]:
"""Send media message using uploaded media ID"""
url = f'{self.base_url}/messages'
# Determine message structure based on type
message_data = {
'to': to,
'type': message_type
}
if message_type == 'image':
message_data['image'] = {'id': media_id, 'caption': caption}
elif message_type == 'video':
message_data['video'] = {'id': media_id, 'caption': caption}
elif message_type == 'audio':
message_data['audio'] = {'id': media_id}
elif message_type == 'document':
message_data['document'] = {'id': media_id, 'caption': caption}
try:
response = requests.post(url, json=message_data, headers=self.headers)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
raise Exception(f"Message send failed: {e}")
def send_file_message(self, to: str, file_path: str,
media_type: str, caption: str = '') -> Dict[str, Any]:
"""Complete flow: upload media and send message"""
# Upload media
media_id = self.upload_media(file_path, media_type)
# Determine message type
message_type = self.get_media_message_type(media_type)
# Send message
return self.send_media_message(to, media_id, message_type, caption)
def get_media_message_type(self, media_type: str) -> str:
"""Determine WhatsApp message type from media type"""
if media_type.startswith('image/'):
return 'image'
elif media_type.startswith('video/'):
return 'video'
elif media_type.startswith('audio/'):
return 'audio'
else:
return 'document'
# Usage
api = CMzonMediaAPI(os.getenv('CMZON_API_TOKEN'))
try:
# Send an image
result = api.send_file_message(
to='+1234567890',
file_path='./product.jpg',
media_type='image/jpeg',
caption='Check out our new product!'
)
print(f"Message sent: {result}")
except Exception as e:
print(f"Error: {e}")Best Practices
File Optimization
Image Optimization
- • Compress images to reduce file size
- • Use appropriate dimensions (max 4096x4096)
- • Choose JPEG for photos, PNG for graphics
- • Consider WebP for better compression
Video Optimization
- • Use H.264 codec for best compatibility
- • Optimize bitrate for file size
- • Consider duration (shorter is better)
- • Use appropriate resolution (720p max)
User Experience
Caption Guidelines
- • Keep captions concise and relevant
- • Use captions to provide context
- • Include call-to-action when appropriate
- • Avoid spammy or promotional language
Media Selection
- • Choose high-quality, relevant media
- • Ensure media is appropriate for your audience
- • Test media on different devices
- • Consider loading times for users
Error Handling
Common Media Errors
File Too Large
Media file exceeds size limits. Check file size and compress if necessary.
{
"error": {
"code": 400,
"message": "File size exceeds limit",
"details": "Image must be less than 5MB"
}
}Unsupported Format
Media format is not supported. Convert to a supported format.
{
"error": {
"code": 400,
"message": "Unsupported media format",
"details": "Only JPG, PNG, GIF are supported for images"
}
}Media Not Found
Media ID is invalid or expired. Re-upload the media file.
{
"error": {
"code": 400,
"message": "Media not found",
"details": "Media ID is invalid or has expired"
}
}Retry Logic
Implement proper retry logic for media uploads and message sending.
// Example retry logic
async function uploadMediaWithRetry(filePath, mediaType, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await uploadMedia(filePath, mediaType);
} catch (error) {
if (attempt === maxRetries) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
}
}
}Need Help with Media?
Our support team can help you implement media messaging and resolve any issues you encounter.