WhatsApp Business Platform API

Create and manage WhatsApp templates, send individual messages, and dispatch bulk campaigns from your own application. Templates are approved by Meta and then referenced by name; message sends and campaigns both run against those approved templates.

Document IDVersionStatusProtocolAuthenticationLast updated
FON-API-WA-0011.0ReleasedREST over HTTPS, JSONBearer token07 September 2026

1. Overview

An integration follows a fixed order. Create a template and wait for Meta to approve it, verify the approval, then send — either to a single number through the message sender, or to a list through the campaign creator. Nothing can be sent from an unapproved template.

BASE URL — https://app.fonada.ai/functions/v1

EndpointMethodPurpose
/whatsapp_templatesGETList templates, optionally filtered by status or category.
/whatsapp_template_managerPOSTCreate, check status of, sync, or delete a template. The action field selects the operation.
/whatsapp_message_senderPOSTSend a text, image, document, or interactive message to one number.
/whatsapp_campaign_creatorPOSTSend an approved template to an audience list in a single call.

1.1 The 24-hour conversation window

Free-form messages — text, image, document, and interactive — may only be sent within 24 hours of the customer's last inbound message. Once that window closes, the send fails with error 131047 and a template message must be used instead. Template messages, including every campaign send, are not subject to the window.

1.2 Conventions used in this document

NotationMeaning
RequiredThe request is rejected if the field is absent.
ConditionalRequired only when a related condition applies — the condition is stated in the description.
OptionalMay be omitted. Any default is stated in the description.
{{1}}A numbered template variable. Values are supplied via sample_values at creation and BODY_n at campaign dispatch.
fsk_…Placeholder for your workspace API key. Replace it with your own value in every example.

2. Authentication

All endpoints accept a bearer token in the Authorization header. Three credential types are supported; use the API key for server-to-server integrations.

CredentialFormatUse
API keyfsk_…Standard server-side integrations. Valid on every endpoint in this document.
WhatsApp API tokenUUIDAccount-scoped token. The account is implied by the token, so account_id is not sent.
Supabase JWTJWTSession-based access, used by the console.
Authorization: Bearer fsk_your_api_key_here
Content-Type: application/json

accountId is derived from the token and must not be included in template payloads. For message sends with an fsk_ key or JWT, account_id may be omitted when exactly one active WABA is linked to your user; include it in the body otherwise.

3. Template management

3.1 List templates

GET /whatsapp_templates — 100 requests / minute

Returns the templates available to your account. Use it to confirm the exact, case-sensitive template name before a send.

curl -G 'https://app.fonada.ai/functions/v1/whatsapp_templates' \
-H 'Authorization: Bearer fsk_your_key_here' \
--data-urlencode 'status=APPROVED'
Query parameterRequiredDescription
statusOptionalFilter by approval status, for example APPROVED.
categoryOptionalFilter by category, for example MARKETING. See the dashboard for the exact filter values.
{ "success": true, "data": { "templates": [ ... ] }, "count": N }

3.2 Create a template

POST /whatsapp_template_manager — "action": "create"

A template defines the exact message structure Meta will approve. Once approved, reference it by name from campaigns and message sends.

Rules before creating

FieldRule
nameLowercase with underscores only — no spaces, uppercase, or hyphens. The name cannot be changed after creation.
categoryUppercase: MARKETING, UTILITY, or AUTHENTICATION.
languageMust include the locale — en_US, hi_IN, en_GB. A bare en is rejected.
variablesNumbered sequentially — {{1}}, {{2}}, {{3}}.
BODYAt least one BODY component is mandatory.

Payload structure

{
  "action": "create",
  "templateData": {
    "name": "your_template_name",
    "category": "MARKETING",
    "language": "en_US",
    "components": [ ... ],
    "sample_values": { "1": "example value" }
  }
}

accountId is auto-derived from your token — do not include it.

Example A — body-only template

A single-paragraph message with one variable, suitable for OTPs, order updates, or welcome messages.

curl -X POST 'https://app.fonada.ai/functions/v1/whatsapp_template_manager' \
-H 'Authorization: Bearer fsk_your_key_here' \
-H 'Content-Type: application/json' \
-d '{
  "action": "create",
  "templateData": {
    "name": "welcome_new_customer",
    "category": "MARKETING",
    "language": "en_US",
    "components": [{
      "type": "BODY",
      "text": "Welcome {{1}}! Thank you for joining us."
    }],
    "sample_values": { "1": "John Doe" },
    "include_optout": true,
    "optout_message": "Reply STOP to unsubscribe"
  }
}'

Example B — header, body, and footer

