Overview
Before your business can place a business-initiated call to a WhatsApp user, the user must grant call permission. The user is in full control — they can accept (temporary or permanent), decline, or ignore. They can revoke a granted permission at any time. Your business cannot revoke or modify a granted permission.
As of November 3, 2025, permanent permissions are available — users can grant ongoing permission to call. Permanent permission data is stored until the user revokes it. Permanent permissions are only available in regions where business-initiated calling is available.
Temporary vs Permanent
| Temporary | Permanent | |
|---|---|---|
| Duration | 7 calendar days (168 hours) from approval | No expiration |
| Connected calls cap | 100 / 24h per business + user pair | 100 / 24h per business + user pair |
| Auto-revocation on unanswered | Yes (after 4 consecutive unanswered) | Yes (after 4 consecutive unanswered) |
| User revocable any time | Yes | Yes |
Both kinds share the same per-day connected-call limit. The difference is just the expiration window.
Three Ways to Obtain Permission
| Method | When to use |
|---|---|
| 1. Send a call permission request message | Proactively, when you want to call a user out of the blue (within an open CSW: free-form, otherwise: template) |
2. Enable callback_permission_status | Automatically prompt for permission when a user calls you (whether you answer or miss) |
| 3. User grants permanent permission via business profile | User-driven — they navigate to your business profile and toggle on calling permission |
Request Limits
Per business + WhatsApp user pair (these are designed to protect users from spam):
| Limit | Production | Sandbox / Test |
|---|---|---|
| Permission requests per day | 1 | 25 |
| Permission requests per 7 days | 2 | 100 |
Limits reset when any connected call (BIC or UIC) happens between you and that user. They apply to both free-form and template permission requests combined.
Sending these messages also costs you — call permission request messages are subject to standard messaging charges.
Free-Form Call Permission Request
Use during an open CSW. Header and footer are not supported on free-form variants.
POST /<PHONE_NUMBER_ID>/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "12015550123",
"type": "interactive",
"interactive": {
"type": "call_permission_request",
"action": { "name": "call_permission_request" },
"body": {
"text": "We would like to call you to help support your query on Order No: ON-12853."
}
}
}
body is technically optional but strongly recommended — without context, users decline. The call_permission_request interactive object itself cannot be customized; only the body text is yours.
Note: sending this to users on older app versions returns error 131026.
Template Call Permission Request
Use outside an open CSW (or whenever you'd prefer a templated approach). Templates support header, body, and footer. Body is required.
Create the template:
POST /<WABA_ID>/message_templates
{
"name": "sample_cpr_template",
"language": "en",
"category": "MARKETING",
"components": [
{
"type": "HEADER",
"text": "Support of Order No: {{1}}",
"example": { "body_text": [["ON-12345"]] }
},
{
"type": "BODY",
"text": "We would like to call you to help support your query on Order No: {{1}} for the item {{2}}.",
"example": { "body_text": [["ON-12345", "Avocados"]] }
},
{ "type": "FOOTER", "text": "Talk to you soon!" },
{ "type": "call_permission_request" }
]
}
Category must be MARKETING or UTILITY. The call_permission_request component cannot be combined with other interactive components.
Send the template:
POST /<PHONE_NUMBER_ID>/messages
{
"messaging_product": "whatsapp",
"to": "12015550123",
"type": "template",
"template": {
"name": "sample_cpr_template",
"language": { "code": "en" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "John Smith" },
{ "type": "text", "text": "order #1522" }
]
}
]
}
}
Template-based call permission requests are also covered as a category-specialty template in Marketing Messages and Utility Messages.
Callback Permission (User Calls You)
When callback_permission_status: ENABLED on the phone number's call settings, the WhatsApp client automatically prompts the user with a call permission request after they call you (whether you picked up or missed it). The permission flows back via the permission reply webhook with response_source: automatic.
This is the lowest-friction way to obtain permission for businesses that primarily receive calls and want to follow up.
Permanent Permission from Business Profile
Users can grant permanent calling permission to a business at any time through the business's WhatsApp profile. This is user-driven — there's no API to nudge them toward this UI.
When granted this way, you receive a permission reply webhook with no context.id (since it wasn't in response to a request) and is_permanent: true.
Get Call Permission State
GET /<PHONE_NUMBER_ID>/call_permissions?user_wa_id=<USER_WHATSAPP_ID>
Returns the current permission state plus the rate-limit budget for sending another permission request and placing a new call to that user.
{
"messaging_product": "whatsapp",
"permission": {
"status": "temporary",
"expiration_time": 1745343479
},
"actions": [
{
"action_name": "send_call_permission_request",
"can_perform_action": true,
"limits": [
{ "time_period": "PT24H", "max_allowed": 1, "current_usage": 0 },
{ "time_period": "P7D", "max_allowed": 2, "current_usage": 1 }
]
},
{
"action_name": "start_call",
"can_perform_action": false,
"limits": [
{
"time_period": "PT24H",
"max_allowed": 5,
"current_usage": 5,
"limit_expiration_time": 1745622600
}
]
}
]
}
| Field | Notes |
|---|---|
permission.status | no_permission, temporary, or permanent |
permission.expiration_time | Unix timestamp when temporary permission expires. Absent when permanent. |
actions[].action_name | send_call_permission_request (sending another request) or start_call (placing a new call) |
actions[].can_perform_action | Whether the action is currently allowed by all applicable limits |
limits[].time_period | ISO 8601 duration: PT24H = 24 hours, P7D = 7 days |
limits[].limit_expiration_time | Unix timestamp when the limit resets. Only present if current_usage has hit max_allowed. |
Rate limit on this endpoint itself: 100 requests per second. If the user phone number is uncallable for any reason (not on WhatsApp, etc.), the response returns no_permission.
User Call Permission Reply Webhook
Fires whenever the user accepts, rejects, or has their permission auto-revoked. Includes whether the response was permanent and the source.
{
"messages": [
{
"from": "12015550123",
"id": "wamid.sH0kFlaCGg0xcvZbgmg90lHrg2dL",
"timestamp": "1767168000",
"context": {
"from": "12015550123",
"id": "wamid.gBGGFlaCmZ9plHrf2Mh-o"
},
"interactive": {
"type": "call_permission_reply",
"call_permission_reply": {
"response": "accept",
"is_permanent": false,
"expiration_timestamp": "1768550400",
"response_source": "user_action"
}
}
}
]
}
| Field | Values | Notes |
|---|---|---|
response | accept or reject | |
is_permanent | true or false | Always false for temporary; true for permanent. Absent on rejects. |
expiration_timestamp | Unix timestamp | Present only for accepts of temporary permissions |
response_source | user_action or automatic | automatic = callback permission auto-granted on user-initiated call, or auto-revoked after consecutive unanswered calls |
context.id | wamid. of permission request, or wacid. of missed call, or absent | Tells you what triggered the response. Absent when user grants from business profile. |
No webhook fires when a temporary permission expires naturally — use the expiration_timestamp you received on the accept webhook, or query the permission state endpoint.
Common scenarios:
| Scenario | response | is_permanent | response_source | context.id |
|---|---|---|---|---|
| User accepts temporary from request message | accept | false | user_action | wamid. of request |
| User accepts permanent from request message | accept | true | user_action | wamid. of request |
| User accepts permanent from business profile | accept | true | user_action | absent |
| User rejects from request message | reject | absent | user_action | wamid. of request |
| Auto-permission via callback (user called you) | accept | false | automatic | wacid. of missed call |
| Auto-revoked after 4 unanswered BIC | reject | absent | automatic | absent |
Automatic Revocation (Unanswered Calls)
| Consecutive unanswered BIC calls | Effect |
|---|---|
| 2 | System message in WhatsApp asks the user to reconsider their permission |
| 4 | Permission auto-revoked. You receive a permission reply webhook with response: reject, response_source: automatic |
After auto-revoke, you'd need to send a new permission request to call again. Sandbox accounts have relaxed thresholds (5 / 10 instead of 2 / 4).
Permission Request Expiration
A pending request (sent but not yet responded to) expires when any of these happen:
- The user interacts with a subsequent new permission request from you (the prior one auto-expires).
- 7 days after the user accepts or declines (i.e. the granted permission expires, not the request).
- 7 days after delivery if the user never responds.