MailerSend
WhatsApp API

Messages

Retrieve the WhatsApp messages you sent with the MailerSend API. Get a list of messages filtered by sender, template and date, or a single message with the delivery of every recipient.

A WhatsApp message is the resource created by a single POST /v1/whatsapp/send request. One message can have up to 10 recipients, and the delivery to each recipient is tracked separately as an item.

Messages, items and activities

  • Messages return one row per POST /v1/whatsapp/send request.
  • Items return one row per recipient of a message, with its current status.
  • Activities return one row per status event, so a single item appears once as queued, once as sent, once as delivered, and so on.

Required token scopes

Requires a token with one of the whatsapp_read or whatsapp_full scopes.

Data retention

Sent WhatsApp messages are kept for 7 days. A message older than that is no longer listed, and requesting it returns 404.

Get a list of WhatsApp messages

Get a list of the WhatsApp messages sent from your account with this GET request:

GET https://api.mailersend.com/v1/whatsapp/messages

Messages are returned newest first. The list does not include items; use GET /v1/whatsapp/messages/{message_id} or GET /v1/whatsapp/items for the delivery to each recipient.

Request parameters

Query parameterTypeRequiredLimitationsDetails
whatsapp_account_idstringnoMust be one of your WhatsApp senders.The MailerSend sender ID the messages were sent from. A deleted sender is accepted. See Sender identifiers.
fromstringnoMax: 32 charactersThe sender's phone number in international format. See Filtering.
template_idstringnoThe ID of the template that was sent.
date_fromint|stringnoTimestamp is assumed to be UTC. Must be lower than date_to. No fractional seconds: 2026-10-14T00:00:00.000Z is rejected.Unix timestamp: 1791936000, ISO 8601 datetime: 2026-10-14T00:00:00Z or datetime: 2026-10-14 00:00:00. Exclusive.
date_toint|stringnoTimestamp is assumed to be UTC. Must be higher than date_from. No fractional seconds: 2026-10-15T00:00:00.000Z is rejected.Unix timestamp: 1792022400, ISO 8601 datetime: 2026-10-15T00:00:00Z or datetime: 2026-10-15 00:00:00. Exclusive.
pageintnoMin: 1, Max: 100To reach older messages beyond page 100, narrow date_from and date_to.
limitintnoMin: 1, Max: 100Default: 25

Filtering

date_from and date_to are exclusive: only messages created strictly after date_from and strictly before date_to are returned. Both accept a Unix timestamp, an ISO 8601 datetime with Z or an offset such as 2026-10-14T00:00:00+02:00, or a datetime in Y-m-d H:i:s format. A date without a time, such as 2026-10-14, returns a 422 validation error.

from accepts a phone number in international format. Spaces, dashes and the leading + are ignored, so +1 555-000-1234 and 15550001234 match the same sender.

An example request that returns the messages one sender sent with one template over one day:

GET https://api.mailersend.com/v1/whatsapp/messages?whatsapp_account_id=3enl6x27wmrxrl2v&template_id=23zxk54v6gjy6v7m&date_from=2026-10-14T00:00:00Z&date_to=2026-10-15T00:00:00Z&limit=50
curl --request GET \
  --url 'https://api.mailersend.com/v1/whatsapp/messages?whatsapp_account_id=3enl6x27wmrxrl2v&template_id=23zxk54v6gjy6v7m&date_from=2026-10-14T00:00:00Z&date_to=2026-10-15T00:00:00Z&limit=25' \
  --header 'Authorization: Bearer API_KEY_HERE'
use MailerSend\MailerSend;
use MailerSend\Helpers\Builder\WhatsappMessageParams;

$mailersend = new MailerSend(['api_key' => 'key']);

$whatsappMessageParams = (new WhatsappMessageParams())
    ->setWhatsappAccountId('whatsapp_account_id')
    ->setFrom('15550001234')
    ->setTemplateId('template_id')
    ->setDateFrom('2026-10-14T00:00:00Z')
    ->setDateTo('2026-10-15T00:00:00Z')
    ->setPage(1)
    ->setLimit(25);