curl -X POST 'https://app.fonada.ai/functions/v1/whatsapp_template_manager' \
-H 'Authorization: Bearer fsk_your_key_here' \
-H 'Content-Type: application/json' \
-d '{
  "action": "create",
  "templateData": {
    "name": "order_confirmed_full",
    "category": "UTILITY",
    "language": "en_US",
    "components": [
      { "type": "HEADER", "format": "TEXT", "text": "Order Confirmed" },
      { "type": "BODY",   "text": "Hi {{1}}, your order #{{2}} has been confirmed.\nTotal: Rs. {{3}}\nExpected delivery: {{4}}" },
      { "type": "FOOTER", "text": "Thank you for shopping with us!" }
    ],
    "sample_values": { "1": "Priya Sharma", "2": "ORD-12345", "3": "1,999", "4": "Feb 28, 2026" }
  }
}'

Example C — template with action buttons

curl -X POST 'https://app.fonada.ai/functions/v1/whatsapp_template_manager' \
-H 'Authorization: Bearer fsk_your_key_here' \
-H 'Content-Type: application/json' \
-d '{
  "action": "create",
  "templateData": {
    "name": "delivery_update_with_cta",
    "category": "UTILITY",
    "language": "en_US",
    "components": [
      { "type": "BODY", "text": "Your order #{{1}} is out for delivery! Estimated arrival: {{2}}" },
      { "type": "BUTTONS", "buttons": [
        { "type": "URL",          "text": "Track Order",  "url": "https://yourstore.com/track/{{1}}" },
        { "type": "PHONE_NUMBER", "text": "Call Support", "phone_number": "+910000000000" }
      ]}
    ],
    "sample_values": { "1": "ORD-98765", "2": "Today by 6 PM" }
  }
}'

Component constraints

ComponentMax per templateMax variablesMax lengthMandatory
HEADER1160 charactersNo
BODY1101,024 charactersYes
FOOTER1None60 charactersNo
BUTTONS1 set3 buttons total20 characters per buttonNo

Button types

TypeDescriptionRequired fields
URLOpens a websitetext, url
PHONE_NUMBERDials a numbertext, phone_number
QUICK_REPLYSends a pre-filled reply back to youtext

Success response

{
  "success": true,
  "template": {
    "id": "7119e2f3-7469-4cbe-a85b-5e7cf614ae03",
    "template_name": "order_confirmed_full",
    "status": "PENDING",
    "category": "UTILITY",
    "language": "en_US",
    "created_at": "2026-02-26T12:00:00Z"
  },
  "message": "Template submitted to WhatsApp for review. Approval typically takes 24-48 hours."
}

Common errors

MessageCauseFix
action is requiredMissing root-level action fieldAdd "action": "create".
templateData is requiredMissing wrapper objectWrap the template inside "templateData": {}.
Template name invalidName contains uppercase or spacesUse lowercase with underscores only.
Language format should be locale-specificUsing en instead of en_USAlways include the locale, for example en_US or hi_IN.
BODY component is requiredNo BODY in the components arrayAdd { "type": "BODY", "text": "…" }.
Template already existsDuplicate nameNames cannot be reused — choose a new one.

3.3 Get template status

POST /whatsapp_template_manager — "action": "get_status"

curl -X POST 'https://app.fonada.ai/functions/v1/whatsapp_template_manager' \
-H 'Authorization: Bearer fsk_your_key_here' \
-H 'Content-Type: application/json' \
-d '{ "action": "get_status", "templateName": "order_confirmed_full" }'
{
  "success": true,
  "template": {
    "id": "7119e2f3-7469-4cbe-a85b-5e7cf614ae03",
    "template_name": "order_confirmed_full",
    "status": "APPROVED",
    "rejection_reason": null,
    "quality_score": "HIGH"
  }
}
StatusMeaningNext action
PENDINGUnder Meta reviewWait 24 to 48 hours, then poll again.
APPROVEDReady to useProceed to campaigns or message sends.
REJECTEDMeta declined the templateDelete it and recreate under a different name.

3.4 Sync templates from Meta

POST /whatsapp_template_manager — "action": "sync"

Pulls the latest template statuses from Meta into the Fonada database.

curl -X POST 'https://app.fonada.ai/functions/v1/whatsapp_template_manager' \
-H 'Authorization: Bearer fsk_your_key_here' \
-H 'Content-Type: application/json' \
-d '{ "action": "sync" }'

3.5 Delete a template

POST /whatsapp_template_manager — "action": "delete"

A template in use by an active campaign cannot be deleted. Stop the campaign first.

curl -X POST 'https://app.fonada.ai/functions/v1/whatsapp_template_manager' \
-H 'Authorization: Bearer fsk_your_key_here' \
-H 'Content-Type: application/json' \
-d '{ "action": "delete", "templateName": "old_promo_v1" }'

4. Message sending

POST /whatsapp_message_sender — 80 requests / second

