WhatsApp Business API
1MSG.IO is the official WhatsApp Business API for sending messages, receiving webhooks, and managing your channel.
Authentication. Every request needs your channel token from the channel page in the dashboard. Do not share it.
Pass the token in one of these places (the API checks body, then query, then header):
- JSON body field
token(POST) - Query string
?token= - Header
Authorization: Bearer <token>— preferred in production (it is not written to access logs)
URL. https://api.1msg.io/{channelId}/<method>
Session window. All send* methods except /sendTemplate (and order-details templates) require an open 24-hour customer service window with the recipient.
Quick start: https://help.1msg.io/platform-1msg/getting-start/quick-start
Channel
Manage your WhatsApp Business API channel
Webhooks
Configure the URL that receives inbound WhatsApp events, and inspect the callback payloads (messages, ACKs, groups, coexistence echoes, calls).
Messaging
This part of the documentation describes how to send and receive messages using the WhatsApp Business API
- Send List Message POST
- Send Reply Buttons Message POST
- Send Location Request Message POST
- Send WhatsApp Flow Message POST
- Send Reaction POST
- Send a File POST
- Send a Sticker POST
- Send CTA URL Button POST
- Send a Message POST
- Send a Location POST
- Send a Contact POST
- Send Carousel POST
- Send address request (India only) POST
- Send order details (India payments template) POST
- Send payment request POST
- Get messages list GET
- Mark message as read (optional typing) POST
Users
Block, unblock, and list blocked WhatsApp users
Groups
Manage WhatsApp group chats
Templates
Template messaging via WhatsApp Business API
Products & Catalogs
How to build and send messages with single and multiple products.
You can send product cards via Carousel in two ways:
Template messages: do not require a 24-hour customer service window between you and the recipient. Use sendTemplate.
Free-form messages: can be sent only when a customer service window is open between you and the recipient. Use sendCarousel.
The message structure in /sendCarousel is largely similar to sending a template. However, in this case you must explicitly specify all elements that are created in advance when working with templates. This is because the message is sent without using a template.
In /sendCarousel, for sending a Catalog Carousel there can be either 1 URL button or one or more quick reply buttons.
Catalog
Catalog and cart commerce settings (GET/POST /commerce).
GET response fields: id (catalog id), is_cart_enabled, is_catalog_visible.
POST body: { "params": { "is_cart_enabled": boolean, "is_catalog_visible": boolean } }.
Media
Use the media node to upload, retrieve, or delete media
Template Analytics
Limitations
- Button click analytics are available only for MARKETING and UTILITY template categories.
- WhatsApp Business accounts owned by or shared with Meta Business Accounts in the European Union (EU), United Kingdom (UK), and Japan, as well as accounts with a business phone number containing the country code of the UK, Japan, or an EU country/region, are not supported.
- Read and click event data for WhatsApp template messages is available only for 7 days from the date the message was sent. After this 7-day period, the respective read and click counters are zeroed out, and no further updates are recorded for those messages.
WhatsApp Flows
Manage WhatsApp Flow lifecycle: create, preview, publish, deprecate.
A Flow that loads screens from your server needs two things 1msg does not host: a signed business public key on the phone number, and an endpointUri on your HTTPS server. Data-channel requests are not delivered to the channel webhook.
Business public key
Generate a 2048-bit RSA pair. Keep private.pem on your server. Never send it to 1msg.
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pemUpload the contents of public.pem with POST /whatsapp_business_encryption. Then call GET /whatsapp_business_encryption:
VALID— the signature matches the stored key. This does not prove your endpoint works.MISMATCH— the stored key and the signature do not match. Upload the public key again.
One key is active per number. A new upload replaces the previous key.
endpointUri
Set endpointUri on create or with PATCH /flows/{flowId}/metadata. It is your URL, not a 1msg method.
WhatsApp POSTs encrypted_flow_data, encrypted_aes_key, and initial_vector. Decrypt encrypted_aes_key with private.pem (RSA-OAEP, SHA-256), then the body with AES-128-GCM. The response is a base64 string with Content-Type: text/plain, encrypted with the same AES key and the IV after inverting every byte. If decryption fails, respond HTTP 421 so the WhatsApp app fetches the public key again.
The same URL receives the service ping (decrypted response {"data":{"status":"active"}}). Those requests are not sent to the channel webhook. When the form is submitted, the result arrives on the channel webhookUrl: messages[].interactive.type = nfm_reply.
- Get WhatsApp Flows List GET
- Create WhatsApp Flow POST
- Get WhatsApp Flow Details GET
- Delete WhatsApp Flow (draft only) DELETE
- Update WhatsApp Flow Metadata PATCH
- Update WhatsApp Flow JSON PATCH
- Get WhatsApp Flow Preview GET
- Publish WhatsApp Flow POST
- Deprecate WhatsApp Flow POST
- Get business encryption public key GET
- Set business encryption public key POST
Calling
WhatsApp Calling API (beta) — VoIP signaling proxy.
1msg does not host media, store call history, or store recordings. You need your own WebRTC or SIP stack.
Prerequisites
- Meta Calling enabled on the number (Cloud API; not COEX)
- Paid channel — trial /
subscriptionBlocked→ 403 plain text - Webhook URL configured (
POST /webhook) forcallsevents
Inbound (user → business)
- Webhook
type=calls,event=connect— takecall_id+ SDP offer - Optional:
POST /initiateCallaction=pre_accept+ WebRTC answer SDP action=accept+ WebRTC answer SDP, oraction=reject- Later
event=terminate, oraction=terminateto hang up
Answer within ~30–60s or Meta ends as unanswered.
Critical: accept / pre_accept need a WebRTC-generated SDP answer.
Do not echo Meta's offer. Postman/curl alone cannot establish real media.
Outbound (business → user)
- Send Call Permission Request (CPR) — template or interactive
- Wait for permission reply on the messages webhook (
call_permission_reply) POST /initiateCallaction=connect+ business SDP offer- Apply Meta's SDP answer from the
callsconnect webhook
Meta limits (summary): permission ~7 days; up to 5 calls / 24h / user; max 2 CPR / 7 days; auto-revoke after 4 unanswered.
Webhooks (type=calls)
Passthrough of Meta field=calls plus type, instanceId.
Events: connect (offer or answer SDP), statuses (RINGING / ACCEPTED /
REJECTED), terminate. CPR replies use the messages path, not type=calls.
See operations below for request bodies and examples.
