Whats91
Developers

Create MARKETING templates for offers, promotions, launches, and customer engagement campaigns.

Marketing Template Creation

Summary

Create MARKETING templates for promotions, offers, announcements, and campaign messages that require Meta review.

Prerequisites

  • Bearer token authentication
  • Template name, language, category, and body text
  • Meta-compliant marketing content

Use MARKETING templates for offers, announcements, product launches, coupons, events, and promotional journeys. Whats91 validates the template locally, stores the request, uploads any media header privately, and submits only Meta-supported fields to Meta for review.

Create Marketing Template API

Endpoint: POST /api/v2/templates.

HeaderRequiredDescription
AuthorizationYesUse Authorization: Bearer w91_public_token_here. Compatibility body fields authToken, auth_token, or token are also accepted.
Content-TypeYesUse application/json for text and public media URL templates. Use multipart/form-data when uploading a local header media file.
POST/api/v2/templates
ParameterTypeRequiredDescription
senderIdstringOptionalWhatsApp sender number. Omit when the token resolves to one default or number-scoped sender.
template.namestringRequiredTemplate name. Whats91 normalizes it to lowercase snake_case before submission.
template.categorystringRequiredMust be MARKETING for this page.
template.languagestringRequiredLanguage code such as en. Use the same language you want Meta to review.
template.body.textstringRequiredMarketing message body. Variables use positional placeholders such as {{1}}.
template.body.examplesarrayRequiredExample values for body placeholders. Required when the body contains variables.
template.headerobjectOptionalOptional TEXT, IMAGE, VIDEO, or DOCUMENT header. Media headers need mediaUrl or multipart mediaFile.
template.footer.textstringOptionalOptional short footer text.
template.buttonsarrayOptionalOptional URL, PHONE_NUMBER, or QUICK_REPLY buttons supported by Meta for marketing use cases.
template.metadataobjectOptionalLocal Whats91 metadata stored under temp_data.public_api.metadata and not sent to Meta.
Marketing create request
curl -X POST "https://graph.whats91.com/api/v2/templates" \
  -H "Authorization: Bearer w91_public_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "senderId": "916268662275",
    "template": {
      "name": "festival_offer_v1",
      "category": "MARKETING",
      "language": "en",
      "body": {
        "text": "Hello {{1}}, our festive offer is live. Save {{2}} until {{3}}.",
        "examples": ["Devendar", "20%", "Sunday"]
      },
      "header": { "type": "TEXT", "text": "Festive offer" },
      "footer": { "text": "Whats91" },
      "buttons": [
        {
          "type": "URL",
          "text": "Shop now",
          "url": "https://example.com/offers"
        }
      ],
      "metadata": {
        "clientReferenceId": "campaign-festival-2026"
      }
    }
  }'
Success Response
{
  "success": true,
  "message": "Template submitted to Meta",
  "data": {
    "templateUid": "0e6fb4f1-5a60-4d1d-8ef2-61a6ec8b7103",
    "templateId": "w91_1780300000000_ab12cd34",
    "requestedTemplateName": "festival_offer_v1",
    "templateName": "festival_offer_v1",
    "normalizedTemplateName": "festival_offer_v1",
    "category": "MARKETING",
    "language": "en",
    "status": "PENDING",
    "senderId": "916268662275",
    "phoneNumberId": "1043189608869917",
    "wabaId": "643703032991069",
    "metaSubmission": {
      "submitted": true,
      "status": "PENDING",
      "metaTemplateId": "1234567890"
    }
  },
  "metadata": {
    "apiVersion": "v2",
    "requestId": "request-uuid",
    "processingTimeMs": 320
  }
}
Validation Error Response
{
  "success": false,
  "message": "Template name already exists",
  "error_code": "TEMPLATE_NAME_EXISTS",
  "details": {
    "templateName": "festival_offer_v1",
    "normalizedTemplateName": "festival_offer_v1",
    "templateUid": "existing-template-uid",
    "status": "APPROVED"
  },
  "metadata": {
    "apiVersion": "v2",
    "requestId": "request-uuid"
  }
}
Meta Rejection Error Response
{
  "success": false,
  "message": "Meta rejected template body",
  "error_code": "META_TEMPLATE_SUBMISSION_FAILED",
  "details": {
    "templateUid": "0e6fb4f1-5a60-4d1d-8ef2-61a6ec8b7103",
    "templateName": "festival_offer_v1",
    "meta": {
      "message": "Meta rejected template body",
      "code": 100,
      "subcode": 2388040
    }
  },
  "metadata": {
    "apiVersion": "v2",
    "requestId": "request-uuid"
  }
}

Required fields

FieldTypeNotes
template.namestringUse a unique, readable name. Whats91 normalizes names to lowercase snake_case.
template.categorystringUse MARKETING. Unsupported categories return VALIDATION_FAILED.
template.languagestringUse a supported Meta language code such as en.
template.body.textstringMust not start or end with a variable. Add examples for every placeholder.
template.body.examplesarrayRequired when body text contains {{1}}, {{2}}, or later placeholders.