$whatsappMessages = $mailersend->whatsappMessage->getAll($whatsappMessageParams);

More examples

import 'dotenv/config';
import { MailerSend } from "mailersend";

const mailerSend = new MailerSend({
  apiKey: process.env.API_KEY,
});

mailerSend.whatsapp.message.list({
  whatsapp_account_id: "whatsapp_account_id",
  from: "15550001234",
  template_id: "template_id",
  date_from: 1791936000,
  date_to: 1792022400,
  limit: 25,
  page: 1,
})
  .then((response) => console.log(response.body))
  .catch((error) => console.log(error.body));

More examples

from mailersend import MailerSendClient, WhatsAppMessagesBuilder

ms = MailerSendClient()

request = (WhatsAppMessagesBuilder()
          .whatsapp_account_id("whatsapp-account-id")
          .from_number("15550001234")
          .template_id("template-id")
          .date_from("2026-10-14T00:00:00Z")
          .date_to("2026-10-15T00:00:00Z")
          .page(1)
          .limit(25)
          .build_list_request())

response = ms.whatsapp_messages.list_whatsapp_messages(request)

More examples

package main

import (
	"context"
	"log"
	"time"

	"github.com/mailersend/mailersend-go"
)

var APIKey = "Api Key Here"

func main() {
	// Create an instance of the mailersend client
	ms := mailersend.NewMailersend(APIKey)

	ctx := context.Background()
	ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
	defer cancel()

	options := &mailersend.ListWhatsAppMessageOptions{
		WhatsAppAccountID: "whatsapp-account-id",
		From:              "15550001234",
		TemplateID:        "template-id",
		DateFrom:          1791936000,
		DateTo:            1792022400,
		Page:              1,
		Limit:             25,
	}

	_, _, err := ms.WhatsAppMessage.List(ctx, options)
	if err != nil {
		log.Fatal(err)
	}
}

More examples

import com.mailersend.sdk.MailerSend;
import com.mailersend.sdk.exceptions.MailerSendException;
import com.mailersend.sdk.whatsapp.messages.WhatsAppMessage;
import com.mailersend.sdk.whatsapp.messages.WhatsAppMessageList;

public void getWhatsAppMessages() {

    MailerSend ms = new MailerSend();
    ms.setToken("mailersend token");

    try {

        WhatsAppMessageList list = ms.whatsapp().messages()
            .whatsappAccountId("whatsapp account id")
            .from("15550001234")
            .templateId("template id")
            .dateFrom(1791936000)
            .dateTo(1792022400)
            .page(1)
            .limit(25)
            .getMessages();

        for (WhatsAppMessage message : list.messages) {
            System.out.println(message.id);
            System.out.println(message.templateId);
        }

    } catch (MailerSendException e) {

        e.printStackTrace();
    }
}

More examples

require "mailersend-ruby"

# Intialize the WhatsApp Messages class
ms_whatsapp_messages = Mailersend::WhatsAppMessages.new

# Add parameters
ms_whatsapp_messages.list(
  whatsapp_account_id: 'your-whatsapp-account-id',
  from: '15550001234',
  template_id: 'your-template-id',
  date_from: 1791936000,
  date_to: 1792022400,
  page: 1,
  limit: 25
)

More examples

Responses

Valid

