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/templatesTemplates are returned newest first. Templates of a deleted sender are not listed.
Request parameters
| Query parameter | Type | Required | Limitations | Details |
|---|---|---|---|---|
whatsapp_account_id | string | no | Must be one of your WhatsApp senders. | The MailerSend sender ID the templates belong to. See Sender identifiers. |
status | string | no | Possible values: draft, pending, approved, rejected, archived, deleted, disabled, flagged, in_appeal, limit_exceeded, locked, paused, reinstated, pending_deletion | The template's review status. Only approved templates can be sent. |
category | string | no | Possible values: UTILITY, AUTHENTICATION, MARKETING | |
language | string | no | The template's language code, for example en_US. | |
page | int | no | Min: 1, Max: 100 | |
limit | int | no | Min: 1, Max: 100 | Default: 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=UTILITYcurl --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);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));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)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)
}
}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();
}
}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
)Responses
Valid
| Response key | Type | Details |
|---|---|---|
data[].id | string | ID of the template. Use it as template_id in POST /v1/whatsapp/send. |
data[].whatsapp_account_id | string | The MailerSend sender ID the template belongs to. A template can only be sent from this sender. |
data[].name | string | The template name registered with Meta. |
data[].readable_name | string|null | The name of the template shown in your MailerSend account. null when no display name is set. |
data[].category | string | UTILITY, AUTHENTICATION or MARKETING. |
data[].language | string | The template's language code. |
data[].status | string | The template's review status, for example approved, pending, rejected, paused or disabled. |
data[].components | object | The content of the template. |
data[].components.header | object|null | The header, or null when the template has no header. |
data[].components.header.format | string | The header type: TEXT, IMAGE, VIDEO, DOCUMENT or LOCATION. |
data[].components.header.text | string|null | The header text, including any variable placeholders. null when the header has no text, such as a media header. |
data[].components.body | object|null | The body, or null when the template has no body. |
data[].components.body.text | string|null | The body text, including any variable placeholders. null when the body has no text. |
data[].components.buttons | object[] | The template's buttons, in the order they appear. Empty when the template has no buttons. |
data[].components.buttons.*.type | string | The type of button. |
data[].components.buttons.*.text | string|null | The button label. null when the button has no label, such as the copy code button of an authentication template. |
data[].components.buttons.*.url | string|null | The URL a URL button opens, otherwise null. |
data[].created_at | string | When the template was created, in ISO 8601 format. |
data[].updated_at | string | When the template was last updated, in ISO 8601 format. |
links.first | string | Full URL of the first page, with all your query parameters preserved. |
links.last | null | Always null. |
links.prev | string|null | Full URL of the previous page. null on the first page. |
links.next | string|null | Full URL of the next page. null on the last page. |
meta.current_page | int | The effective page. |
meta.current_page_url | string | Full URL of the current page. |
meta.from | int|null | Index of the first row on this page within the result set. null when the page is empty. |
meta.path | string | The URL of the endpoint, without query parameters. |
meta.per_page | int | The effective limit. |
meta.to | int|null | Index 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 EntityReturned 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 parameter | Type | Required | Limitations | Details |
|---|---|---|---|---|
template_id | string | yes | The 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');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));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)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)
}
}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();
}
}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')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 ForbiddenThe token is missing the whatsapp_read or whatsapp_full scope.
Response Code: 404 Not FoundReturned when the template does not exist or belongs to another account.
Recipients
Retrieve the WhatsApp recipients of your account with the MailerSend API. Get a list of recipients filtered by status or phone number, or a single recipient with their latest deliveries.
Webhooks
Receive real-time WhatsApp delivery events and inbound messages with MailerSend WhatsApp webhooks. See all events, payloads and how to verify signatures.