Msgeradocs
API Reference

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/v1

Auth Header

X-API-Key: wak_your_api_key_here

Global 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.

API docs workspace

49 endpoints across 12 feature groups

X-API-Keyhttps://api.msgera.com/v1

Overview

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.

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.

bash
curl "https://api.msgera.com/v1/developer/devices" \
  -H "X-API-Key: wak_your_api_key_here"

API Keys

Create and manage integration credentials.

3 endpoints
GET

List API Keys

/v1/api-keys

Returns all keys for your account.

0 required1 response

Request Examples

curl -X GET "https://api.msgera.com/v1/api-keys" \
  -H "X-API-Key: wak_your_api_key_here"

Responses

200Success
{
  "data": [{ "id": "uuid", "name": "My API Key", "isActive": true }],
  "total": 1
}

Status Codes

200

Success

401

Unauthorized - missing or invalid API key

500

Internal Server Error

POST

Create API Key

/v1/api-keys

Creates a new API key and returns the raw key one time.

0 required1 response

Request Fields

name

Optional

stringbody

Friendly key label (1-100 chars).

Request Body

json
{
  "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

201Created
{
  "id": "uuid",
  "name": "CI key",
  "key": "wak_abcdef1234567890...",
  "isActive": true
}

Status Codes

201

Created

400

Bad Request - invalid input

401

Unauthorized - missing or invalid API key

500

Internal Server Error

DELETE

Revoke API Key

/v1/api-keys/:id

Deletes an API key by id.

1 required1 response

Request Fields

id

Required

stringpath

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

200Success
{ "deleted": true }

Status Codes

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).

2 endpoints
GET

List Devices

/v1/developer/devices

Returns 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

Request Examples

curl -X GET "https://api.msgera.com/v1/developer/devices" \
  -H "X-API-Key: wak_your_api_key_here"

Responses

