Msgera API Reference
A production-ready reference for sending WhatsApp messages, managing contacts, launching campaigns, and streaming delivery events from one consistent HTTP API.
Auth
API key
Format
JSON
Retries
Webhook-safe
Latency
Async sends
- Endpoints
- 49
- Groups
- 12
- Base path
- /v1
Connection details
Use these values for every request.
Base URL
https://api.msgera.com/v1Auth Header
X-API-Key: wak_your_api_key_hereGlobal Rules
- Authenticate with the X-API-Key header.
- Device-scoped endpoints take deviceUid in the request body.
- Unknown request properties are rejected.
- Phone format must match +?[0-9]{7,15}.
- Dates must be ISO 8601.
- Max file size is 16 MB per upload.
- Spintax syntax uses {option1|option2|option3}.
- Account safety: each device (WhatsApp account) has daily, hourly, and per-minute send budgets. Limits apply to direct sends and campaigns — check GET /developer/devices/:deviceUid → safety before bulk sending.
- TEXT campaigns with multiple recipients require enough unique spintax variants (default: one variant per 8 recipients).
- Campaign audiences: provide at least one of contactGroupIds, tagIds, or phoneNumbers. You may combine all three in one campaign; recipients are deduplicated by phone.
- Contact groups and tags use Authorization: Bearer (dashboard session JWT). Create and manage them via /v1/contact-groups and /v1/contact-tags, then reference their UUIDs in POST /v1/developer/campaigns.
Create an API key
Generate a key in the dashboard and send it as X-API-Key.
Pick a device
List devices, copy deviceUid, and check safety.dailyRemaining before bulk sends.
Send or automate
Send a direct message, schedule a send, or launch a campaign.
Track events
Use message history and webhooks to reconcile delivery states.
API docs workspace
49 endpoints across 12 feature groups
https://api.msgera.com/v1Overview
A practical tour of what you can do with the API — written for engineers and non-engineers alike.
Msgera lets your apps talk to WhatsApp through one consistent HTTP API. Whether you're sending a single message, running a marketing campaign, syncing contacts, or hooking real-time events into your own backend, every endpoint speaks the same JSON over the same auth model.
Send your first message
Text, media, and voice messages from a connected device.
Manage contacts and groups
Create and list contacts via the developer API.
Contact groups & tags
Segment audiences (session auth), import CSV, assign members — use IDs in campaigns.
Run automated campaigns
Scheduled bulk sends with delivery tracking.
Listen with webhooks
Real-time events for incoming messages and status updates.
Account safety limits
Per-device send budgets, burst caps, and campaign variant rules.
Production shape
Every endpoint uses the same auth header, JSON error envelope, owner-scoped resources, and paginated list shape where applicable.
Authentication is a single header — `X-API-Key` — generated from your developer dashboard. Every request is scoped to your account, and resources you don't own simply do not appear.
curl "https://api.msgera.com/v1/developer/devices" \
-H "X-API-Key: wak_your_api_key_here"API Keys
Create and manage integration credentials.
GET
Request Examples
curl -X GET "https://api.msgera.com/v1/api-keys" \
-H "X-API-Key: wak_your_api_key_here"Responses
{
"data": [{ "id": "uuid", "name": "My API Key", "isActive": true }],
"total": 1
}Status Codes
Success
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
POST/v1/api-keysCreates a new API key and returns the raw key one time.
0 required1 response
/v1/api-keysCreates a new API key and returns the raw key one time.
Request Fields
name
Optionalstring • body
Friendly key label (1-100 chars).
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| name | string | body | No | Friendly key label (1-100 chars). |
Request Body
{
"name": "CI key"
}Request Examples
curl -X POST "https://api.msgera.com/v1/api-keys" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "CI key"
}'Responses
{
"id": "uuid",
"name": "CI key",
"key": "wak_abcdef1234567890...",
"isActive": true
}Status Codes
Created
Bad Request - invalid input
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 201 | Created |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
DELETE
Request Fields
id
Requiredstring • path
API key id.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| id | string | path | Yes | API key id. |
Request Examples
curl -X DELETE "https://api.msgera.com/v1/api-keys/{id}" \
-H "X-API-Key: wak_your_api_key_here"Responses
{ "deleted": true }Status Codes
Success
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
Devices
Read linked WhatsApp devices and per-device send safety budgets (daily warm-up tier, hourly/minute burst caps).
GET/v1/developer/devicesReturns all linked devices with a safety object on each item. Use safety.canSend and safety.dailyRemaining before campaigns or high-volume sends.
0 required1 response
/v1/developer/devicesReturns all linked devices with a safety object on each item. Use safety.canSend and safety.dailyRemaining before campaigns or high-volume sends.
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/devices" \
-H "X-API-Key: wak_your_api_key_here"Responses
{
"items": [{
"deviceUid": "dev_ABCD1234",
"name": "My WhatsApp",
"status": "CONNECTED",
"phone": "+1234567890",
"createdAt": "2026-05-20T10:00:00.000Z",
"safety": {
"dailyLimit": 25,
"dailySent": 9,
"dailyRemaining": 16,
"hourlyLimit": 25,
"hourlySent": 0,
"hourlyRemaining": 25,
"minuteLimit": 5,
"minuteSent": 0,
"minuteRemaining": 5,
"accountAgeDays": 2,
"canSend": true,
"blockedReason": null,
"resetsAt": "2026-05-23T23:59:59.999Z",
"campaignDelayMinSec": 18,
"campaignDelayMaxSec": 50,
"variantRecipientsPerVariant": 8
}
}]
}Status Codes
Success
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
GET/v1/developer/devices/:deviceUidReturns one device by UID, including the same safety snapshot as the list endpoint.
1 required1 response
/v1/developer/devices/:deviceUidReturns one device by UID, including the same safety snapshot as the list endpoint.
Request Fields
deviceUid
Requiredstring • path
Device unique id.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| deviceUid | string | path | Yes | Device unique id. |
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/devices/{deviceUid}" \
-H "X-API-Key: wak_your_api_key_here"Responses
{
"deviceUid": "dev_ABCD1234",
"name": "My WhatsApp",
"status": "CONNECTED",
"phone": "+1234567890",
"createdAt": "2026-05-20T10:00:00.000Z",
"safety": {
"dailyLimit": 25,
"dailySent": 9,
"dailyRemaining": 16,
"hourlyLimit": 25,
"hourlySent": 0,
"hourlyRemaining": 25,
"minuteLimit": 5,
"minuteSent": 0,
"minuteRemaining": 5,
"accountAgeDays": 2,
"canSend": true,
"blockedReason": null,
"resetsAt": "2026-05-23T23:59:59.999Z",
"campaignDelayMinSec": 18,
"campaignDelayMaxSec": 50,
"variantRecipientsPerVariant": 8
}
}Status Codes
Success
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
Messaging
Send and inspect outbound messages. Each send counts against the device's account safety limits (not campaign-only).
POST/v1/developer/messages/sendSends a text message through a selected device. Counts toward the device safety daily/hourly/minute counters. Call GET /developer/devices/:deviceUid first to read safety.dailyRemaining.
3 required2 responses
/v1/developer/messages/sendSends a text message through a selected device. Counts toward the device safety daily/hourly/minute counters. Call GET /developer/devices/:deviceUid first to read safety.dailyRemaining.
Request Fields
deviceUid
Requiredstring • body
Sender device UID.
to
Requiredstring • body
Recipient phone number.
text
Requiredstring • body
Message text.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| deviceUid | string | body | Yes | Sender device UID. |
| to | string | body | Yes | Recipient phone number. |
| text | string | body | Yes | Message text. |
Request Body
{
"deviceUid": "dev_4f8c2a1e",
"to": "+1234567890",
"text": "Hello from API!"
}Request Examples
curl -X POST "https://api.msgera.com/v1/developer/messages/send" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"deviceUid": "dev_4f8c2a1e",
"to": "+1234567890",
"text": "Hello from API!"
}'Responses
{
"accepted": true,
"providerMessageId": "msg_abc123",
"sessionId": "session_xyz",
"messageId": "uuid"
}{
"statusCode": 429,
"error": "Account Send Limit",
"message": "Daily account safety limit reached (25 messages per day for accounts at this age). Try again after 2026-05-23T23:59:59.999Z.",
"accountId": "uuid",
"resetsAt": "2026-05-23T23:59:59.999Z"
}Status Codes
Success
Bad Request - invalid input
Unauthorized - missing or invalid API key
Too Many Requests - account send limit (daily/hourly/minute) or user anti-spam pause. Account limit errors use error Account Send Limit and include accountId and resetsAt when applicable.
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 429 | Too Many Requests - account send limit (daily/hourly/minute) or user anti-spam pause. Account limit errors use error Account Send Limit and include accountId and resetsAt when applicable. |
| 500 | Internal Server Error |
POST/v1/developer/messages/send-mediaSends a media message using a media asset. Subject to the same per-device safety limits as send text.
3 required2 responses
/v1/developer/messages/send-mediaSends a media message using a media asset. Subject to the same per-device safety limits as send text.
Request Fields
deviceUid
Requiredstring • body
Sender device UID.
to
Requiredstring • body
Recipient phone number.
mediaId
Requiredstring • body
Uploaded media id.
caption
Optionalstring • body
Optional media caption.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| deviceUid | string | body | Yes | Sender device UID. |
| to | string | body | Yes | Recipient phone number. |
| mediaId | string | body | Yes | Uploaded media id. |
| caption | string | body | No | Optional media caption. |
Request Body
{
"deviceUid": "dev_4f8c2a1e",
"to": "+1234567890",
"mediaId": "media_uuid",
"caption": "Check this out!"
}Request Examples
curl -X POST "https://api.msgera.com/v1/developer/messages/send-media" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"deviceUid": "dev_4f8c2a1e",
"to": "+1234567890",
"mediaId": "media_uuid",
"caption": "Check this out!"
}'Responses
{ "accepted": true, "messageId": "uuid" }{
"statusCode": 429,
"error": "Account Send Limit",
"message": "Daily account safety limit reached (25 messages per day for accounts at this age). Try again after 2026-05-23T23:59:59.999Z.",
"accountId": "uuid",
"resetsAt": "2026-05-23T23:59:59.999Z"
}Status Codes
Success
Bad Request - invalid input
Unauthorized - missing or invalid API key
Too Many Requests - account send limit (daily/hourly/minute) or user anti-spam pause. Account limit errors use error Account Send Limit and include accountId and resetsAt when applicable.
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 429 | Too Many Requests - account send limit (daily/hourly/minute) or user anti-spam pause. Account limit errors use error Account Send Limit and include accountId and resetsAt when applicable. |
| 500 | Internal Server Error |
POST/v1/developer/messages/send-voiceSends an uploaded audio file as a voice message. Subject to the same per-device safety limits as send text.
3 required2 responses
/v1/developer/messages/send-voiceSends an uploaded audio file as a voice message. Subject to the same per-device safety limits as send text.
Request Fields
deviceUid
Requiredstring • body
Sender device UID.
to
Requiredstring • body
Recipient phone number.
mediaId
Requiredstring • body
Audio media id.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| deviceUid | string | body | Yes | Sender device UID. |
| to | string | body | Yes | Recipient phone number. |
| mediaId | string | body | Yes | Audio media id. |
Request Body
{
"deviceUid": "dev_4f8c2a1e",
"to": "+1234567890",
"mediaId": "media_uuid"
}Request Examples
curl -X POST "https://api.msgera.com/v1/developer/messages/send-voice" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"deviceUid": "dev_4f8c2a1e",
"to": "+1234567890",
"mediaId": "media_uuid"
}'Responses
{ "accepted": true, "messageId": "uuid" }{
"statusCode": 429,
"error": "Account Send Limit",
"message": "Daily account safety limit reached (25 messages per day for accounts at this age). Try again after 2026-05-23T23:59:59.999Z.",
"accountId": "uuid",
"resetsAt": "2026-05-23T23:59:59.999Z"
}Status Codes
Success
Bad Request - invalid input
Unauthorized - missing or invalid API key
Too Many Requests - account send limit (daily/hourly/minute) or user anti-spam pause. Account limit errors use error Account Send Limit and include accountId and resetsAt when applicable.
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 429 | Too Many Requests - account send limit (daily/hourly/minute) or user anti-spam pause. Account limit errors use error Account Send Limit and include accountId and resetsAt when applicable. |
| 500 | Internal Server Error |
POST/v1/developer/messages/check-whatsappChecks whether each provided phone number is registered on WhatsApp. Baileys (linked-device) accounts only. Up to 50 numbers per call. Does not consume the per-minute send rate limit.
2 required1 response
/v1/developer/messages/check-whatsappChecks whether each provided phone number is registered on WhatsApp. Baileys (linked-device) accounts only. Up to 50 numbers per call. Does not consume the per-minute send rate limit.
Request Fields
deviceUid
Requiredstring • body
Sender device UID (must be a Baileys device in CONNECTED state).
numbers
Requiredstring[] • body
1–50 phone numbers in international format (e.g. +15551234567).
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| deviceUid | string | body | Yes | Sender device UID (must be a Baileys device in CONNECTED state). |
| numbers | string[] | body | Yes | 1–50 phone numbers in international format (e.g. +15551234567). |
Request Body
{
"deviceUid": "dev_4f8c2a1e",
"numbers": ["+15551234567", "+19999999999"]
}Request Examples
curl -X POST "https://api.msgera.com/v1/developer/messages/check-whatsapp" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"deviceUid": "dev_4f8c2a1e",
"numbers": ["+15551234567", "+19999999999"]
}'Responses
{
"results": [
{ "phone": "+15551234567", "exists": true },
{ "phone": "+19999999999", "exists": false }
]
}Status Codes
Success
Bad Request - invalid input
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
GET
Request Fields
deviceUid
Optionalstring • query
Filter by device UID.
to
Optionalstring • query
Filter by recipient number.
page
Optionalnumber • query
Page number.
limit
Optionalnumber • query
Items per page.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| deviceUid | string | query | No | Filter by device UID. |
| to | string | query | No | Filter by recipient number. |
| page | number | query | No | Page number. |
| limit | number | query | No | Items per page. |
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/messages" \
-H "X-API-Key: wak_your_api_key_here"Responses
{ "data": [{ "id": "uuid", "status": "DELIVERED" }], "total": 100, "page": 1, "limit": 20 }Status Codes
Success
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
GET
Request Fields
id
Requiredstring • path
Message id.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| id | string | path | Yes | Message id. |
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/messages/{id}" \
-H "X-API-Key: wak_your_api_key_here"Responses
{ "id": "uuid", "messageType": "TEXT", "status": "DELIVERED" }Status Codes
Success
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
Media
Upload and manage media assets.
POST/v1/developer/media/uploadUploads one media file using multipart/form-data.
1 required1 response
/v1/developer/media/uploadUploads one media file using multipart/form-data.
Request Fields
file
Requiredbinary • body
Uploaded file binary.
kind
Optionalstring • query
image|video|audio|document.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| file | binary | body | Yes | Uploaded file binary. |
| kind | string | query | No | image|video|audio|document. |
Request Examples
curl -X POST "https://api.msgera.com/v1/developer/media/upload" \
-H "X-API-Key: wak_your_api_key_here"Responses
{ "id": "uuid", "kind": "image", "mimeType": "image/jpeg" }Status Codes
Created
Bad Request - invalid input
Unauthorized - missing or invalid API key
Too Many Requests - account send limit (daily/hourly/minute) or user anti-spam pause. Account limit errors use error Account Send Limit and include accountId and resetsAt when applicable.
Internal Server Error
| Code | Description |
|---|---|
| 201 | Created |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 429 | Too Many Requests - account send limit (daily/hourly/minute) or user anti-spam pause. Account limit errors use error Account Send Limit and include accountId and resetsAt when applicable. |
| 500 | Internal Server Error |
GET
Request Fields
page
Optionalnumber • query
Page number.
limit
Optionalnumber • query
Items per page.
kind
Optionalstring • query
Media type filter.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| page | number | query | No | Page number. |
| limit | number | query | No | Items per page. |
| kind | string | query | No | Media type filter. |
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/media" \
-H "X-API-Key: wak_your_api_key_here"Responses
{ "data": [{ "id": "uuid", "kind": "image" }], "total": 10 }Status Codes
Success
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
GET
Request Fields
id
Requiredstring • path
Media id.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| id | string | path | Yes | Media id. |
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/media/{id}" \
-H "X-API-Key: wak_your_api_key_here"Responses
{ "id": "uuid", "downloadUrl": "/v1/media/uuid/download" }Status Codes
Success
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
DELETE
Request Fields
id
Requiredstring • path
Media id.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| id | string | path | Yes | Media id. |
Request Examples
curl -X DELETE "https://api.msgera.com/v1/developer/media/{id}" \
-H "X-API-Key: wak_your_api_key_here"Responses
{}Status Codes
No Content
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 204 | No Content |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
Campaigns
Create, monitor, and control campaign sends. Audiences may combine contactGroupIds, tagIds, and phoneNumbers in one request; recipients are deduplicated by phone. Groups and tags are managed under Contact Groups & Tags (Bearer auth); pass their UUIDs here. Campaigns share per-device safety budgets with direct messages and enforce spintax variant rules for TEXT audiences. Multi-device campaigns return accounts[] on GET :id; recipients include accountId, accountName, accountPhone.
POST/v1/developer/campaignsCreates and starts a campaign unless scheduled/recurring. At least one audience source is required; you may send contactGroupIds, tagIds, and phoneNumbers together (deduplicated). TEXT campaigns need ceil(recipients / 8) unique spintax variants. Audiences may exceed dailyRemaining — sends drip across UTC days. Use deviceUids for parallel multi-account sends (round-robin recipients).
3 required2 responses
/v1/developer/campaignsCreates and starts a campaign unless scheduled/recurring. At least one audience source is required; you may send contactGroupIds, tagIds, and phoneNumbers together (deduplicated). TEXT campaigns need ceil(recipients / 8) unique spintax variants. Audiences may exceed dailyRemaining — sends drip across UTC days. Use deviceUids for parallel multi-account sends (round-robin recipients).
Request Fields
deviceUid
Requiredstring • body
Primary sender device UID (first parallel lane).
deviceUids
Optionalstring[] • body
Additional device UIDs for parallel sending. Include deviceUid; recipients are split round-robin across lanes.
name
Requiredstring • body
Campaign name.
text
Requiredstring • body
Message body. Use spintax {A|B|C} for account safety when sending to multiple recipients.
spintaxTemplate
Optionalstring • body
Optional separate spintax template. Variant count is validated against audience size.
contactGroupIds
Optionalstring[] • body
UUIDs from GET /v1/contact-groups (Bearer auth). All contacts in these groups are included.
tagIds
Optionalstring[] • body
UUIDs from GET /v1/contact-tags (Bearer auth). All contacts with these tags are included.
phoneNumbers
Optionalstring[] • body
Individual E.164 phone numbers (+?[0-9]{7,15}). Use for specific contacts without a group/tag, or numbers not yet in your address book.
messageType
Optionalstring • body
TEXT|MEDIA|VOICE. Variant rules apply to TEXT only.
scheduledAt
Optionalstring • body
ISO date for scheduled send.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| deviceUid | string | body | Yes | Primary sender device UID (first parallel lane). |
| deviceUids | string[] | body | No | Additional device UIDs for parallel sending. Include deviceUid; recipients are split round-robin across lanes. |
| name | string | body | Yes | Campaign name. |
| text | string | body | Yes | Message body. Use spintax {A|B|C} for account safety when sending to multiple recipients. |
| spintaxTemplate | string | body | No | Optional separate spintax template. Variant count is validated against audience size. |
| contactGroupIds | string[] | body | No | UUIDs from GET /v1/contact-groups (Bearer auth). All contacts in these groups are included. |
| tagIds | string[] | body | No | UUIDs from GET /v1/contact-tags (Bearer auth). All contacts with these tags are included. |
| phoneNumbers | string[] | body | No | Individual E.164 phone numbers (+?[0-9]{7,15}). Use for specific contacts without a group/tag, or numbers not yet in your address book. |
| messageType | string | body | No | TEXT|MEDIA|VOICE. Variant rules apply to TEXT only. |
| scheduledAt | string | body | No | ISO date for scheduled send. |
Request Body
{
"deviceUid": "dev_4f8c2a1e",
"name": "Summer Sale",
"text": "{Hi|Hello} {name}! Check out our deals.",
"contactGroupIds": ["group-uuid-vip"],
"tagIds": ["tag-uuid-leads"],
"phoneNumbers": ["+1234567890"]
}Request Examples
curl -X POST "https://api.msgera.com/v1/developer/campaigns" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"deviceUid": "dev_4f8c2a1e",
"name": "Summer Sale",
"text": "{Hi|Hello} {name}! Check out our deals.",
"contactGroupIds": ["group-uuid-vip"],
"tagIds": ["tag-uuid-leads"],
"phoneNumbers": ["+1234567890"]
}'Responses
{
"id": "uuid",
"status": "RUNNING",
"totalRecipients": 150,
"accountIds": ["acc_1", "acc_2"],
"accounts": [
{ "id": "acc_1", "name": "Sales Line 1", "phone": "+12025550101" },
{ "id": "acc_2", "name": "Sales Line 2", "phone": "+12025550102" }
],
"estimatedCompletionAt": "2026-05-26T14:30:00.000Z",
"estimatedCompletion": {
"startsAt": "2026-05-22T10:00:00.000Z",
"estimatedCompletionAt": "2026-05-26T14:30:00.000Z",
"estimatedDurationLabel": "~4 days",
"calendarDaysSpanned": 4,
"accountCount": 1
}
}{
"statusCode": 400,
"message": "Account safety: this campaign has 80 recipients but only 3 unique message variant(s). Provide at least 10 variants (one per every 8 recipients) using spintax like {Hello|Hi|Hey} or separate message options in your template."
}Status Codes
Created
Bad Request - invalid input
Unauthorized - missing or invalid API key
Conflict - duplicate resource
Internal Server Error
| Code | Description |
|---|---|
| 201 | Created |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 409 | Conflict - duplicate resource |
| 500 | Internal Server Error |
GET
Request Fields
parentOnly
Optionalboolean • query
Show only parent campaigns.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| parentOnly | boolean | query | No | Show only parent campaigns. |
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/campaigns" \
-H "X-API-Key: wak_your_api_key_here"Responses
{ "data": [{ "id": "uuid", "status": "RUNNING" }], "total": 20 }Status Codes
Success
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
GET/v1/developer/campaigns/:idCampaign metadata for monitoring. Includes all send lanes (accounts), spintaxTemplate, text, and estimatedCompletionAt. Count unique TEXT variants from spintax in spintaxTemplate when set, otherwise text.
1 required1 response
/v1/developer/campaigns/:idCampaign metadata for monitoring. Includes all send lanes (accounts), spintaxTemplate, text, and estimatedCompletionAt. Count unique TEXT variants from spintax in spintaxTemplate when set, otherwise text.
Request Fields
id
Requiredstring • path
Campaign id.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| id | string | path | Yes | Campaign id. |
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/campaigns/{id}" \
-H "X-API-Key: wak_your_api_key_here"Responses
{
"id": "uuid",
"name": "Summer Sale",
"status": "RUNNING",
"accountId": "acc_1",
"accountIds": ["acc_1", "acc_2"],
"accountName": "Sales Line 1",
"accounts": [
{ "id": "acc_1", "name": "Sales Line 1", "phone": "+12025550101" },
{ "id": "acc_2", "name": "Sales Line 2", "phone": "+12025550102" }
],
"text": "{Hi|Hello} there!",
"spintaxTemplate": null,
"totalRecipients": 150,
"sentCount": 42,
"failedCount": 1,
"startedAt": "2026-05-22T10:00:00.000Z",
"completedAt": null,
"estimatedCompletionAt": "2026-05-23T18:30:00.000Z"
}Status Codes
Success
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
GET/v1/developer/campaigns/:id/progressLive counters while RUNNING. Includes estimatedCompletionAt and accountIds for multi-device campaigns.
1 required1 response
/v1/developer/campaigns/:id/progressLive counters while RUNNING. Includes estimatedCompletionAt and accountIds for multi-device campaigns.
Request Fields
id
Requiredstring • path
Campaign id.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| id | string | path | Yes | Campaign id. |
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/campaigns/{id}/progress" \
-H "X-API-Key: wak_your_api_key_here"Responses
{
"status": "RUNNING",
"totalRecipients": 150,
"sentCount": 42,
"failedCount": 1,
"pendingCount": 107,
"startedAt": "2026-05-22T10:00:00.000Z",
"completedAt": null,
"estimatedCompletionAt": "2026-05-23T18:30:00.000Z",
"accountIds": ["acc_1", "acc_2"]
}Status Codes
Success
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
GET/v1/developer/campaigns/:id/analyticsDelivery funnel (sent, delivered, read, failed, pending, rates) plus startedAt, completedAt, estimatedCompletionAt, and durationSec.
1 required1 response
/v1/developer/campaigns/:id/analyticsDelivery funnel (sent, delivered, read, failed, pending, rates) plus startedAt, completedAt, estimatedCompletionAt, and durationSec.
Request Fields
id
Requiredstring • path
Campaign id.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| id | string | path | Yes | Campaign id. |
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/campaigns/{id}/analytics" \
-H "X-API-Key: wak_your_api_key_here"Responses
{
"status": "RUNNING",
"totalRecipients": 150,
"sent": 42,
"delivered": 38,
"read": 12,
"failed": 1,
"pending": 107,
"deliveryRate": 90.5,
"readRate": 31.6,
"failureRate": 0.7,
"startedAt": "2026-05-22T10:00:00.000Z",
"completedAt": null,
"estimatedCompletionAt": "2026-05-23T18:30:00.000Z",
"durationSec": 3720
}Status Codes
Success
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
GET/v1/developer/campaigns/:id/recipientsPaginated per-recipient delivery state. Sorted: PENDING first (queue order), then SENT/DELIVERED/READ by sentAt ascending, then FAILED. Each row includes accountId, accountName, and accountPhone (assigned lane or account that sent after failover).
1 required1 response
/v1/developer/campaigns/:id/recipientsPaginated per-recipient delivery state. Sorted: PENDING first (queue order), then SENT/DELIVERED/READ by sentAt ascending, then FAILED. Each row includes accountId, accountName, and accountPhone (assigned lane or account that sent after failover).
Request Fields
id
Requiredstring • path
Campaign id.
page
Optionalnumber • query
Page number (default 1).
limit
Optionalnumber • query
Page size (default 20).
status
Optionalstring • query
Filter by messageStatus: PENDING|SENT|DELIVERED|READ|FAILED.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| id | string | path | Yes | Campaign id. |
| page | number | query | No | Page number (default 1). |
| limit | number | query | No | Page size (default 20). |
| status | string | query | No | Filter by messageStatus: PENDING|SENT|DELIVERED|READ|FAILED. |
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/campaigns/{id}/recipients" \
-H "X-API-Key: wak_your_api_key_here"Responses
{
"data": [
{
"id": "uuid",
"phone": "+1234567890",
"contactName": "Jane",
"accountId": "acc_2",
"accountName": "Sales Line 2",
"accountPhone": "+12025550102",
"messageStatus": "PENDING",
"status": "PENDING",
"sentAt": null,
"deliveredAt": null,
"readAt": null,
"failedAt": null,
"error": null
}
],
"total": 150,
"page": 1,
"limit": 20
}Status Codes
Success
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
POST/v1/developer/campaigns/:id/pause|resume|retry-failedCampaign control actions for runtime operations.
1 required1 response
/v1/developer/campaigns/:id/pause|resume|retry-failedCampaign control actions for runtime operations.
Request Fields
id
Requiredstring • path
Campaign id.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| id | string | path | Yes | Campaign id. |
Request Examples
curl -X POST "https://api.msgera.com/v1/developer/campaigns/{id}/pause" \
-H "X-API-Key: wak_your_api_key_here"Responses
{ "updated": true }Status Codes
Success
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
Contacts
Manage contact records via the developer API (X-API-Key). Use groupId or tagId filters to list members of a segment. Create groups/tags and assign membership with Contact Groups & Tags (Bearer auth), then target them in campaigns.
GET
Request Fields
search
Optionalstring • query
Search by name or phone.
groupId
Optionalstring • query
Filter by group.
tagId
Optionalstring • query
Filter by tag.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| search | string | query | No | Search by name or phone. |
| groupId | string | query | No | Filter by group. |
| tagId | string | query | No | Filter by tag. |
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/contacts" \
-H "X-API-Key: wak_your_api_key_here"Responses
{ "data": [{ "id": "uuid", "phone": "+1234567890" }], "total": 90 }Status Codes
Success
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
POST
Request Fields
phone
Requiredstring • body
Contact phone.
name
Optionalstring • body
Contact name.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| phone | string | body | Yes | Contact phone. |
| name | string | body | No | Contact name. |
Request Body
{
"phone": "+1234567890",
"name": "John Doe"
}Request Examples
curl -X POST "https://api.msgera.com/v1/developer/contacts" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phone": "+1234567890",
"name": "John Doe"
}'Responses
{ "id": "uuid", "phone": "+1234567890", "name": "John Doe" }Status Codes
Created
Bad Request - invalid input
Unauthorized - missing or invalid API key
Conflict - duplicate resource
Internal Server Error
| Code | Description |
|---|---|
| 201 | Created |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 409 | Conflict - duplicate resource |
| 500 | Internal Server Error |
PATCH/v1/developer/contacts/:idRead, modify, or delete a single contact.
1 required1 response
/v1/developer/contacts/:idRead, modify, or delete a single contact.
Request Fields
id
Requiredstring • path
Contact id.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| id | string | path | Yes | Contact id. |
Request Body
{
"phone": "+1234567890",
"name": "John Doe"
}Request Examples
curl -X PATCH "https://api.msgera.com/v1/developer/contacts/{id}" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phone": "+1234567890",
"name": "John Doe"
}'Responses
{ "id": "uuid", "phone": "+1234567890", "name": "John Doe" }Status Codes
Success
Bad Request - invalid input
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
Scheduled Messages
Schedule, update, and cancel future sends.
POST/v1/developer/scheduled-messagesCreates a scheduled message job.
4 required1 response
/v1/developer/scheduled-messagesCreates a scheduled message job.
Request Fields
deviceUid
Requiredstring • body
device UID.
to
Requiredstring • body
Recipient phone.
text
Requiredstring • body
Message text.
scheduledAt
Requiredstring • body
Future ISO date.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| deviceUid | string | body | Yes | device UID. |
| to | string | body | Yes | Recipient phone. |
| text | string | body | Yes | Message text. |
| scheduledAt | string | body | Yes | Future ISO date. |
Request Body
{
"deviceUid": "dev_4f8c2a1e",
"to": "+1234567890",
"text": "Reminder: your meeting is tomorrow",
"scheduledAt": "2024-12-25T10:00:00Z"
}Request Examples
curl -X POST "https://api.msgera.com/v1/developer/scheduled-messages" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"deviceUid": "dev_4f8c2a1e",
"to": "+1234567890",
"text": "Reminder: your meeting is tomorrow",
"scheduledAt": "2024-12-25T10:00:00Z"
}'Responses
{ "id": "uuid", "status": "PENDING" }Status Codes
Created
Bad Request - invalid input
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 201 | Created |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
GET/v1/developer/scheduled-messagesFull lifecycle operations for scheduled records.
0 required1 response
/v1/developer/scheduled-messagesFull lifecycle operations for scheduled records.
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/scheduled-messages" \
-H "X-API-Key: wak_your_api_key_here"Responses
{ "data": [{ "id": "uuid", "status": "PENDING" }], "total": 10 }Status Codes
Success
Bad Request - invalid input
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
Auto-Reply Rules
Define keyword-based response automation.
GET
Request Fields
deviceUid
Requiredstring • query
device UID filter.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| deviceUid | string | query | Yes | device UID filter. |
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/auto-reply" \
-H "X-API-Key: wak_your_api_key_here"Responses
{ "data": [{ "id": "uuid", "triggerType": "CONTAINS" }], "total": 12 }Status Codes
Success
Bad Request - invalid input
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
POST/v1/developer/auto-reply|:idManage one rule with trigger and reply text.
4 required1 response
/v1/developer/auto-reply|:idManage one rule with trigger and reply text.
Request Fields
deviceUid
Requiredstring • body
Sender device UID for create requests.
triggerType
Requiredstring • body
CONTAINS|EXACT|STARTS_WITH|ENDS_WITH.
triggerValue
Requiredstring • body
Matching phrase.
replyText
Requiredstring • body
Auto-reply content.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| deviceUid | string | body | Yes | Sender device UID for create requests. |
| triggerType | string | body | Yes | CONTAINS|EXACT|STARTS_WITH|ENDS_WITH. |
| triggerValue | string | body | Yes | Matching phrase. |
| replyText | string | body | Yes | Auto-reply content. |
Request Body
{
"deviceUid": "dev_4f8c2a1e",
"triggerType": "CONTAINS",
"triggerValue": "price",
"replyText": "Our prices start at $15.99/mo."
}Request Examples
curl -X POST "https://api.msgera.com/v1/developer/auto-reply" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"deviceUid": "dev_4f8c2a1e",
"triggerType": "CONTAINS",
"triggerValue": "price",
"replyText": "Our prices start at $15.99/mo."
}'Responses
{ "id": "uuid", "enabled": true, "order": 0 }Status Codes
Success
Bad Request - invalid input
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
Webhooks
Configure outbound event delivery and history.
GET
Request Fields
deviceUid
Optionalstring • query
Optional device filter.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| deviceUid | string | query | No | Optional device filter. |
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/webhooks" \
-H "X-API-Key: wak_your_api_key_here"Responses
{ "data": [{ "id": "uuid", "isActive": true }] }Status Codes
Success
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
PUT/v1/developer/webhooksUpserts webhook config for a specific device.
1 required1 response
/v1/developer/webhooksUpserts webhook config for a specific device.
Request Fields
deviceUid
Requiredstring • body
device UID.
personalWebhookUrl
Optionalstring • body
Personal chat event URL.
groupWebhookUrl
Optionalstring • body
Group chat event URL.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| deviceUid | string | body | Yes | device UID. |
| personalWebhookUrl | string | body | No | Personal chat event URL. |
| groupWebhookUrl | string | body | No | Group chat event URL. |
Request Body
{
"deviceUid": "dev_4f8c2a1e",
"personalWebhookUrl": "https://example.com/webhook",
"groupWebhookUrl": "https://example.com/group-hook",
"isActive": true
}Request Examples
curl -X PUT "https://api.msgera.com/v1/developer/webhooks" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"deviceUid": "dev_4f8c2a1e",
"personalWebhookUrl": "https://example.com/webhook",
"groupWebhookUrl": "https://example.com/group-hook",
"isActive": true
}'Responses
{ "id": "uuid", "isActive": true }Status Codes
Success
Bad Request - invalid input
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
GET/v1/developer/webhooks/historyReturns delivery attempts with status and response code.
0 required1 response
/v1/developer/webhooks/historyReturns delivery attempts with status and response code.
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/webhooks/history" \
-H "X-API-Key: wak_your_api_key_here"Responses
{ "data": [{ "deliveryStatus": "SUCCESS", "responseStatusCode": 200 }], "total": 50 }Status Codes
Success
Bad Request - invalid input
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
WhatsApp Status
Post stories/status updates and read privacy settings.
POST
Request Fields
deviceUid
Requiredstring • body
Sender device UID.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| deviceUid | string | body | Yes | Sender device UID. |
Request Body
{
"deviceUid": "dev_4f8c2a1e",
"text": "Hello World!",
"backgroundColor": "#FF0000"
}Request Examples
curl -X POST "https://api.msgera.com/v1/developer/status/text" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"deviceUid": "dev_4f8c2a1e",
"text": "Hello World!",
"backgroundColor": "#FF0000"
}'Responses
{ "accepted": true }Status Codes
Success
Bad Request - invalid input
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
POST/v1/developer/status/mediaPublishes media status using uploaded media.
1 required1 response
/v1/developer/status/mediaPublishes media status using uploaded media.
Request Fields
deviceUid
Requiredstring • body
Sender device UID.
| Field | Type | Location | Required | Description |
|---|---|---|---|---|
| deviceUid | string | body | Yes | Sender device UID. |
Request Body
{
"deviceUid": "dev_4f8c2a1e",
"mediaId": "media_uuid",
"caption": "Check this out!"
}Request Examples
curl -X POST "https://api.msgera.com/v1/developer/status/media" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"deviceUid": "dev_4f8c2a1e",
"mediaId": "media_uuid",
"caption": "Check this out!"
}'Responses
{ "accepted": true }Status Codes
Success
Bad Request - invalid input
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
GET/v1/developer/status/privacy/:deviceUidReturns current status privacy rules.
0 required1 response
/v1/developer/status/privacy/:deviceUidReturns current status privacy rules.
Request Examples
curl -X GET "https://api.msgera.com/v1/developer/status/privacy/{deviceUid}" \
-H "X-API-Key: wak_your_api_key_here"Responses
{ "privacy": "contacts" }Status Codes
Success
Unauthorized - missing or invalid API key
Not Found - resource does not exist
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized - missing or invalid API key |
| 404 | Not Found - resource does not exist |
| 500 | Internal Server Error |
Spintax
Preview and generate randomized message variants.
POST/v1/developer/spintax/previewReturns a list of generated samples.
0 required1 response
/v1/developer/spintax/previewReturns a list of generated samples.
Request Body
{
"template": "{Hi|Hello|Hey} {there|friend}!",
"count": 5
}Request Examples
curl -X POST "https://api.msgera.com/v1/developer/spintax/preview" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"template": "{Hi|Hello|Hey} {there|friend}!",
"count": 5
}'Responses
{ "samples": ["Hi there!", "Hello friend!"] }Status Codes
Success
Bad Request - invalid input
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
POST/v1/developer/spintax/spinReturns one generated result from template.
0 required1 response
/v1/developer/spintax/spinReturns one generated result from template.
Request Body
{
"template": "{Hi|Hello|Hey} {there|friend}!"
}Request Examples
curl -X POST "https://api.msgera.com/v1/developer/spintax/spin" \
-H "X-API-Key: wak_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"template": "{Hi|Hello|Hey} {there|friend}!"
}'Responses
{ "result": "Hello friend!" }Status Codes
Success
Bad Request - invalid input
Unauthorized - missing or invalid API key
Internal Server Error
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 500 | Internal Server Error |
Account Safety
Protect WhatsApp devices from ban risk with per-device send budgets, burst limits, campaign pacing, and message variant rules. Limits are enforced on the API — not only in the dashboard.
Every linked device (WhatsApp account) has its own safety counters in Redis. Direct sends (POST /developer/messages/send, send-media, send-voice) and campaign sends both increment the same counters, so integrators cannot bypass daily caps by sending one-by-one instead of using campaigns.
Read budgets before you send
Call GET /v1/developer/devices/:deviceUid and inspect the safety object. When canSend is false, blockedReason explains why (daily, hourly, or per-minute limit). When canSend is true, use dailyRemaining to size your audience.
- dailyLimit / dailySent / dailyRemaining — warm-up tier by device age (e.g. 10/day for day 0–1, 25/day for days 2–7, up to 200/day for mature accounts)
- hourlyLimit — burst cap per UTC hour for display (min of config default 30 and dailyLimit); hourlyRemaining — messages left in the current UTC hour
- minuteLimit — per-minute cap for display (min of config default 5 and hourlyLimit); minuteRemaining — messages left in the current UTC minute
- variantRecipientsPerVariant — default 8 (require ceil(recipients / 8) unique TEXT variants)
- campaignDelayMinSec / campaignDelayMaxSec — randomized pause between campaign jobs (default 18–50 seconds, plus 120s every 5 messages)
All limits must pass at send time (logical AND). Example: 25 remaining today, 30/hour configured, 5/minute configured → you can send at most min(25, 25, 5) = 5 messages in the current minute, and at most 25 total before the UTC day resets (resetsAt on the safety object).
{
"dailyLimit": 25,
"dailySent": 9,
"dailyRemaining": 16,
"hourlyLimit": 25,
"hourlySent": 0,
"hourlyRemaining": 25,
"minuteLimit": 5,
"minuteSent": 0,
"minuteRemaining": 5,
"accountAgeDays": 2,
"canSend": true,
"blockedReason": null,
"resetsAt": "2026-05-23T23:59:59.999Z",
"campaignDelayMinSec": 18,
"campaignDelayMaxSec": 50,
"variantRecipientsPerVariant": 8
}When a limit is exceeded, message endpoints return HTTP 429 with error Account Send Limit. Campaign create returns HTTP 400 only for insufficient TEXT variants or disconnected accounts — not for audiences larger than dailyRemaining. Oversized audiences drip across UTC days; use estimatedCompletion on preview/create. Multiple deviceUids send in parallel (separate limits per device).
{
"statusCode": 429,
"error": "Account Send Limit",
"message": "Daily account safety limit reached (25 messages per day for accounts at this age). Try again after 2026-05-23T23:59:59.999Z.",
"accountId": "uuid",
"resetsAt": "2026-05-23T23:59:59.999Z"
}Separate from plan limits
Monthly message quotas (Starter / Growth / Pro) and account safety budgets are independent. You may hit account safety first even when your plan still has monthly headroom.
MCP ServersComing Soon
Plug Msgera into Claude, Cursor, and other MCP-aware tools so AI agents can send messages, read history, and manage contacts on your behalf.
We are publishing a Model Context Protocol (MCP) server that exposes a curated subset of this API as native MCP tools. You will install it once, point it at your API key, and any MCP-aware client will gain authenticated access.
- Send and schedule messages from inside Claude or Cursor
- Look up and update contacts, groups, and tags
- Trigger campaigns and inspect delivery status
- Subscribe to webhook streams as live MCP resources
Want early access?
Reach out from the developer dashboard and we will add you to the private beta before the public release.
SDKs & LibrariesComing Soon
Idiomatic client libraries with typed requests, retries, and pagination helpers — so you don't write the same fetch boilerplate twice.
First-party SDKs are on the roadmap for the languages our customers use most. Each SDK wraps the same endpoints documented here, plus quality-of-life helpers for auth, retries, idempotency, and webhook signature verification.
- Node.js / TypeScript — primary target, used by the dashboard itself
- Python — for data and automation workflows
- Go — for high-throughput backend services
- PHP, Java, .NET — based on demand
Until then
The Request Examples section on every endpoint generates working snippets in cURL, JavaScript, Python, and Java that you can drop straight into your code.
Common Error Responses
Errors return a stable JSON envelope. Plan enforcement uses PLAN_LIMIT_EXCEEDED and PLAN_FEATURE_UNAVAILABLE. Account safety returns HTTP 429 with error Account Send Limit when a device's daily, hourly, or per-minute budget is exhausted.
Bad Request - invalid input
Unauthorized - missing or invalid API key
Forbidden - unavailable feature, exceeded plan limit, or no access to resource. Plan errors return PLAN_FEATURE_UNAVAILABLE or PLAN_LIMIT_EXCEEDED.
Not Found - resource does not exist
Conflict - duplicate resource
Too Many Requests - account send limit (daily/hourly/minute) or user anti-spam pause. Account limit errors use error Account Send Limit and include accountId and resetsAt when applicable.
Internal Server Error
| Code | Description |
|---|---|
| 400 | Bad Request - invalid input |
| 401 | Unauthorized - missing or invalid API key |
| 403 | Forbidden - unavailable feature, exceeded plan limit, or no access to resource. Plan errors return PLAN_FEATURE_UNAVAILABLE or PLAN_LIMIT_EXCEEDED. |
| 404 | Not Found - resource does not exist |
| 409 | Conflict - duplicate resource |
| 429 | Too Many Requests - account send limit (daily/hourly/minute) or user anti-spam pause. Account limit errors use error Account Send Limit and include accountId and resetsAt when applicable. |
| 500 | Internal Server Error |
Rate Limits
Plan quotas plus per-device account safety budgets (daily warm-up, hourly/minute burst caps, campaign pacing). See Account Safety for details.
Messages per month
Starter 3,000, Growth 12,000, Pro 30,000, Business custom
WhatsApp accounts
Starter 2, Growth 3, Pro 5, Business custom
Contacts
Starter 500, Growth 2,000, Pro 5,000, Business custom
Campaigns per month
Starter 5, Growth 15, Pro 30, Business custom
AI template generations
Starter 10/month, Growth 50/month, Pro 100/month, Business custom
Account safety — daily send budget
Per device, UTC day; warm-up by device age (10 → 25 → 75 → 150 → 200 messages/day)
Account safety — hourly burst
30 messages per UTC hour per device (display capped to daily limit)
Account safety — per-minute burst
5 messages per UTC minute per device
Campaign TEXT variant ratio
At least ceil(recipients / 8) unique spintax variants (account safety)
Campaign delay between sends
18–50 seconds randomized between sends; extra 120s cool-down every 5 messages (per device queue)
Consecutive campaign failures before pause
3
Webhook delivery retries
3 attempts (exponential backoff)
Webhook delivery timeout
10 seconds/request