Response keyTypeDetails
data[].idstringID of the message. The same value is returned by POST /v1/whatsapp/send in the response body and the X-Message-Id header, and sent as data.whatsapp_message_id in webhooks.
data[].fromstring|nullThe sender's phone number, or its WhatsApp username when the message was sent from the username or the sender has no phone number, such as one connected with a Meta virtual number. null when the sender has neither.
data[].tostring[]The recipients of the message.
data[].whatsapp_account_idstring|nullThe MailerSend sender ID of the phone number the message was sent from. See Sender identifiers.
data[].template_idstring|nullThe ID of the template that was sent.
data[].created_atstringWhen the message was created, in ISO 8601 format.
links.firststringFull URL of the first page, with all your query parameters preserved.
links.lastnullAlways null.
links.prevstring|nullFull URL of the previous page. null on the first page.
links.nextstring|nullFull URL of the next page. null on the last page.
meta.current_pageintThe effective page.
meta.current_page_urlstringFull URL of the current page.
meta.fromint|nullIndex of the first row on this page within the result set. null when the page is empty.
meta.pathstringThe URL of the endpoint, without query parameters.
meta.per_pageintThe effective limit.
meta.toint|nullIndex of the last row on this page within the result set. null when the page is empty.
Response Code: 200 OK
Response Headers:
	content-type: application/json
{
  "data": [
    {
      "id": "67f91abd69f79df391e9d78d",
      "from": "15550001234",
      "to": [
        "48600000001",
        "48600000002"
      ],
      "whatsapp_account_id": "3enl6x27wmrxrl2v",
      "template_id": "23zxk54v6gjy6v7m",
      "created_at": "2026-10-14T12:25:33.000000Z"
    },
    {
      "id": "67f91a0c69f79df391e9d6a1",
      "from": null,
      "to": [
        "US.13491208655302741918"
      ],
      "whatsapp_account_id": "p6nq4jyzkyv5x3zl",
      "template_id": "6v7m23zxk54vgjy2",
      "created_at": "2026-10-14T12:21:16.000000Z"
    }
  ],
  "links": {
    "first": "https:\/\/api.mailersend.com\/v1\/whatsapp\/messages?page=1",
    "last": null,
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "current_page_url": "https:\/\/api.mailersend.com\/v1\/whatsapp\/messages?page=1",
    "from": 1,
    "path": "https:\/\/api.mailersend.com\/v1\/whatsapp\/messages",
    "per_page": 25,
    "to": 2
  }
}

Paginating through the results

The list uses simple pagination. The response carries no total and no last_page, and links.last is always null. Follow the URL in links.next, which keeps the filters you sent, until it is null.

Error

Response Code: 403 Forbidden
{
  "message": "The custom API token you're using doesn't have the required permissions. #MS40301"
}

The token is missing the whatsapp_read or whatsapp_full scope.

Response Code: 422 Unprocessable Entity

Returned when a parameter is invalid — including a whatsapp_account_id that does not belong to your account, a from that is not a phone number or is longer than 32 characters, a date_from or date_to without a time, a date_to that is not after date_from, or a page or limit out of range.

See - Validation errors

Get a WhatsApp message

Get a single WhatsApp message, together with the delivery to each of its recipients, with this GET request:

GET https://api.mailersend.com/v1/whatsapp/messages/{message_id}

Request parameters

URL parameterTypeRequiredLimitationsDetails
message_idstringyesThe id of a message, as returned by POST /v1/whatsapp/send in the response body and the X-Message-Id header, or by GET /v1/whatsapp/messages.
curl --request GET \
  --url https://api.mailersend.com/v1/whatsapp/messages/67f91abd69f79df391e9d78d \
  --header 'Authorization: Bearer API_KEY_HERE'
use MailerSend\MailerSend;

$mailersend = new MailerSend(['api_key' => 'key']);

$whatsappMessage = $mailersend->whatsappMessage->find('message_id');

More examples

import 'dotenv/config';
import { MailerSend } from "mailersend";

const mailerSend = new MailerSend({
  apiKey: process.env.API_KEY,
});

mailerSend.whatsapp.message.single("message_id")
  .then((response) => console.log(response.body))
  .catch((error) => console.log(error.body));

More examples

from mailersend import MailerSendClient, WhatsAppMessagesBuilder

ms = MailerSendClient()

request = (WhatsAppMessagesBuilder()
          .whatsapp_message_id("message-id")
          .build_get_request())

response = ms.whatsapp_messages.get_whatsapp_message(request)

More examples

package main

import (
	"context"
	"log"
	"time"

	"github.com/mailersend/mailersend-go"
)

var APIKey = "Api Key Here"

func main() {
	// Create an instance of the mailersend client
	ms := mailersend.NewMailersend(APIKey)

	ctx := context.Background()
	ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
	defer cancel()

	_, _, err := ms.WhatsAppMessage.Get(ctx, "message-id")
	if err != nil {
		log.Fatal(err)
	}
}