Optional fields

FieldTypeNotes
senderIdstringSelects the WhatsApp sender number when the token can access multiple senders.
template.headerobjectTEXT, IMAGE, VIDEO, or DOCUMENT. Use mediaUrl for public HTTPS media or multipart mediaFile for local files.
template.footer.textstringShort footer shown below the message body.
template.buttonsarrayUse URL, PHONE_NUMBER, or QUICK_REPLY buttons for clear marketing actions.
template.metadataobjectStored locally by Whats91 and never sent to Meta.

Practical Marketing Examples

1. Festival offer with URL button

Request body
{
  "senderId": "916268662275",
  "template": {
    "name": "festival_offer_v1",
    "category": "MARKETING",
    "language": "en",
    "body": {
      "text": "Hello {{1}}, our festive offer is live. Save {{2}} until {{3}}.",
      "examples": ["Devendar", "20%", "Sunday"]
    },
    "buttons": [
      { "type": "URL", "text": "Shop now", "url": "https://example.com/offers" }
    ]
  }
}

2. Flash sale alert

Request body
{
  "template": {
    "name": "flash_sale_alert",
    "category": "MARKETING",
    "language": "en",
    "body": {
      "text": "Hi {{1}}, flash sale starts at {{2}}. Use code {{3}} before stock runs out.",
      "examples": ["Devendar", "6 PM", "FLASH20"]
    },
    "footer": { "text": "Limited period offer" },
    "buttons": [
      { "type": "URL", "text": "View sale", "url": "https://example.com/sale" }
    ]
  }
}

3. New product launch with image header

Request body
{
  "template": {
    "name": "new_product_launch",
    "category": "MARKETING",
    "language": "en",
    "header": {
      "type": "IMAGE",
      "mediaUrl": "https://cdn.example.com/products/launch.jpg"
    },
    "body": {
      "text": "Introducing {{1}}. Explore launch benefits and early access pricing today.",
      "examples": ["Whats91 Campaign Studio"]
    },
    "buttons": [
      { "type": "URL", "text": "Explore", "url": "https://example.com/product" }
    ]
  }
}

4. Cart recovery offer

Request body
{
  "template": {
    "name": "cart_recovery_offer",
    "category": "MARKETING",
    "language": "en",
    "body": {
      "text": "Hi {{1}}, items in your cart are waiting. Complete checkout and get {{2}} off.",
      "examples": ["Devendar", "10%"]
    },
    "buttons": [
      {
        "type": "URL",
        "text": "Checkout",
        "url": "https://example.com/cart/{{1}}",
        "example": "https://example.com/cart/CART-1001"
      }
    ]
  }
}

5. Loyalty coupon

Request body
{
  "template": {
    "name": "loyalty_coupon",
    "category": "MARKETING",
    "language": "en",
    "body": {
      "text": "Hello {{1}}, your loyalty coupon {{2}} is ready. Redeem it before {{3}}.",
      "examples": ["Devendar", "LOYAL500", "31 March"]
    },
    "buttons": [
      { "type": "QUICK_REPLY", "text": "Use coupon" }
    ]
  }
}

6. Event invitation with video header

Request body
{
  "template": {
    "name": "event_invitation",
    "category": "MARKETING",
    "language": "en",
    "header": {
      "type": "VIDEO",
      "mediaUrl": "https://cdn.example.com/events/invite.mp4"
    },
    "body": {
      "text": "Hi {{1}}, you are invited to {{2}} on {{3}}.",
      "examples": ["Devendar", "Whats91 Connect", "Friday"]
    },
    "buttons": [
      { "type": "URL", "text": "Register", "url": "https://example.com/events" }
    ],
    "metadata": {
      "clientReferenceId": "event-template-2026"
    }
  }
}

SDK Examples

Use these examples as starting points for server-side implementations.

cURL
curl -X POST "https://graph.whats91.com/api/v2/templates" \
  -H "Authorization: Bearer w91_live_xxx" \
  -H "Content-Type: application/json" \
  -d 'curl -X POST "https://graph.whats91.com/api/v2/templates" \
  -H "Authorization: Bearer w91_public_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "senderId": "916268662275",
    "template": {
      "name": "festival_offer_v1",
      "category": "MARKETING",
      "language": "en",
      "body": {
        "text": "Hello {{1}}, our festive offer is live. Save {{2}} until {{3}}.",
        "examples": ["Devendar", "20%", "Sunday"]
      },
      "header": { "type": "TEXT", "text": "Festive offer" },
      "footer": { "text": "Whats91" },
      "buttons": [
        {
          "type": "URL",
          "text": "Shop now",
          "url": "https://example.com/offers"
        }
      ],
      "metadata": {
        "clientReferenceId": "campaign-festival-2026"
      }
    }
  }''