Sends an individual message to one WhatsApp number. All four message types below are free-form and therefore restricted to the 24-hour conversation window described in section 1.1.

4.1 Text message

curl -X POST 'https://app.fonada.ai/functions/v1/whatsapp_message_sender' \
-H 'Authorization: Bearer fsk_your_key_here' \
-H 'Content-Type: application/json' \
-d '{
  "to": "919876543210",
  "message": {
    "type": "text",
    "text": { "body": "Hello! Your order has been dispatched and will arrive by tomorrow." }
  }
}'
FieldRequiredDescription
toRequiredPhone number with country code — no +, no spaces. For example 919876543210.
message.typeRequiredSet to text.
message.text.bodyRequiredMessage content. Maximum 4,096 characters.
{
  "success": true,
  "data": {
    "message_id": "wamid.HBgLOTE5ODc2NTQzMjEwFQIAERgS...",
    "wa_id": "919876543210",
    "status": "sent"
  },
  "performance": { "total_time_ms": 1682 }
}

4.2 Image message

curl -X POST 'https://app.fonada.ai/functions/v1/whatsapp_message_sender' \
-H 'Authorization: Bearer fsk_your_key_here' \
-H 'Content-Type: application/json' \
-d '{
  "to": "919876543210",
  "message": {
    "type": "image",
    "image": {
      "link": "https://yourcdn.com/products/item-001.jpg",
      "caption": "Your ordered item — arrives by tomorrow!"
    }
  }
}'

Requirements: JPEG or PNG, maximum 5 MB, caption up to 1,024 characters.

4.3 Document message

curl -X POST 'https://app.fonada.ai/functions/v1/whatsapp_message_sender' \
-H 'Authorization: Bearer fsk_your_key_here' \
-H 'Content-Type: application/json' \
-d '{
  "to": "919876543210",
  "message": {
    "type": "document",
    "document": {
      "link": "https://yourcdn.com/invoices/INV-2026-001.pdf",
      "filename": "Invoice_March2026.pdf",
      "caption": "Your invoice for order ORD-12345"
    }
  }
}'

Requirements: PDF, DOC, DOCX, XLS, XLSX, PPT, or PPTX, maximum 100 MB.

4.4 Interactive buttons

curl -X POST 'https://app.fonada.ai/functions/v1/whatsapp_message_sender' \
-H 'Authorization: Bearer fsk_your_key_here' \
-H 'Content-Type: application/json' \
-d '{
  "to": "919876543210",
  "message": {
    "type": "interactive",
    "interactive": {
      "type": "button",
      "body": { "text": "Your order ORD-12345 is ready for pickup. Confirm?" },
      "action": {
        "buttons": [
          { "type": "reply", "reply": { "id": "confirm_pickup", "title": "Yes, confirm" } },
          { "type": "reply", "reply": { "id": "reschedule",     "title": "Reschedule"   } },
          { "type": "reply", "reply": { "id": "cancel_order",   "title": "Cancel order" } }
        ]
      }
    }
  }
}'
  • Minimum 1 and maximum 3 buttons.
  • title is limited to 20 characters.
  • id is returned in the webhook when tapped — use it to identify the customer's choice.
  • Must be sent within the 24-hour customer-initiated window.

4.5 Message status values

StatusMeaningBilling
sentDispatched from Meta's servers—
deliveredDelivered to the recipient's deviceBilled at this point
readRead by the recipient—
failedCould not be deliveredNot billed

Common errors on message sends

ErrorCodeCauseFix
Invalid phone number400Missing country code or wrong formatUse 919876543210 — no +, no spaces.
Re-engagement required13104724-hour window closedSwitch to a template message.
Media type mismatch131053Wrong MIME typeMatch the MIME type to the file extension.
Message undeliverable131026Number unreachable or blockedVerify the phone number.
Rate limit exceeded133000More than 80 messages per secondThrottle your send rate.

5. Campaigns

POST /whatsapp_campaign_creator

Use this endpoint to send the same approved template to many recipients in one call, with per-recipient variable values. The message sender targets a single number; the campaign creator accepts an audience list and handles bulk dispatch.

