Skip to main content

πŸ–ΌοΈ Send Image Messages

Send stunning images with captions to WhatsApp contacts using the enhanced Whatspie API with support for various formats and advanced delivery options.

πŸ“Έ Rich Media Support

Upload images directly from URLs with automatic optimization, caption support, and typing simulation for a natural conversation experience.

🌐 Endpoint​

POST https://api.whatspie.com/messages

πŸ” Authentication​

Bearer token required with proper JSON content headers.

πŸ“‹ Request Parameters​

ParameterTypeRequiredDescription
devicestringβœ…Your registered WhatsApp device number
receiverstringβœ…Recipient's phone number (international format)
typestringβœ…Message type: "image" for image messages
paramsobjectβœ…Message parameters containing image data
params.imageobjectβœ…Image object with URL
params.image.urlstringβœ…Direct URL to the image file
params.captionstring❌Image caption text (supports formatting)
params.viewOnceboolean❌Whether image should be viewable only once
simulate_typinginteger❌Show typing indicator: 1 (yes) or 0 (no)

🎨 Supported Image Formats​

πŸ“· JPEG/JPG
Most compatible format
πŸ–ΌοΈ PNG
Transparency support
🎞️ GIF
Animated images
πŸš€ WebP
Modern format

πŸ“ Image Requirements​

  • Maximum file size: 16MB
  • Recommended dimensions: Up to 1600x1600 pixels
  • File accessibility: Must be publicly accessible via direct URL
  • Upload time: Images are automatically optimized for WhatsApp

πŸš€ Request Examples​

Basic Image Message​

curl -X POST "https://api.whatspie.com/messages" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"device": "6281234567890",
"receiver": "6289876543210",
"type": "image",
"params": {
"image": {
"url": "https://example.com/images/photo.jpg"
},
"caption": "Check out this amazing photo! πŸ“Έβœ¨"
},
"simulate_typing": 1
}'

Image with Rich Caption​

curl -X POST "https://api.whatspie.com/messages" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"device": "6281234567890",
"receiver": "6289876543210",
"type": "image",
"params": {
"image": {
"url": "https://example.com/products/headphones.jpg"
},
"caption": "πŸŽ‰ *NEW PRODUCT ALERT* πŸŽ‰\n\n_Premium Quality Headphones_\n\nβœ… Noise Cancellation\nβœ… 30h Battery Life\nβœ… Fast Charging\n\n*Special Price: $199*\n~~Original: $299~~"
},
"simulate_typing": 1
}'

Image Without Caption​

curl -X POST "https://api.whatspie.com/messages" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"device": "6281234567890",
"receiver": "6289876543210",
"type": "image",
"params": {
"image": {
"url": "https://example.com/images/screenshot.png"
}
},
"simulate_typing": 1
}'

πŸ“Š Response Format​

Success Response​

{
"code": 200,
"message": "Image sent successfully",
"data": {
"id": "msg_image_12345",
"status": "pending",
"type": "image",
"device": "6281234567890",
"receiver": "6289876543210",
"file_url": "https://example.com/images/photo.jpg",
"message": "Check out this amazing photo! πŸ“Έβœ¨",
"simulate_typing": 1,
"timestamp": "2024-12-20T10:30:00Z"
}
}

Response Fields​

FieldTypeDescription
idstringUnique message identifier
statusstringMessage status (pending, sent, delivered, failed)
typestringMessage type (image)
devicestringSender device number
receiverstringRecipient's phone number
file_urlstringURL of the sent image
messagestringImage caption (if provided)
simulate_typingintegerTyping simulation setting (1 or 0)
timestampstringMessage sent timestamp (ISO 8601)

Error Responses​

Invalid Image URL​

{
"code": 400,
"message": "Invalid image URL",
"error": "The provided image URL is not accessible or invalid"
}

Unsupported Image Format​

{
"code": 400,
"message": "Unsupported file format",
"error": "Only JPEG, PNG, GIF, and WebP images are supported"
}

Image Too Large​

{
"code": 400,
"message": "File too large",
"error": "Image size exceeds 16MB limit"
}

URL Not Accessible​

{
"code": 400,
"message": "Unable to download image",
"error": "The image URL is not publicly accessible"
}

Advanced Examples​

Image with Formatting in Caption​

async function sendProductImage() {
const caption = `πŸŽ‰ *NEW PRODUCT ALERT* πŸŽ‰

_Premium Wireless Headphones_

βœ… Noise Cancellation
βœ… 30-hour Battery Life
βœ… Fast Charging
βœ… Premium Sound Quality

~~$299~~ *$199* (33% OFF)

Use code: *SAVE100*
Valid until: December 31st

Order now: https://shop.example.com`;

await sendImageMessage(
'YOUR_JWT_TOKEN',
'1234567890',
'https://example.com/headphones.jpg',
caption,
'headphones-promo.jpg'
);
}

Batch Image Sending​

