Skip to content

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 TypePlatformUser ExperienceSetup ComplexityUse Case
Copy CodeAll platformsUser taps to copy code to clipboard✅ SimpleUniversal compatibility
One-TapAndroid (fallback: copy code)Automatically opens your app with code🔶 MediumEnhanced Android UX
Zero-TapAndroid (fallback: one-tap/copy)Code appears automatically in app🔴 ComplexInvisible authentication
Platform Compatibility Matrix
FeatureAndroidiOSWeb WhatsAppWhatsApp 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:

ParameterTypeDescription
recipientstringRecipient phone number (10-15 digits)
template_namestringName of the authentication template (must exist in WhatsApp Business Manager)
language_codestringLanguage code (e.g., en_US)
codestringThe OTP/verification code to send (1-15 characters)

Optional Parameters:

ParameterTypeDescription
reference_idstringCustom reference ID for tracking
componentsobjectOptional 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:

  1. Using Google's Method: Follow Google's instructions

  2. 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 CodeDescriptionSolution
TEMPLATE_NOT_FOUNDAuthentication template doesn't existCreate the template first
INVALID_SIGNATURE_HASHSignature hash format is incorrectVerify hash is exactly 11 characters
INVALID_PACKAGE_NAMEPackage name format is invalidCheck package name requirements
ZERO_TAP_TERMS_NOT_ACCEPTEDTerms not accepted for zero-tapSet zero_tap_terms_accepted: true
INVALID_OTP_TYPEUnknown OTP button typeUse copy_code, one_tap, or zero_tap
Best Practices

Security:

  1. Never log or store verification codes in plain text
  2. Use HTTPS for all API communications
  3. Implement rate limiting on your authentication endpoints
  4. Validate codes server-side before accepting them
  5. Use appropriate expiration times (5-15 minutes recommended)

User Experience:

  1. Start with copy code templates for maximum compatibility
  2. Implement one-tap for Android users when possible
  3. Consider zero-tap only for high-security applications
  4. Always include security recommendations for sensitive operations
  5. Use clear, branded template names

Template Management:

  1. Create templates in all required languages
  2. Test templates thoroughly before production use
  3. Monitor template approval status
  4. Keep template names consistent across languages
  5. 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

ParameterTypeRequiredDescription
recipientstringYesRecipient phone number (10-15 digits)
headerobjectNoOptional header section
header.typestringYes*Must be "text"
header.textstringYes*Header text (max 60 characters)
bodyobjectYesMain message content
body.textstringYesBody text (1-1024 characters)
footerobjectNoOptional footer section
footer.textstringYes*Footer text (max 60 characters)
actionobjectYesList action configuration
action.buttonstringYesButton text (max 20 characters)
action.sectionsarrayYesList sections (1-10 sections)
reference_idstringNoCustom reference ID for tracking

Section Object

ParameterTypeRequiredDescription
titlestringYesSection title (max 24 characters)
rowsarrayYesList rows (1-10 rows per section)

Row Object

ParameterTypeRequiredDescription
idstringYesUnique row ID (max 200 characters)
titlestringYesRow title (max 24 characters)
descriptionstringNoRow 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

ParameterTypeRequiredDescription
recipientstringYesRecipient phone number (10-15 digits)
headerobjectNoOptional header section
bodyobjectYesMain message content
body.textstringYesBody text (1-1024 characters)
footerobjectNoOptional footer section
footer.textstringYes*Footer text (max 60 characters)
actionobjectYesButton action configuration
action.buttonsarrayYesReply buttons (1-3 buttons)
reference_idstringNoCustom 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

ParameterTypeRequiredDescription
typestringYesMust be "reply"
replyobjectYesReply button configuration
reply.idstringYesUnique button ID (max 256 characters)
reply.titlestringYesButton 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 processing
  • processing: Message is being processed
  • sent: Message has been sent to WhatsApp
  • delivered: Message has been delivered to the recipient's device
  • read: Message has been read by the recipient
  • failed: Message delivery failed

Get Message History

GET /messages

Retrieve a list of messages with optional filtering.

Query Parameters
  • recipient (string): Filter by recipient phone number
  • status (string): Filter by message status
  • from_date (ISO 8601): Start date
  • to_date (ISO 8601): End date
  • limit (integer, 1-100, default 50): Maximum number of results
  • offset (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:

  1. Get the signature from the X-WMA-Signature header
  2. Compute an HMAC-SHA256 signature of the raw request body using your webhook secret
  3. 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 key
  • ValidationError: Invalid request parameters
  • RateLimitError: Rate limit exceeded
  • QuotaExceededError: Message quota exceeded
  • ResourceNotFoundError: Requested resource not found
  • WhatsAppAPIError: Error from the WhatsApp Business API

Status Codes

  • 200 OK: Request succeeded
  • 201 Created: Resource created successfully
  • 202 Accepted: Request accepted for processing
  • 400 Bad Request: Invalid request parameters
  • 401 Unauthorized: Missing or invalid authentication
  • 403 Forbidden: Authentication valid but insufficient permissions
  • 404 Not Found: Resource not found
  • 429 Too Many Requests: Rate limit exceeded
  • 500 Internal Server Error: Server error

Best Practices

  1. Store and reuse message IDs: When you send a message, store the returned message_id for future reference in status updates.
  2. Handle webhooks asynchronously: Respond to webhook events quickly (with a 200 response) and process the data asynchronously to avoid timeouts.
  3. Implement webhook verification: Always verify webhook signatures to ensure security.
  4. Implement proper error handling: Handle API errors gracefully in your application.
  5. Use message templates for notifications: Pre-approved templates have higher delivery rates for notifications.
  6. 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

Transform WhatsApp into Your Business Growth Engine