MailerSend
WhatsApp API

Templates

Retrieve the WhatsApp templates of your account with the MailerSend API. Get a list of templates filtered by sender, status, category and language, or a single template.

Every business-initiated WhatsApp message uses a template approved by Meta. Use these requests to look up your templates and their id, which you pass as template_id to POST /v1/whatsapp/send. Templates are created and submitted to Meta in your MailerSend account, under WhatsApp → Templates.

Required token scopes

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

Get a list of WhatsApp templates

Get a list of your WhatsApp templates with this GET request:

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

Templates are returned newest first. Templates of a deleted sender are not listed.

Request parameters

Query parameterTypeRequiredLimitationsDetails
whatsapp_account_idstringnoMust be one of your WhatsApp senders.The MailerSend sender ID the templates belong to. See Sender identifiers.
statusstringnoPossible values: draft, pending, approved, rejected, archived, deleted, disabled, flagged, in_appeal, limit_exceeded, locked, paused, reinstated, pending_deletionThe template's review status. Only approved templates can be sent.
categorystringnoPossible values: UTILITY, AUTHENTICATION, MARKETING
languagestringnoThe template's language code, for example en_US.
pageintnoMin: 1, Max: 100
limitintnoMin: 1, Max: 100Default: 25

An example request that returns the approved utility templates of one sender:

GET https://api.mailersend.com/v1/whatsapp/templates?whatsapp_account_id=3enl6x27wmrxrl2v&status=approved&category=UTILITY
curl --request GET \
  --url 'https://api.mailersend.com/v1/whatsapp/templates?whatsapp_account_id=3enl6x27wmrxrl2v&status=approved&category=UTILITY&limit=25' \
  --header 'Authorization: Bearer API_KEY_HERE'
use MailerSend\MailerSend;
use MailerSend\Helpers\Builder\WhatsappTemplateParams;

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

$whatsappTemplateParams = (new WhatsappTemplateParams())
    ->setWhatsappAccountId('whatsapp_account_id')
    ->setStatus('approved')
    ->setCategory('UTILITY')
    ->setPage(1)
    ->setLimit(25);

$whatsappTemplates = $mailersend->whatsappTemplate->getAll($whatsappTemplateParams);

More examples

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

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

mailerSend.whatsapp.template.list({
  whatsapp_account_id: "whatsapp_account_id",
  status: "approved",
  category: "UTILITY",
  limit: 25,
  page: 1,
})
  .then((response) => console.log(response.body))
  .catch((error) => console.log(error.body));

More examples

from mailersend import MailerSendClient, WhatsAppTemplatesBuilder
from mailersend.models.whatsapp_templates import WhatsAppTemplateCategory, WhatsAppTemplateStatus

ms = MailerSendClient()

request = (WhatsAppTemplatesBuilder()
          .whatsapp_account_id("whatsapp-account-id")
          .status(WhatsAppTemplateStatus.APPROVED)
          .category(WhatsAppTemplateCategory.UTILITY)
          .page(1)
          .limit(25)
          .build_list_request())