FieldRequiredDescription
campaign_nameRequiredUnique name for this campaign run, in lowercase with underscores. Used for tracking and reporting in the dashboard.
template_nameRequiredName of an approved template. Case-sensitive; must match the value listed by GET /whatsapp_templates.
audience_rowsRequiredArray of recipient objects. Each contains phone plus one key per template variable — BODY_1, BODY_2, … BODY_n.
audience_rows[].phoneRequiredCountry code and number, no + prefix and no spaces. For example 917983272926.
audience_rows[].BODY_nConditionalValue for the n-th variable in the template body. Required when the template contains {{n}} placeholders. Must start at BODY_1 and be consecutive.
curl --location 'https://app.fonada.ai/functions/v1/whatsapp_campaign_creator' \
--header 'Authorization: Bearer fsk_your_key_here' \
--header 'Content-Type: application/json' \
--data '{
  "campaign_name": "test_abc1",
  "template_name": "test_abcd",
  "audience_rows": [
    { "phone": "917983272926", "BODY_1": "test1" },
    { "phone": "917428346262", "BODY_1": "test1" }
  ]
}'
{
  "success": true,
  "campaign": {
    "id": "c3a1e2f4-9b7d-4e6a-a123-0d8f1e5c2b90",
    "campaign_name": "test_abc1",
    "template_name": "test_abcd",
    "status": "launched",
    "total_recipients": 2,
    "queued_at": "2026-04-29T10:00:00Z"
  }
}

Common campaign errors

CodeCauseFix
400campaign_name or template_name missingInclude both fields in the request body.
400audience_rows empty or missingProvide at least one recipient object.
404Template not foundVerify the exact name using GET /whatsapp_templates.
409Campaign name already existsChoose a unique campaign_name.
402Insufficient creditsTop up the balance under Billing in the dashboard.
133000 / 130429Rate limit exceededThrottle the send rate to 80 messages per second or lower.

6. Error reference

6.1 HTTP status codes

CodeStatusMeaningAction
200OKRequest succeededProcess the response.
207Multi-StatusCampaign saved but auto-launch failedUse campaign.id to retry the launch.
400Bad RequestInvalid payload or missing fieldsRead the error field in the response body.
401UnauthorizedToken missing, invalid, or expiredRegenerate your API token.
402Payment RequiredInsufficient creditsTop up under Billing in the dashboard.
403ForbiddenToken does not own this resourceVerify the token matches the campaign or account.
404Not FoundCampaign, template, or account not foundVerify the name or UUID.
409ConflictDuplicate nameUse a different name.
500Internal Server ErrorServer-side failureRetry once; if it persists, contact support.
503Service UnavailableFonada or Meta temporarily unavailableRetry after a few minutes.

6.2 WhatsApp error codes

These appear in the error_data.code field when Meta rejects a message.

CodeErrorCauseFix
130429Rate limit hitToo many messages too quicklySlow to 80 messages per second or lower.
131047Re-engagement required24-hour conversation window closedUse a template message.
131026Message undeliverableNumber unreachable or blockedVerify the phone number.
131053Media type mismatchWrong MIME typeMatch the MIME type to the file extension.
133000Rate limit exceededAccount messaging tier limit reachedReduce volume or upgrade the tier.
100Invalid parameterMalformed requestCheck the template structure and parameters.

6.3 Troubleshooting

ScenarioCauseFix
Template name lookup returns 404The name must match exactly, in lowercase, and the template must belong to the account tied to your token.List templates with section 3.1 and verify the exact template_name.
API token returns 401The token is revoked, expired after its 365-day limit, or belongs to another account.Generate a new token from the dashboard.

7. Support

When raising a ticket, quote the message_id for a single send or the campaign id for a bulk send — these identify the exact dispatch in platform logs.

Technical support1800 120 0081
Emailinfo@fonada.com
Consoleapp.fonada.ai
Related documentationWhatsApp onboarding, RCS Campaign API, KPI Analytics

Appendix A — Field formats and rate limits

Phone number format

ValueValidNote
919876543210YesIndia — correct
14155551234YesUSA — correct
9876543210NoMissing country code
+919876543210NoRemove the + prefix
91 9876543210NoRemove the space

Date and time format (ISO 8601, UTC)

ValueValid
2026-02-26T12:00:00ZYes
2026-02-26T12:00:00.000ZYes
26/02/2026No
Feb 26, 2026No

Template name format

ValueValidNote
order_confirmation_v2Yes—
welcome_customer_march2026Yes—
Order ConfirmationNoSpaces and uppercase not allowed
order-confirmationNoHyphens not allowed
OrderConfirmationNoCamelCase not allowed

WhatsApp messaging tiers (enforced by Meta)

TierMessages per 24 hoursHow to reach the next tier
Tier 11,000Message 1,000 unique users while maintaining good quality.
Tier 210,000Maintain consistent quality after Tier 1.
Tier 3100,000Maintain consistent quality after Tier 2.
Tier 4UnlimitedEnterprise — contact Meta directly.

API request limits (enforced by Fonada)

EndpointLimit
/whatsapp_message_sender80 requests per second
/whatsapp_templates100 requests per minute
/whatsapp_campaign_creatorSubject to the WhatsApp messaging tier limits above

Appendix B — Revision history

VersionDateSummary of changeAuthor
1.007 Sep 2026First released edition. Template management, message sending, campaign dispatch, error reference, and format appendix.Platform Engineering