async function sendImageCatalog(token, phoneNumber, products) {
const results = [];

for (const product of products) {
try {
const caption = `${product.name}\nPrice: $${product.price}\n${product.description}`;

const result = await sendImageMessage(
token,
phoneNumber,
product.imageUrl,
caption,
`${product.id}.jpg`
);

results.push({
product: product.name,
success: true,
messageId: result.data.id
});

// Delay between messages to avoid rate limiting
await new Promise(resolve => setTimeout(resolve, 2000));

} catch (error) {
results.push({
product: product.name,
success: false,
error: error.message
});
}
}

return results;
}

// Usage
const products = [
{
id: 'p001',
name: 'Wireless Headphones',
price: 199,
description: 'Premium quality with noise cancellation',
imageUrl: 'https://example.com/headphones.jpg'
},
{
id: 'p002',
name: 'Smart Watch',
price: 299,
description: 'Track your fitness and stay connected',
imageUrl: 'https://example.com/smartwatch.jpg'
}
];

const results = await sendImageCatalog('YOUR_JWT_TOKEN', '1234567890', products);
console.log('Catalog sent:', results);

Image URL Validation​

function isValidImageUrl(url) {
try {
const urlObj = new URL(url);

// Check if it's HTTP/HTTPS
if (!['http:', 'https:'].includes(urlObj.protocol)) {
return false;
}

// Check for common image extensions
const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp'];
const hasImageExtension = imageExtensions.some(ext =>
urlObj.pathname.toLowerCase().includes(ext)
);

return hasImageExtension;
} catch {
return false;
}
}

async function sendValidatedImage(token, phoneNumber, imageUrl, caption) {
if (!isValidImageUrl(imageUrl)) {
throw new Error('Invalid image URL format');
}

return await sendImageMessage(token, phoneNumber, imageUrl, caption);
}

Download and Upload Helper​

If you need to upload images from your local server:

const fs = require('fs');
const FormData = require('form-data');

// Example function to upload image to your CDN/storage
async function uploadImageToCDN(filePath) {
// This is pseudo-code - implement according to your storage solution
const formData = new FormData();
formData.append('file', fs.createReadStream(filePath));

const response = await axios.post('https://your-cdn.com/upload', formData, {
headers: formData.getHeaders()
});

return response.data.url; // Returns public URL
}

// Send local image
async function sendLocalImage(token, phoneNumber, localFilePath, caption) {
try {
// Upload to CDN first
const publicUrl = await uploadImageToCDN(localFilePath);

// Send via WhatsApp
return await sendImageMessage(token, phoneNumber, publicUrl, caption);
} catch (error) {
console.error('Error sending local image:', error);
throw error;
}
}

Best Practices​

1. Image Optimization​

// Check image size before sending
async function getImageSize(url) {
try {
const response = await fetch(url, { method: 'HEAD' });
const contentLength = response.headers.get('content-length');
return contentLength ? parseInt(contentLength) : null;
} catch {
return null;
}
}

async function sendOptimizedImage(token, phoneNumber, imageUrl, caption) {
const size = await getImageSize(imageUrl);
const maxSize = 16 * 1024 * 1024; // 16MB

if (size && size > maxSize) {
throw new Error(`Image too large: ${size} bytes. Maximum allowed: ${maxSize} bytes`);
}

return await sendImageMessage(token, phoneNumber, imageUrl, caption);
}

2. CDN Usage​

Use a reliable CDN for hosting images:

const CDN_BASE_URL = 'https://your-cdn.com/images/';

function getCDNImageUrl(fileName) {
return `${CDN_BASE_URL}${fileName}`;
}

async function sendCDNImage(token, phoneNumber, fileName, caption) {
const imageUrl = getCDNImageUrl(fileName);
return await sendImageMessage(token, phoneNumber, imageUrl, caption);
}

3. Error Handling and Retries​

async function sendImageWithRetry(token, phoneNumber, imageUrl, caption, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await sendImageMessage(token, phoneNumber, imageUrl, caption);
} catch (error) {
if (error.response?.status === 400 && error.response?.data?.error?.includes('URL')) {
// Don't retry URL-related errors
throw error;
}

if (attempt === maxRetries) {
throw error;
}

const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}

Common Use Cases​

E-commerce Product Images​

async function sendProductUpdate(token, customerPhone, product) {
const caption = `πŸ›οΈ *${product.name}*

πŸ’° Price: $${product.price}
πŸ“¦ Stock: ${product.stock > 0 ? 'Available' : 'Out of Stock'}
⭐ Rating: ${product.rating}/5

${product.description}

πŸ›’ Order: ${product.orderUrl}`;

return await sendImageMessage(
token,
customerPhone,
product.imageUrl,
caption,
`${product.sku}.jpg`
);
}

Event Invitations​

async function sendEventInvitation(token, guestPhone, event) {
const caption = `πŸŽ‰ You're Invited! πŸŽ‰

*${event.title}*

πŸ“… Date: ${event.date}
⏰ Time: ${event.time}
πŸ“ Venue: ${event.venue}

${event.description}

RSVP: ${event.rsvpUrl}`;

return await sendImageMessage(
token,
guestPhone,
event.bannerUrl,
caption,
'event-invitation.jpg'
);
}

Limitations​

  • File size: Maximum 16MB per image
  • Formats: JPEG, PNG, GIF, WebP only
  • URL accessibility: Images must be publicly accessible
  • Rate limits: Follow WhatsApp's messaging limits

Next Steps​