200Success
{
  "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

200

Success

401

Unauthorized - missing or invalid API key

500

Internal Server Error

GET

Get Device

/v1/developer/devices/:deviceUid

Returns one device by UID, including the same safety snapshot as the list endpoint.

1 required1 response

Request Fields

deviceUid

Required

stringpath

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

200Success
{
  "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

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).

6 endpoints
POST

Send Text Message

/v1/developer/messages/send

Sends 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

Request Fields

deviceUid

Required

stringbody

Sender device UID.

to

Required

stringbody

Recipient phone number.

text

Required

stringbody

Message text.

Request Body

json
{
  "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

200Accepted
{
  "accepted": true,
  "providerMessageId": "msg_abc123",
  "sessionId": "session_xyz",
  "messageId": "uuid"
}
429Account send limit
{
  "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

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

Send Media Message

/v1/developer/messages/send-media

Sends a media message using a media asset. Subject to the same per-device safety limits as send text.

3 required2 responses

Request Fields

deviceUid

Required

stringbody

Sender device UID.

to

Required

stringbody

Recipient phone number.

mediaId

Required

stringbody

Uploaded media id.

caption

Optional

stringbody

Optional media caption.

Request Body

json
{
  "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

200Accepted
{ "accepted": true, "messageId": "uuid" }
429Account send limit
{
  "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

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

Send Voice Message

/v1/developer/messages/send-voice

Sends an uploaded audio file as a voice message. Subject to the same per-device safety limits as send text.

3 required2 responses

Request Fields

deviceUid

Required

stringbody

Sender device UID.

to

Required

stringbody

Recipient phone number.

mediaId

Required

stringbody

Audio media id.

Request Body

json
{
  "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

200Accepted
{ "accepted": true, "messageId": "uuid" }
429Account send limit
{
  "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

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

Check WhatsApp Numbers

/v1/developer/messages/check-whatsapp

Checks 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

Request Fields

deviceUid

Required

stringbody

Sender device UID (must be a Baileys device in CONNECTED state).

numbers

Required

string[]body

1–50 phone numbers in international format (e.g. +15551234567).

Request Body

json
{
  "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

200Success
{
  "results": [
    { "phone": "+15551234567", "exists": true },
    { "phone": "+19999999999", "exists": false }
  ]
}

Status Codes

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

List Messages

/v1/developer/messages

Returns paginated messages with filters.

0 required1 response

Request Fields

deviceUid

Optional

stringquery

Filter by device UID.

to

Optional

stringquery

Filter by recipient number.

page

Optional

numberquery

Page number.

limit

Optional

numberquery

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

200Success
{ "data": [{ "id": "uuid", "status": "DELIVERED" }], "total": 100, "page": 1, "limit": 20 }

Status Codes

200

Success

401

Unauthorized - missing or invalid API key

500

Internal Server Error

GET

Get Message

/v1/developer/messages/:id

Returns detailed message payload by id.

1 required1 response

Request Fields

id

Required

stringpath

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

200Success
{ "id": "uuid", "messageType": "TEXT", "status": "DELIVERED" }

Status Codes

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.

4 endpoints
POST

Upload Media

/v1/developer/media/upload

Uploads one media file using multipart/form-data.

1 required1 response

Request Fields

file

Required

binarybody

Uploaded file binary.

kind

Optional

stringquery

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

201Created
{ "id": "uuid", "kind": "image", "mimeType": "image/jpeg" }

Status Codes

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

List Media

/v1/developer/media

Returns paginated media assets.

0 required1 response

Request Fields

page

Optional

numberquery

Page number.

limit

Optional

numberquery

Items per page.

kind

Optional

stringquery

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

200Success
{ "data": [{ "id": "uuid", "kind": "image" }], "total": 10 }

Status Codes

200

Success

401

Unauthorized - missing or invalid API key

500

Internal Server Error

GET

Get Media

/v1/developer/media/:id

Returns one media asset.

1 required1 response

Request Fields

id

Required

stringpath

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

200Success
{ "id": "uuid", "downloadUrl": "/v1/media/uuid/download" }

Status Codes

200

Success

401

Unauthorized - missing or invalid API key

404

Not Found - resource does not exist

500

Internal Server Error

DELETE

Delete Media

/v1/developer/media/:id

Deletes a media asset.

1 required1 response

Request Fields

id

Required

stringpath

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

204No Content
{}

Status Codes

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.

7 endpoints
POST

Create Campaign

/v1/developer/campaigns

Creates 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

Request Fields

deviceUid

Required

stringbody

Primary sender device UID (first parallel lane).

deviceUids

Optional

string[]body

Additional device UIDs for parallel sending. Include deviceUid; recipients are split round-robin across lanes.

name

Required

stringbody

Campaign name.

text

Required

stringbody

Message body. Use spintax {A|B|C} for account safety when sending to multiple recipients.

spintaxTemplate

Optional

stringbody

Optional separate spintax template. Variant count is validated against audience size.

contactGroupIds

Optional

string[]body

UUIDs from GET /v1/contact-groups (Bearer auth). All contacts in these groups are included.

tagIds

Optional

string[]body

UUIDs from GET /v1/contact-tags (Bearer auth). All contacts with these tags are included.

phoneNumbers

Optional

string[]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

Optional

stringbody

TEXT|MEDIA|VOICE. Variant rules apply to TEXT only.

scheduledAt

Optional

stringbody

ISO date for scheduled send.

Request Body

json
{
  "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

201Created
{
  "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
  }
}
400Account safety validation
{
  "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

201

Created

400

Bad Request - invalid input

401

Unauthorized - missing or invalid API key

409

Conflict - duplicate resource

500

Internal Server Error

GET

List Campaigns

/v1/developer/campaigns

Returns paginated campaigns.

0 required1 response

Request Fields

parentOnly

Optional

booleanquery

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

200Success
{ "data": [{ "id": "uuid", "status": "RUNNING" }], "total": 20 }

Status Codes

200

Success

401

Unauthorized - missing or invalid API key

500

Internal Server Error

GET

Get Campaign

/v1/developer/campaigns/:id

Campaign 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

Request Fields

id

Required

stringpath

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

200Success
{
  "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

200

Success

401

Unauthorized - missing or invalid API key

404

Not Found - resource does not exist

500

Internal Server Error

GET

Get Campaign Progress

/v1/developer/campaigns/:id/progress

Live counters while RUNNING. Includes estimatedCompletionAt and accountIds for multi-device campaigns.

1 required1 response

Request Fields

id

Required

stringpath

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

200Success
{
  "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

200

Success

401

Unauthorized - missing or invalid API key

404

Not Found - resource does not exist

500

Internal Server Error

GET

Get Campaign Analytics

/v1/developer/campaigns/:id/analytics

Delivery funnel (sent, delivered, read, failed, pending, rates) plus startedAt, completedAt, estimatedCompletionAt, and durationSec.

1 required1 response

Request Fields

id

Required

stringpath

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

200Success
{
  "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

200

Success

401

Unauthorized - missing or invalid API key

404

Not Found - resource does not exist

500

Internal Server Error

GET

Get Campaign Recipients

/v1/developer/campaigns/:id/recipients

Paginated 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

Request Fields

id

Required

stringpath

Campaign id.

page

Optional

numberquery

Page number (default 1).

limit

Optional

numberquery

Page size (default 20).

status

Optional

stringquery

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

200Success
{
  "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

200

Success

401

Unauthorized - missing or invalid API key

404

Not Found - resource does not exist

500

Internal Server Error

POST

Pause / Resume / Retry Failed

/v1/developer/campaigns/:id/pause|resume|retry-failed

Campaign control actions for runtime operations.

1 required1 response

Request Fields

id

Required

stringpath

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

200Success
{ "updated": true }

Status Codes

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.

3 endpoints
GET

List Contacts

/v1/developer/contacts

Returns paginated contacts and filters.

0 required1 response

Request Fields

search

Optional

stringquery

Search by name or phone.

groupId

Optional

stringquery

Filter by group.

tagId

Optional

stringquery

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

200Success
{ "data": [{ "id": "uuid", "phone": "+1234567890" }], "total": 90 }

Status Codes

200

Success

401

Unauthorized - missing or invalid API key

500

Internal Server Error

POST

Create Contact

/v1/developer/contacts

Creates a contact.

1 required1 response

Request Fields

phone

Required

stringbody

Contact phone.

name

Optional

stringbody

Contact name.

Request Body

json
{
  "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

201Created
{ "id": "uuid", "phone": "+1234567890", "name": "John Doe" }

Status Codes

201

Created

400

Bad Request - invalid input

401

Unauthorized - missing or invalid API key

409

Conflict - duplicate resource

500

Internal Server Error

PATCH

Get / Update / Delete Contact

/v1/developer/contacts/:id

Read, modify, or delete a single contact.

1 required1 response

Request Fields

id

Required

stringpath

Contact id.

Request Body

json
{
  "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

200Success
{ "id": "uuid", "phone": "+1234567890", "name": "John Doe" }

Status Codes

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

Contact Groups & Tags

Organize contacts into groups and colored tags. Authenticate with Authorization: Bearer <access_token> from the dashboard login (not X-API-Key). On create you can assign contactIds; use POST :id/contacts to add members later, or POST :id/import for CSV/XLSX (columns: name, phone). Pass group/tag UUIDs to POST /v1/developer/campaigns alongside optional phoneNumbers.

12 endpoints
GET

List Contact Groups

/v1/contact-groups

Returns all groups with contactCount per group.

0 required1 response

Request Examples

curl -X GET "https://api.msgera.com/v1/contact-groups" \
  -H "X-API-Key: wak_your_api_key_here"

Responses

200Success
{ "data": [{ "id": "uuid", "name": "VIP", "contactCount": 42 }], "total": 3 }

Status Codes

200

Success

401

Unauthorized - missing or invalid API key

500

Internal Server Error

GET

Get Contact Group

/v1/contact-groups/:id

Returns group metadata and contacts[] (id, name, phone).

1 required1 response

Request Fields

id

Required

stringpath

Group UUID.

Request Examples

curl -X GET "https://api.msgera.com/v1/contact-groups/{id}" \
  -H "X-API-Key: wak_your_api_key_here"

Responses

200Success
{ "id": "uuid", "name": "VIP", "contacts": [{ "id": "uuid", "phone": "+1234567890" }] }

Status Codes

200

Success

401

Unauthorized - missing or invalid API key

404

Not Found - resource does not exist

500

Internal Server Error

POST

Create Contact Group

/v1/contact-groups

Creates a group. Optionally add members immediately via POST :id/contacts after creation.

1 required1 response

Request Fields

name

Required

stringbody

Group name.

description

Optional

stringbody

Optional description.

Request Body

json
{ "name": "VIP Clients", "description": "High-value customers" }

Request Examples

curl -X POST "https://api.msgera.com/v1/contact-groups" \
  -H "X-API-Key: wak_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "name": "VIP Clients", "description": "High-value customers" }'

Responses

201Created
{ "id": "uuid", "name": "VIP Clients", "contactCount": 0 }

Status Codes

201

Created

400

Bad Request - invalid input

401

Unauthorized - missing or invalid API key

409

Conflict - duplicate resource

500

Internal Server Error

POST

Add Contacts to Group

/v1/contact-groups/:id/contacts

Links existing contacts to the group by contact UUID.

2 required1 response

Request Fields

id

Required

stringpath

Group UUID.

contactIds

Required

string[]body

Contact UUIDs to add (min 1).

Request Body

json
{ "contactIds": ["contact-uuid-1", "contact-uuid-2"] }

Request Examples

curl -X POST "https://api.msgera.com/v1/contact-groups/{id}/contacts" \
  -H "X-API-Key: wak_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "contactIds": ["contact-uuid-1", "contact-uuid-2"] }'

Responses

200Success
{ "added": 2 }

Status Codes

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

DELETE

Remove Contacts from Group

/v1/contact-groups/:id/contacts

Removes contacts from the group (does not delete contacts).

2 required1 response

Request Fields

id

Required

stringpath

Group UUID.

contactIds

Required

string[]body

Contact UUIDs to remove.

Request Body

json
{ "contactIds": ["contact-uuid-1"] }

Request Examples

curl -X DELETE "https://api.msgera.com/v1/contact-groups/{id}/contacts" \
  -H "X-API-Key: wak_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "contactIds": ["contact-uuid-1"] }'

Responses

200Success
{ "removed": 1 }

Status Codes

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

POST

Import Contacts to Group

/v1/contact-groups/:id/import

Multipart file upload (CSV, XLSX, XLS). Creates new contacts or links existing ones by phone. Requires contactImport plan feature.

2 required1 response

Request Fields

id

Required

stringpath

Group UUID.

file

Required

filebody

Multipart field name: file.

Request Examples

curl -X POST "https://api.msgera.com/v1/contact-groups/{id}/import" \
  -H "X-API-Key: wak_your_api_key_here"

Responses

200Success
{ "linked": 5, "created": 12, "errors": [{ "row": 4, "message": "Invalid phone number" }] }

Status Codes

200

Success

400

Bad Request - invalid input

401

Unauthorized - missing or invalid API key

404

Not Found - resource does not exist

403

Forbidden - unavailable feature, exceeded plan limit, or no access to resource. Plan errors return PLAN_FEATURE_UNAVAILABLE or PLAN_LIMIT_EXCEEDED.

500

Internal Server Error

GET

List Contact Tags

/v1/contact-tags

Returns all tags with name, color, and contactCount.

0 required1 response

Request Examples

curl -X GET "https://api.msgera.com/v1/contact-tags" \
  -H "X-API-Key: wak_your_api_key_here"

Responses

200Success
{ "data": [{ "id": "uuid", "name": "Leads", "color": "#6366f1", "contactCount": 18 }], "total": 5 }

Status Codes

200

Success

401

Unauthorized - missing or invalid API key

500

Internal Server Error

POST

Create Contact Tag

/v1/contact-tags

Creates a tag. Assign members via POST :id/contacts or import.

1 required1 response

Request Fields

name

Required

stringbody

Tag name (unique per account).

color

Optional

stringbody

Hex color (default #6366f1).

Request Body

json
{ "name": "Leads", "color": "#22c55e" }

Request Examples

curl -X POST "https://api.msgera.com/v1/contact-tags" \
  -H "X-API-Key: wak_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Leads", "color": "#22c55e" }'

Responses

201Created
{ "id": "uuid", "name": "Leads", "color": "#22c55e", "contactCount": 0 }

Status Codes

201

Created

400

Bad Request - invalid input

401

Unauthorized - missing or invalid API key

409

Conflict - duplicate resource

500

Internal Server Error

PATCH

Update Contact Tag

/v1/contact-tags/:id

Updates tag name and/or color.

1 required1 response

Request Fields

id

Required

stringpath

Tag UUID.

name

Optional

stringbody

New tag name.

color

Optional

stringbody

New hex color.

Request Body

json
{ "name": "Hot Leads", "color": "#ef4444" }

Request Examples

curl -X PATCH "https://api.msgera.com/v1/contact-tags/{id}" \
  -H "X-API-Key: wak_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Hot Leads", "color": "#ef4444" }'

Responses

200Success
{ "id": "uuid", "name": "Hot Leads", "color": "#ef4444", "contactCount": 18 }

Status Codes

200

Success

400

Bad Request - invalid input

401

Unauthorized - missing or invalid API key

404

Not Found - resource does not exist

409

Conflict - duplicate resource

500

Internal Server Error

POST

Add Contacts to Tag

/v1/contact-tags/:id/contacts

Tags existing contacts by contact UUID.

2 required1 response

Request Fields

id

Required

stringpath

Tag UUID.

contactIds

Required

string[]body

Contact UUIDs (min 1).

Request Body

json
{ "contactIds": ["contact-uuid-1"] }

Request Examples

curl -X POST "https://api.msgera.com/v1/contact-tags/{id}/contacts" \
  -H "X-API-Key: wak_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "contactIds": ["contact-uuid-1"] }'

Responses

200Success
{ "added": 1 }

Status Codes

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

DELETE

Remove Contacts from Tag

/v1/contact-tags/:id/contacts

Removes the tag from contacts (does not delete contacts).

2 required1 response

Request Fields

id

Required

stringpath

Tag UUID.

contactIds

Required

string[]body

Contact UUIDs.

Request Body

json
{ "contactIds": ["contact-uuid-1"] }

Request Examples

curl -X DELETE "https://api.msgera.com/v1/contact-tags/{id}/contacts" \
  -H "X-API-Key: wak_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "contactIds": ["contact-uuid-1"] }'

Responses

200Success
{ "removed": 1 }

Status Codes

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

POST

Import Contacts to Tag

/v1/contact-tags/:id/import

Multipart CSV/XLSX/XLS import into a tag — same behavior as group import (linked, created, errors). Requires contactImport plan feature.

2 required1 response

Request Fields

id

Required

stringpath

Tag UUID.

file

Required

filebody

Multipart field name: file.

Request Examples

curl -X POST "https://api.msgera.com/v1/contact-tags/{id}/import" \
  -H "X-API-Key: wak_your_api_key_here"

Responses

200Success
{ "linked": 3, "created": 8, "errors": [] }

Status Codes

200

Success

400

Bad Request - invalid input

401

Unauthorized - missing or invalid API key

404

Not Found - resource does not exist

403

Forbidden - unavailable feature, exceeded plan limit, or no access to resource. Plan errors return PLAN_FEATURE_UNAVAILABLE or PLAN_LIMIT_EXCEEDED.

500

Internal Server Error

Scheduled Messages

Schedule, update, and cancel future sends.

2 endpoints
POST

Create Scheduled Message

/v1/developer/scheduled-messages

Creates a scheduled message job.

4 required1 response

Request Fields

deviceUid

Required

stringbody

device UID.

to

Required

stringbody

Recipient phone.

text

Required

stringbody

Message text.

scheduledAt

Required

stringbody

Future ISO date.

Request Body

json
{
  "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

201Created
{ "id": "uuid", "status": "PENDING" }

Status Codes

201

Created

400

Bad Request - invalid input

401

Unauthorized - missing or invalid API key

500

Internal Server Error

GET

List / Get / Update / Cancel Scheduled Message

/v1/developer/scheduled-messages

Full lifecycle operations for scheduled records.

0 required1 response

Request Examples

curl -X GET "https://api.msgera.com/v1/developer/scheduled-messages" \
  -H "X-API-Key: wak_your_api_key_here"

Responses

200Success
{ "data": [{ "id": "uuid", "status": "PENDING" }], "total": 10 }

Status Codes

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.

2 endpoints
GET

List Auto-Reply Rules

/v1/developer/auto-reply

Returns rules for a given device.

1 required1 response

Request Fields

deviceUid

Required

stringquery

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

200Success
{ "data": [{ "id": "uuid", "triggerType": "CONTAINS" }], "total": 12 }

Status Codes

200

Success

400

Bad Request - invalid input

401

Unauthorized - missing or invalid API key

500

Internal Server Error

POST

Create / Update / Delete Rule

/v1/developer/auto-reply|:id

Manage one rule with trigger and reply text.

4 required1 response

Request Fields

deviceUid

Required

stringbody

Sender device UID for create requests.

triggerType

Required

stringbody

CONTAINS|EXACT|STARTS_WITH|ENDS_WITH.

triggerValue

Required

stringbody

Matching phrase.

replyText

Required

stringbody

Auto-reply content.

Request Body

json
{
  "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

200Success
{ "id": "uuid", "enabled": true, "order": 0 }

Status Codes

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.

3 endpoints
GET

List Webhooks

/v1/developer/webhooks

List webhook configurations.

0 required1 response

Request Fields

deviceUid

Optional

stringquery

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

200Success
{ "data": [{ "id": "uuid", "isActive": true }] }

Status Codes

200

Success

401

Unauthorized - missing or invalid API key

500

Internal Server Error

PUT

Create or Update Webhook

/v1/developer/webhooks

Upserts webhook config for a specific device.

1 required1 response

Request Fields

deviceUid

Required

stringbody

device UID.

personalWebhookUrl

Optional

stringbody

Personal chat event URL.

groupWebhookUrl

Optional

stringbody

Group chat event URL.

Request Body

json
{
  "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

200Success
{ "id": "uuid", "isActive": true }

Status Codes

200

Success

400

Bad Request - invalid input

401

Unauthorized - missing or invalid API key

500

Internal Server Error

GET

Webhook Delivery History

/v1/developer/webhooks/history

Returns delivery attempts with status and response code.

0 required1 response

Request Examples

curl -X GET "https://api.msgera.com/v1/developer/webhooks/history" \
  -H "X-API-Key: wak_your_api_key_here"

Responses

200Success
{ "data": [{ "deliveryStatus": "SUCCESS", "responseStatusCode": 200 }], "total": 50 }

Status Codes

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.

3 endpoints
POST

Post Text Status

/v1/developer/status/text

Publishes text status to stories.

1 required1 response

Request Fields

deviceUid

Required

stringbody

Sender device UID.

Request Body

json
{
  "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

200Success
{ "accepted": true }

Status Codes

200

Success

400

Bad Request - invalid input

401

Unauthorized - missing or invalid API key

500

Internal Server Error

POST

Post Media Status

/v1/developer/status/media

Publishes media status using uploaded media.

1 required1 response

Request Fields

deviceUid

Required

stringbody

Sender device UID.

Request Body

json
{
  "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

200Success
{ "accepted": true }

Status Codes

200

Success

400

Bad Request - invalid input

401

Unauthorized - missing or invalid API key

500

Internal Server Error

GET

Get Status Privacy

/v1/developer/status/privacy/:deviceUid

Returns current status privacy rules.

0 required1 response

Request Examples

curl -X GET "https://api.msgera.com/v1/developer/status/privacy/{deviceUid}" \
  -H "X-API-Key: wak_your_api_key_here"

Responses

200Success
{ "privacy": "contacts" }

Status Codes

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.

2 endpoints
POST

Preview Spintax Variations

/v1/developer/spintax/preview

Returns a list of generated samples.

0 required1 response

Request Body

json
{
  "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

200Success
{ "samples": ["Hi there!", "Hello friend!"] }

Status Codes

200

Success

400

Bad Request - invalid input

401

Unauthorized - missing or invalid API key

500

Internal Server Error

POST

Spin Single Variation

/v1/developer/spintax/spin

Returns one generated result from template.

0 required1 response

Request Body

json
{
  "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

200Success
{ "result": "Hello friend!" }

Status Codes

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).

json
{
  "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).

json
{
  "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.

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