Appearance
WhatsApp Messaging API Documentation
The WhatsApp Messaging API allows your applications to programmatically send WhatsApp messages to your customers. This API supports sending text messages, media files, and template messages while providing message tracking and delivery status updates.
Base URL
https://api.talkingshops.com/v1
Authentication
All API requests (except webhooks) require authentication using an API key. Include your API key in the request header:
x-tenant-api-key: your_api_key_here
API keys are tenant-specific and can be generated through the Talking Shops Dashboard.
Rate Limiting
The API implements rate limiting to prevent abuse. By default, each tenant is limited to 100 requests per minute. When you exceed this limit, the API will respond with a 429 status code.
Endpoints
Message Endpoints
Send a Text Message
POST /messages/text
Send a simple text message to a WhatsApp recipient.
Request
json
{
"recipient": "919876543210",
"message": "Hello! This is a test message from Talking Shops.",
"reference_id": "order_123" // optional
}
Response (202 Accepted)
json
{
"message_id": "msg_ABC123XYZ",
"status": "pending",
"timestamp": "2023-06-21T14:35:12Z"
}
Send a Media Message
POST /messages/media
Send an image, video, document, or audio file to a WhatsApp recipient.
Request
json
{
"recipient": "919876543210",
"media_type": "image", // "image", "video", "document", or "audio"
"media_url": "https://example.com/images/product.jpg",
"caption": "Check out our new product!", // optional
"reference_id": "product_launch_456" // optional
}
Response (202 Accepted)
json
{
"message_id": "msg_DEF456UVW",
"status": "pending",
"timestamp": "2023-06-21T15:40:22Z"
}
Send a Template Message
POST /messages/template
Send a pre-approved message template with dynamic content.
Request
json
{
"recipient": "919876543210",
"template_name": "order_confirmation",
"language_code": "en_US",
"components": [
{
"type": "header",
"parameters": [
{
"type": "image",
"image": {
"link": "https://example.com/images/logo.jpg"
}
}
]
},
{
"type": "body",
"parameters": [
{
"type": "text",
"text": "John Doe"
},
{
"type": "text",
"text": "12345"
},
{
"type": "currency",
"currency": {
"code": "USD",
"amount": 100.50
}
}
]
}
],
"reference_id": "order_conf_789" // optional
}
Response (202 Accepted)
json
{
"message_id": "msg_GHI789RST",
"status": "pending",
"timestamp": "2023-06-21T16:45:33Z"
}
Send Authentication Template Message
POST /messages/authentication-template
Authentication templates are specialized WhatsApp templates designed to send one-time passwords (OTP) and verification codes to users. They provide enhanced security features and better user experience compared to regular text messages.
Important: Authentication templates must be created first using the WhatsApp Business Management API (one-time setup). The button type (copy_code, one_tap, zero_tap) is configured during template creation.
Key Features
- Linked Device Security: Authentication messages are only delivered to a user's primary WhatsApp device
- Multiple Button Types: Support for one-tap autofill, copy code, and zero-tap authentication
- Security Recommendations: Optional security warning text
- Code Expiration: Configurable expiration times (1-90 minutes)
- Android App Integration: Deep integration with Android apps for seamless user experience
Quick Reference: Button Types
Button Type | Platform | User Experience | Setup Complexity | Use Case |
---|---|---|---|---|
Copy Code | All platforms | User taps to copy code to clipboard | ✅ Simple | Universal compatibility |
One-Tap | Android (fallback: copy code) | Automatically opens your app with code | 🔶 Medium | Enhanced Android UX |
Zero-Tap | Android (fallback: one-tap/copy) | Code appears automatically in app | 🔴 Complex | Invisible authentication |
Platform Compatibility Matrix
Feature | Android | iOS | Web WhatsApp | WhatsApp Desktop |
---|---|---|---|---|
Copy Code | ✅ | ✅ | ✅ | ✅ |
One-Tap | ✅ | ❌ (fallback to copy) | ❌ (fallback to copy) | ❌ (fallback to copy) |
Zero-Tap | ✅ | ❌ (fallback to one-tap) | ❌ (fallback to one-tap) | ❌ (fallback to one-tap) |
Request
json
{
"recipient": "919876543210",
"template_name": "auth_code_template",
"language_code": "en_US",
"code": "123456",
"reference_id": "auth-123456"
}
Note: The components
field is optional and used for API validation only. The actual button behavior is determined by how the template was created in WhatsApp Business Manager.
Examples by Template Type
Copy Code Template:
json
{
"recipient": "919876543210",
"template_name": "auth_copy_code",
"language_code": "en_US",
"code": "567890",
"reference_id": "auth-567890-copy"
}
One-Tap Autofill Template:
json
{
"recipient": "919876543210",
"template_name": "auth_one_tap",
"language_code": "en_US",
"code": "789012",
"components": {
"buttons": {
"otp_type": "one_tap",
"supported_apps": [
{
"package_name": "com.example.myapp",
"signature_hash": "K8a/AINcGX7"
}
]
}
},
"reference_id": "auth-789012-onetap"
}
Zero-Tap Template:
json
{
"recipient": "919876543210",
"template_name": "auth_zero_tap",
"language_code": "en_US",
"code": "345678",
"components": {
"buttons": {
"otp_type": "zero_tap",
"zero_tap_terms_accepted": true,
"supported_apps": [
{
"package_name": "com.example.myapp",
"signature_hash": "K8a/AINcGX7"
}
]
}
},
"reference_id": "auth-345678-zerotap"
}
Request Parameters
Required Parameters:
Parameter | Type | Description |
---|---|---|
recipient | string | Recipient phone number (10-15 digits) |
template_name | string | Name of the authentication template (must exist in WhatsApp Business Manager) |
language_code | string | Language code (e.g., en_US) |
code | string | The OTP/verification code to send (1-15 characters) |
Optional Parameters:
Parameter | Type | Description |
---|---|---|
reference_id | string | Custom reference ID for tracking |
components | object | Optional validation object for API validation only |
Android App Integration
Calculating App Signature Hash:
To use one-tap or zero-tap authentication, you need your Android app's signature hash:
Using Google's Method: Follow Google's instructions
Using Shell Script: Download and use the sms_retriever_hash_v9.sh script:
bash./sms_retriever_hash_v9.sh --package "com.example.myapp" --keystore ~/.android/debug.keystore
Package Name Requirements:
- Must have at least two segments (contain dots)
- Each segment must start with a letter
- Only alphanumeric characters and underscores allowed
- Maximum 224 characters
Multiple Apps Support:
json
"supported_apps": [
{
"package_name": "com.mycompany.myapp",
"signature_hash": "K8a/AINcGX7"
},
{
"package_name": "com.mycompany.myapp.debug",
"signature_hash": "L9b/BIOdHY8"
}
]
Response (202 Accepted)
json
{
"message_id": "uuid-generated-id",
"status": "queued",
"timestamp": "2024-12-06T12:34:56Z"
}
Common Errors
Error Code | Description | Solution |
---|---|---|
TEMPLATE_NOT_FOUND | Authentication template doesn't exist | Create the template first |
INVALID_SIGNATURE_HASH | Signature hash format is incorrect | Verify hash is exactly 11 characters |
INVALID_PACKAGE_NAME | Package name format is invalid | Check package name requirements |
ZERO_TAP_TERMS_NOT_ACCEPTED | Terms not accepted for zero-tap | Set zero_tap_terms_accepted: true |
INVALID_OTP_TYPE | Unknown OTP button type | Use copy_code, one_tap, or zero_tap |
Best Practices
Security:
- Never log or store verification codes in plain text
- Use HTTPS for all API communications
- Implement rate limiting on your authentication endpoints
- Validate codes server-side before accepting them
- Use appropriate expiration times (5-15 minutes recommended)
User Experience:
- Start with copy code templates for maximum compatibility
- Implement one-tap for Android users when possible
- Consider zero-tap only for high-security applications
- Always include security recommendations for sensitive operations
- Use clear, branded template names
Template Management:
- Create templates in all required languages
- Test templates thoroughly before production use
- Monitor template approval status
- Keep template names consistent across languages
- Document your template naming convention
Send a Product List Message
POST /messages/product-list
Send a list of products from the WhatsApp catalog.
json
{
"recipient": "1234567890",
"product_list": {
"catalog_id": "your_catalog_id",
"text": "Check out our latest products:",
"product_items": [
{
"product_retailer_id": "product_001"
},
{
"product_retailer_id": "product_002"
}
]
}
}
Response (202 Accepted)
json
{
"message_id": "msg_GHI789RST",
"status": "pending",
"timestamp": "2023-06-21T16:45:33Z"
}
Interactive List Messages
Interactive List Messages allow you to present multiple options to users in an organized, scrollable list format.
Endpoint
POST /v1/messages/interactive/list
Request Schema
json
{
"recipient": "1234567890",
"header": {
"type": "text",
"text": "Choose an option"
},
"body": {
"text": "Please select from the following options:"
},
"footer": {
"text": "Powered by TalkingShops"
},
"action": {
"button": "View Options",
"sections": [
{
"title": "Main Categories",
"rows": [
{
"id": "option_1",
"title": "Option 1",
"description": "Description for option 1"
},
{
"id": "option_2",
"title": "Option 2",
"description": "Description for option 2"
}
]
}
]
},
"reference_id": "list_msg_001"
}
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
recipient | string | Yes | Recipient phone number (10-15 digits) |
header | object | No | Optional header section |
header.type | string | Yes* | Must be "text" |
header.text | string | Yes* | Header text (max 60 characters) |
body | object | Yes | Main message content |
body.text | string | Yes | Body text (1-1024 characters) |
footer | object | No | Optional footer section |
footer.text | string | Yes* | Footer text (max 60 characters) |
action | object | Yes | List action configuration |
action.button | string | Yes | Button text (max 20 characters) |
action.sections | array | Yes | List sections (1-10 sections) |
reference_id | string | No | Custom reference ID for tracking |
Section Object
Parameter | Type | Required | Description |
---|---|---|---|
title | string | Yes | Section title (max 24 characters) |
rows | array | Yes | List rows (1-10 rows per section) |
Row Object
Parameter | Type | Required | Description |
---|---|---|---|
id | string | Yes | Unique row ID (max 200 characters) |
title | string | Yes | Row title (max 24 characters) |
description | string | No | Row description (max 72 characters) |
Constraints
- Maximum 10 sections per message
- Maximum 10 rows per section
- Maximum 10 total rows across all sections
- Row IDs must be unique across all sections
Interactive Button Messages
Interactive Button Messages allow you to present up to 3 quick reply buttons for immediate user responses.
Endpoint
POST /v1/messages/interactive/button
Request Schema
json
{
"recipient": "1234567890",
"header": {
"type": "text",
"text": "Quick Question"
},
"body": {
"text": "Would you like to continue with your order?"
},
"footer": {
"text": "Choose an option below"
},
"action": {
"buttons": [
{
"type": "reply",
"reply": {
"id": "yes_continue",
"title": "Yes, Continue"
}
},
{
"type": "reply",
"reply": {
"id": "no_cancel",
"title": "No, Cancel"
}
},
{
"type": "reply",
"reply": {
"id": "need_help",
"title": "Need Help"
}
}
]
},
"reference_id": "button_msg_001"
}
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
recipient | string | Yes | Recipient phone number (10-15 digits) |
header | object | No | Optional header section |
body | object | Yes | Main message content |
body.text | string | Yes | Body text (1-1024 characters) |
footer | object | No | Optional footer section |
footer.text | string | Yes* | Footer text (max 60 characters) |
action | object | Yes | Button action configuration |
action.buttons | array | Yes | Reply buttons (1-3 buttons) |
reference_id | string | No | Custom reference ID for tracking |
Header Types
Interactive Button Messages support multiple header types:
Text Header
json
{
"type": "text",
"text": "Header text (max 60 characters)"
}
Image Header
json
{
"type": "image",
"image": {
"link": "https://example.com/image.jpg"
}
}
Video Header
json
{
"type": "video",
"video": {
"link": "https://example.com/video.mp4"
}
}
Document Header
json
{
"type": "document",
"document": {
"link": "https://example.com/document.pdf",
"filename": "document.pdf"
}
}
Button Object
Parameter | Type | Required | Description |
---|---|---|---|
type | string | Yes | Must be "reply" |
reply | object | Yes | Reply button configuration |
reply.id | string | Yes | Unique button ID (max 256 characters) |
reply.title | string | Yes | Button title (max 20 characters) |
Constraints
- Maximum 3 buttons per message
- Button IDs must be unique within the message
- Button titles are limited to 20 characters
Get Message Status
GET /messages/{messageId}/status
Check the delivery status of a sent message.
Response (200 OK)
json
{
"message_id": "msg_ABC123XYZ",
"external_message_id": "wamid.ABC123XYZ",
"reference_id": "order_123",
"status": "delivered",
"timestamp": "2023-06-21T14:35:50Z",
"errors": [] // Only populated if status is "failed"
}
The possible status values are:
pending
: Message is queued for processingprocessing
: Message is being processedsent
: Message has been sent to WhatsAppdelivered
: Message has been delivered to the recipient's deviceread
: Message has been read by the recipientfailed
: Message delivery failed
Get Message History
GET /messages
Retrieve a list of messages with optional filtering.
Query Parameters
recipient
(string): Filter by recipient phone numberstatus
(string): Filter by message statusfrom_date
(ISO 8601): Start dateto_date
(ISO 8601): End datelimit
(integer, 1-100, default 50): Maximum number of resultsoffset
(integer, default 0): Result offset for pagination
Response (200 OK)
json
{
"messages": [
{
"message_id": "msg_ABC123XYZ",
"external_message_id": "wamid.ABC123XYZ",
"recipient": "919876543210",
"type": "text",
"status": "delivered",
"content": {
"text": "Hello! This is a test message from Talking Shops."
},
"reference_id": "order_123",
"created_at": "2023-06-21T14:35:12Z",
"updated_at": "2023-06-21T14:35:50Z"
},
// More messages...
],
"total": 125,
"limit": 50,
"offset": 0
}
Webhook Endpoints
Register a Webhook
POST /webhooks
Register a URL to receive notifications about message status changes or incoming messages.
Request
json
{
"url": "https://your-app.example.com/webhooks/whatsapp",
"events": ["message.status.updated", "message.received"],
"secret": "your_webhook_secret_key"
}
Response (201 Created)
json
{
"message": "Webhook registered successfully",
"webhook": {
"id": "webhook_123ABC",
"url": "https://your-app.example.com/webhooks/whatsapp",
"events": ["message.status.updated", "message.received"],
"active": true
}
}
List Webhooks
GET /webhooks
Retrieve a list of registered webhooks.
Response (200 OK)
json
{
"webhooks": [
{
"id": "webhook_123ABC",
"url": "https://your-app.example.com/webhooks/whatsapp",
"events": ["message.status.updated", "message.received"],
"active": true,
"created_at": "2023-06-21T12:30:45Z",
"updated_at": "2023-06-21T12:30:45Z",
"last_called_at": "2023-06-21T14:35:50Z",
"failure_count": 0
}
]
}
Account Endpoints
Get Quota Information
GET /account/quota
Check your message quota usage.
Response (200 OK)
json
{
"messages": {
"limit": 1000,
"used": 125,
"remaining": 875
},
"reset_date": "2023-07-01T00:00:00Z"
}
Generate API Key
POST /account/api-keys
Generate a new API key for your tenant.
Request
json
{
"tenantId": "tenant_123",
"phoneId": "phone_456" // optional
}
Response (201 Created)
json
{
"key": "wma_sk_AbCdEfGhIjK1234567890",
"name": "API Key for Tenant 123",
"scopes": ["messages.send", "messages.read"],
"created_at": "2023-06-21T17:30:00Z"
}
Webhook Events
When a webhook is triggered, the following data structure is sent to your registered URL:
Message Status Update
json
{
"event": "message.status.updated",
"timestamp": "2023-06-21T14:35:50Z",
"data": {
"message_id": "msg_ABC123XYZ",
"external_message_id": "wamid.ABC123XYZ",
"reference_id": "order_123",
"status": "delivered",
"recipient": "919876543210",
"timestamp": "2023-06-21T14:35:50Z"
}
}
Message Received
json
{
"event": "message.received",
"timestamp": "2023-06-21T14:40:12Z",
"data": {
"message_id": "wamid.XYZ987ABC",
"from": "919876543210",
"type": "text",
"timestamp": "2023-06-21T14:40:10Z",
"content": {
"text": "Hi, I'd like to place an order."
}
}
}
Webhook Security
When you register a webhook, you provide a secret key. We use this key to sign each webhook request with an HMAC-SHA256 signature, included in the X-WMA-Signature
header. To verify that a webhook came from Talking Shops:
- Get the signature from the
X-WMA-Signature
header - Compute an HMAC-SHA256 signature of the raw request body using your webhook secret
- Compare the signatures using a constant-time comparison function
Example verification in Node.js:
javascript
const crypto = require('crypto');
function verifyWebhook(request, secret) {
const signature = request.headers['x-wma-signature'];
const hmac = crypto.createHmac('sha256', secret);
const computedSignature = hmac.update(request.rawBody).digest('hex');
// Use a constant-time comparison
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(computedSignature, 'hex')
);
}
Error Handling
The API uses standard HTTP status codes and returns errors in a consistent format:
json
{
"error": {
"code": "ErrorType",
"message": "Human-readable error message",
"details": {
// Additional error details, if applicable
}
}
}
Common error codes include:
AuthenticationError
: Invalid or missing API keyValidationError
: Invalid request parametersRateLimitError
: Rate limit exceededQuotaExceededError
: Message quota exceededResourceNotFoundError
: Requested resource not foundWhatsAppAPIError
: Error from the WhatsApp Business API
Status Codes
200 OK
: Request succeeded201 Created
: Resource created successfully202 Accepted
: Request accepted for processing400 Bad Request
: Invalid request parameters401 Unauthorized
: Missing or invalid authentication403 Forbidden
: Authentication valid but insufficient permissions404 Not Found
: Resource not found429 Too Many Requests
: Rate limit exceeded500 Internal Server Error
: Server error
Best Practices
- Store and reuse message IDs: When you send a message, store the returned
message_id
for future reference in status updates. - Handle webhooks asynchronously: Respond to webhook events quickly (with a 200 response) and process the data asynchronously to avoid timeouts.
- Implement webhook verification: Always verify webhook signatures to ensure security.
- Implement proper error handling: Handle API errors gracefully in your application.
- Use message templates for notifications: Pre-approved templates have higher delivery rates for notifications.
- Monitor your quota: Implement tracking for your message quota to avoid disruptions.
Message Types and Content Limitations
Text Messages
- Maximum length: 4,096 characters
Media Messages
- Image: JPEG, PNG (max 5MB)
- Video: MP4, 3GPP (max 16MB)
- Document: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX (max 100MB)
- Audio: AAC, MP4, MPEG, AMR, OGG (max 16MB)
Templates
- Must be pre-approved by WhatsApp
- Limited to specific formats and content types
- Dynamic parameters allowed within defined constraints