Node.js
const response = await fetch("https://graph.whats91.com/api/v2/templates", {
  method: "POST",
  headers: {
    "Authorization": "Bearer w91_live_xxx",
    "Content-Type": "application/json"
  },
  body: JSON.stringify(curl -X POST "https://graph.whats91.com/api/v2/templates" \
  -H "Authorization: Bearer w91_public_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "senderId": "916268662275",
    "template": {
      "name": "festival_offer_v1",
      "category": "MARKETING",
      "language": "en",
      "body": {
        "text": "Hello {{1}}, our festive offer is live. Save {{2}} until {{3}}.",
        "examples": ["Devendar", "20%", "Sunday"]
      },
      "header": { "type": "TEXT", "text": "Festive offer" },
      "footer": { "text": "Whats91" },
      "buttons": [
        {
          "type": "URL",
          "text": "Shop now",
          "url": "https://example.com/offers"
        }
      ],
      "metadata": {
        "clientReferenceId": "campaign-festival-2026"
      }
    }
  }')
});

const data = await response.json();
console.log(data);
PHP
$ch = curl_init("https://graph.whats91.com/api/v2/templates");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    "Authorization: Bearer w91_live_xxx",
    "Content-Type: application/json"
  ],
  CURLOPT_POSTFIELDS => json_encode(curl -X POST "https://graph.whats91.com/api/v2/templates" \
  -H "Authorization: Bearer w91_public_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "senderId": "916268662275",
    "template": {
      "name": "festival_offer_v1",
      "category": "MARKETING",
      "language": "en",
      "body": {
        "text": "Hello {{1}}, our festive offer is live. Save {{2}} until {{3}}.",
        "examples": ["Devendar", "20%", "Sunday"]
      },
      "header": { "type": "TEXT", "text": "Festive offer" },
      "footer": { "text": "Whats91" },
      "buttons": [
        {
          "type": "URL",
          "text": "Shop now",
          "url": "https://example.com/offers"
        }
      ],
      "metadata": {
        "clientReferenceId": "campaign-festival-2026"
      }
    }
  }')
]);

$response = curl_exec($ch);
curl_close($ch);
echo $response;
Python
import requests

response = requests.request(
    "POST",
    "https://graph.whats91.com/api/v2/templates",
    headers={
        "Authorization": "Bearer w91_live_xxx",
        "Content-Type": "application/json",
    },
    json=curl -X POST "https://graph.whats91.com/api/v2/templates" \
  -H "Authorization: Bearer w91_public_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "senderId": "916268662275",
    "template": {
      "name": "festival_offer_v1",
      "category": "MARKETING",
      "language": "en",
      "body": {
        "text": "Hello {{1}}, our festive offer is live. Save {{2}} until {{3}}.",
        "examples": ["Devendar", "20%", "Sunday"]
      },
      "header": { "type": "TEXT", "text": "Festive offer" },
      "footer": { "text": "Whats91" },
      "buttons": [
        {
          "type": "URL",
          "text": "Shop now",
          "url": "https://example.com/offers"
        }
      ],
      "metadata": {
        "clientReferenceId": "campaign-festival-2026"
      }
    }
  }'
)

print(response.json())
C#
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer w91_live_xxx");

var request = new HttpRequestMessage(HttpMethod.Post, "https://graph.whats91.com/api/v2/templates");
request.Content = new StringContent(
  """curl -X POST \"https://graph.whats91.com/api/v2/templates\" \
  -H \"Authorization: Bearer w91_public_token_here\" \
  -H \"Content-Type: application/json\" \
  -d '{
    \"senderId\": \"916268662275\",
    \"template\": {
      \"name\": \"festival_offer_v1\",
      \"category\": \"MARKETING\",
      \"language\": \"en\",
      \"body\": {
        \"text\": \"Hello {{1}}, our festive offer is live. Save {{2}} until {{3}}.\",
        \"examples\": [\"Devendar\", \"20%\", \"Sunday\"]
      },
      \"header\": { \"type\": \"TEXT\", \"text\": \"Festive offer\" },
      \"footer\": { \"text\": \"Whats91\" },
      \"buttons\": [
        {
          \"type\": \"URL\",
          \"text\": \"Shop now\",
          \"url\": \"https://example.com/offers\"
        }
      ],
      \"metadata\": {
        \"clientReferenceId\": \"campaign-festival-2026\"
      }
    }
  }'""",
  Encoding.UTF8,
  "application/json"
);

var response = await client.SendAsync(request);
Console.WriteLine(await response.Content.ReadAsStringAsync());

Frequently Asked Questions

How do I create a template?

Call POST /api/v2/templates with the template category, language, body text, and any supported buttons or examples.

How long does Meta approval take?

Meta review time varies. Many templates are reviewed quickly, but approval timing depends on Meta systems and policy checks.

Can templates include variables?

Yes. Include variables in the body and provide matching example values for Meta review.

Related APIs