More examples

import com.mailersend.sdk.MailerSend;
import com.mailersend.sdk.exceptions.MailerSendException;
import com.mailersend.sdk.whatsapp.messages.WhatsAppMessage;

public void getWhatsAppMessage() {

    MailerSend ms = new MailerSend();
    ms.setToken("mailersend token");

    try {

        WhatsAppMessage message = ms.whatsapp().messages().getMessage("message id");

        System.out.println(message.id);
        System.out.println(message.templateId);

    } catch (MailerSendException e) {

        e.printStackTrace();
    }
}

More examples

require "mailersend-ruby"

# Intialize the WhatsApp Messages class
ms_whatsapp_messages = Mailersend::WhatsAppMessages.new

# Add parameters
ms_whatsapp_messages.get(whatsapp_message_id: 'your-whatsapp-message-id')

More examples

Responses

Valid

The response contains the same fields as an item of the list, plus items.

Response keyTypeDetails
data.itemsobject[]One item per recipient of the message. Items are created asynchronously, so items can be empty right after the message is sent.
data.items.*.idstringID of the item. The same value is sent as data.whatsapp_item_id in webhooks.
data.items.*.whatsapp_message_idstringID of the message the item belongs to.
data.items.*.whatsapp_account_idstring|nullThe MailerSend sender ID of the phone number the message was sent from.
data.items.*.fromstring|nullThe sender's phone number, or its WhatsApp username when the message was sent from the username or the sender has no phone number, such as one connected with a Meta virtual number. null when the sender has neither.
data.items.*.tostringThe recipient's phone number or BSUID.
data.items.*.statusstringThe current status: queued, sent, delivered, read or failed. See WhatsApp status list.
data.items.*.template_idstring|nullThe ID of the template that was sent.
data.items.*.template_namestring|nullThe name of the template that was sent. null when the delivery failed before the template was loaded.
data.items.*.error_codeint|nullThe WhatsApp Cloud API error code when the delivery failed, otherwise null. See Meta's error code reference.
data.items.*.error_messagestring|nullThe error message returned by WhatsApp when the delivery failed, otherwise null.
data.items.*.created_atstringWhen the item was created, in ISO 8601 format.

To get the status timeline of one recipient, use GET /v1/whatsapp/items/{item_id} or GET /v1/whatsapp/activities.

Response Code: 200 OK
Response Headers:
	content-type: application/json
{
  "data": {
    "id": "67f91abd69f79df391e9d78d",
    "from": "15550001234",
    "to": [
      "48600000001",
      "48600000002"
    ],
    "whatsapp_account_id": "3enl6x27wmrxrl2v",
    "template_id": "23zxk54v6gjy6v7m",
    "created_at": "2026-10-14T12:25:33.000000Z",
    "items": [
      {
        "id": "67f91abe2202f3705540234a",
        "whatsapp_message_id": "67f91abd69f79df391e9d78d",
        "whatsapp_account_id": "3enl6x27wmrxrl2v",
        "from": "15550001234",
        "to": "48600000001",
        "status": "read",
        "template_id": "23zxk54v6gjy6v7m",
        "template_name": "Order confirmation",
        "error_code": null,
        "error_message": null,
        "created_at": "2026-10-14T12:25:33.000000Z"
      },
      {
        "id": "67f91abe2202f3705540234b",
        "whatsapp_message_id": "67f91abd69f79df391e9d78d",
        "whatsapp_account_id": "3enl6x27wmrxrl2v",
        "from": "15550001234",
        "to": "48600000002",
        "status": "failed",
        "template_id": "23zxk54v6gjy6v7m",
        "template_name": "Order confirmation",
        "error_code": 131026,
        "error_message": "Message undeliverable",
        "created_at": "2026-10-14T12:25:33.000000Z"
      }
    ]
  }
}

Error

Response Code: 403 Forbidden

The token is missing the whatsapp_read or whatsapp_full scope.

Response Code: 404 Not Found

Returned when the message does not exist, belongs to another account, or is older than the 7-day retention period.

On this page