response = ms.whatsapp_templates.list_whatsapp_templates(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.ListWhatsAppTemplateOptions{
		WhatsAppAccountID: "whatsapp-account-id",
		Status:            "approved",
		Category:          "UTILITY",
		Page:              1,
		Limit:             25,
	}

	_, _, err := ms.WhatsAppTemplate.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.templates.WhatsAppTemplate;
import com.mailersend.sdk.whatsapp.templates.WhatsAppTemplateList;

public void getWhatsAppTemplates() {

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

    try {

        WhatsAppTemplateList list = ms.whatsapp().templates()
            .whatsappAccountId("whatsapp account id")
            .status("approved")
            .category("UTILITY")
            .page(1)
            .limit(25)
            .getTemplates();

        for (WhatsAppTemplate template : list.templates) {
            System.out.println(template.id);
            System.out.println(template.name);
        }

    } catch (MailerSendException e) {

        e.printStackTrace();
    }
}

More examples

require "mailersend-ruby"

# Intialize the WhatsApp Templates class
ms_whatsapp_templates = Mailersend::WhatsAppTemplates.new

# Add parameters
ms_whatsapp_templates.list(
  whatsapp_account_id: 'your-whatsapp-account-id',
  status: 'approved',
  category: 'UTILITY',
  page: 1,
  limit: 25
)

More examples

Responses

Valid

Response keyTypeDetails
data[].idstringID of the template. Use it as template_id in POST /v1/whatsapp/send.
data[].whatsapp_account_idstringThe MailerSend sender ID the template belongs to. A template can only be sent from this sender.
data[].namestringThe template name registered with Meta.
data[].readable_namestring|nullThe name of the template shown in your MailerSend account. null when no display name is set.
data[].categorystringUTILITY, AUTHENTICATION or MARKETING.
data[].languagestringThe template's language code.
data[].statusstringThe template's review status, for example approved, pending, rejected, paused or disabled.
data[].componentsobjectThe content of the template.
data[].components.headerobject|nullThe header, or null when the template has no header.
data[].components.header.formatstringThe header type: TEXT, IMAGE, VIDEO, DOCUMENT or LOCATION.
data[].components.header.textstring|nullThe header text, including any variable placeholders. null when the header has no text, such as a media header.
data[].components.bodyobject|nullThe body, or null when the template has no body.
data[].components.body.textstring|nullThe body text, including any variable placeholders. null when the body has no text.
data[].components.buttonsobject[]The template's buttons, in the order they appear. Empty when the template has no buttons.
data[].components.buttons.*.typestringThe type of button.
data[].components.buttons.*.textstring|nullThe button label. null when the button has no label, such as the copy code button of an authentication template.
data[].components.buttons.*.urlstring|nullThe URL a URL button opens, otherwise null.
data[].created_atstringWhen the template was created, in ISO 8601 format.
data[].updated_atstringWhen the template was last updated, 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": "23zxk54v6gjy6v7m",
      "whatsapp_account_id": "3enl6x27wmrxrl2v",
      "name": "order_confirmation",
      "readable_name": "Order confirmation",
      "category": "UTILITY",
      "language": "en_US",
      "status": "approved",
      "components": {
        "header": {
          "format": "TEXT",
          "text": "{{1}}"
        },
        "body": {
          "text": "Hi {{1}}, your order is confirmed and will arrive on {{2}}."
        },
        "buttons": [
          {
            "type": "URL",
            "text": "View order",
            "url": "https://shop.example.com/{{1}}"
          }
        ]
      },
      "created_at": "2026-10-14T12:25:33.000000Z",
      "updated_at": "2026-10-14T12:41:07.000000Z"
    },
    {
      "id": "p6nq4jyzkyv5x3zl",
      "whatsapp_account_id": "3enl6x27wmrxrl2v",
      "name": "delivery_update",
      "readable_name": "Delivery update",
      "category": "UTILITY",
      "language": "en_US",
      "status": "pending",
      "components": {
        "header": null,
        "body": {
          "text": "Your parcel is out for delivery today."
        },
        "buttons": [
          {
            "type": "QUICK_REPLY",
            "text": "Change delivery time",
            "url": null
          }
        ]
      },
      "created_at": "2026-10-13T09:02:18.000000Z",
      "updated_at": "2026-10-13T09:02:18.000000Z"
    }
  ],
  "links": {
    "first": "https:\/\/api.mailersend.com\/v1\/whatsapp\/templates?page=1",
    "last": null,
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "current_page_url": "https:\/\/api.mailersend.com\/v1\/whatsapp\/templates?page=1",
    "from": 1,
    "path": "https:\/\/api.mailersend.com\/v1\/whatsapp\/templates",
    "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 status or category that is not one of the possible values, or a page or limit out of range.

See - Validation errors

Get a WhatsApp template

Get a single WhatsApp template with this GET request:

GET https://api.mailersend.com/v1/whatsapp/templates/{template_id}

Request parameters

URL parameterTypeRequiredLimitationsDetails
template_idstringyesThe id of a template, as returned by GET /v1/whatsapp/templates.
curl --request GET \
  --url https://api.mailersend.com/v1/whatsapp/templates/23zxk54v6gjy6v7m \
  --header 'Authorization: Bearer API_KEY_HERE'
use MailerSend\MailerSend;

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

$whatsappTemplate = $mailersend->whatsappTemplate->find('template_id');

More examples

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

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

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

More examples

from mailersend import MailerSendClient, WhatsAppTemplatesBuilder

ms = MailerSendClient()

request = (WhatsAppTemplatesBuilder()
          .whatsapp_template_id("template-id")
          .build_get_request())

response = ms.whatsapp_templates.get_whatsapp_template(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.WhatsAppTemplate.Get(ctx, "template-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.templates.WhatsAppTemplate;

public void getWhatsAppTemplate() {

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

    try {

        WhatsAppTemplate template = ms.whatsapp().templates().getTemplate("template id");

        System.out.println(template.id);
        System.out.println(template.status);

    } catch (MailerSendException e) {

        e.printStackTrace();
    }
}

More examples

require "mailersend-ruby"

# Intialize the WhatsApp Templates class
ms_whatsapp_templates = Mailersend::WhatsAppTemplates.new

# Add parameters
ms_whatsapp_templates.get(whatsapp_template_id: 'your-whatsapp-template-id')

More examples

Responses

Valid

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

Response Code: 200 OK
Response Headers:
	content-type: application/json
{
  "data": {
    "id": "23zxk54v6gjy6v7m",
    "whatsapp_account_id": "3enl6x27wmrxrl2v",
    "name": "order_confirmation",
    "readable_name": "Order confirmation",
    "category": "UTILITY",
    "language": "en_US",
    "status": "approved",
    "components": {
      "header": {
        "format": "TEXT",
        "text": "{{1}}"
      },
      "body": {
        "text": "Hi {{1}}, your order is confirmed and will arrive on {{2}}."
      },
      "buttons": [
        {
          "type": "URL",
          "text": "View order",
          "url": "https://shop.example.com/{{1}}"
        }
      ]
    },
    "created_at": "2026-10-14T12:25:33.000000Z",
    "updated_at": "2026-10-14T12:41:07.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 template does not exist or belongs to another account.

On this page