API Documentation
Authentication
Every API request must include your API key in the x-api-key header. Get your key after creating an account — it appears in Settings → API Key.
Base URL
All endpoints below are relative to:
Replace with the host where the gateway is deployed. After logging in, your exact base URL is shown on the dashboard.
Picking a phone (slots)
One API key authenticates your account. You can connect up to two WhatsApp numbers ("slots"). To choose which one sends, add a slot field to the request body:
- Omit it → Phone 1 (default)
"slot": "a"→ Phone 1"slot": "b"→ Phone 2 (Pro plan only)
Quick start
Hello world in three popular languages. Replace YOUR_API_KEY and the destination phone number.
All endpoints
POST /send-message
The single unified endpoint for sending anything — text, images, documents, videos — to any combination of contacts and groups.
| Field | Type | Required | Description |
|---|---|---|---|
| phone | string | string[] | Required | Phone number (919876543210), group ID (120363xxx@g.us), or an array of both |
| message | string | For text | Text body. Max 4096 chars. Supports emoji, line breaks (\n), WhatsApp markdown. |
| type | string | For media | image, document, pdf, or video |
| media_url | string | For media | Public URL of the file (must be reachable from the server) |
| media_base64 | string | For media | Base64-encoded file (alternative to media_url). Max ~15MB. |
| filename | string | Optional | Display filename (recommended for documents/PDFs) |
| caption | string | Optional | Caption shown under the media |
| slot | string | Optional | "a" (default), "b", "c", "d", "e" — based on your plan |
POST /send-bulk
Send to up to 500 contacts in one call. Use {{name}} and {{phone}} as merge variables. The server enforces a 75-120s delay between messages plus a 3-minute rest every 10 sends to avoid bans. Trial plan blocked.
| Field | Type | Required | Description |
|---|---|---|---|
| contacts | array | Required | Up to 500 objects, each with phone and optional name |
| message | string | For text | Template. Use {{name}} and {{phone}} for substitution. |
| type | string | For media | image, document, pdf, or video — attach a file to every contact in this batch instead of plain text |
| media_url | string | For media | Public URL of the file |
| media_base64 | string | For media | Base64-encoded file (alternative to media_url). Max ~15MB. |
| filename | string | Optional | Display filename (recommended for documents/PDFs) |
| caption | string | For media | Text sent together with the file as ONE message. Also supports {{name}}/{{phone}}. Used instead of message when type is set. |
| slot | string | Optional | "a" or "b" |
POST /broadcast Pro
Send the same message to a mix of groups and individual contacts, up to 100 recipients per request. Recipients can come from three sources, used together or separately. Duplicates across sources are removed automatically. Trial plan blocked.
| Field | Type | Required | Description |
|---|---|---|---|
| message | string | For text | Text to broadcast. Max 4096 chars. |
| type | string | For media | image, document, pdf, or video — attach a file to every recipient instead of plain text |
| media_url | string | For media | Public URL of the file |
| media_base64 | string | For media | Base64-encoded file (alternative to media_url). Max ~15MB. |
| filename | string | Optional | Display filename (recommended for documents/PDFs) |
| caption | string | For media | Text sent together with the file as ONE message. Used instead of message when type is set. |
| groups | array | One of | List of { id, name? } — group JIDs (with or without @g.us) |
| contacts | array | One of | List of { phone, name? } — raw numbers, 10–15 digits, no + |
| contact_ids | array | One of | List of saved-contact ids from /contacts (e.g. "ct_a1b2c3") |
| slot | string | Optional | "a" or "b" |
contact_ids — no need to re-send phone numbers each time.
POST /check-whatsapp
Check whether one or more numbers are registered on WhatsApp before sending.
POST /schedule-message
Queue a message to send at a specific future time. Returns a scheduled job ID.
| Field | Type | Required | Description |
|---|---|---|---|
| phone | string | Required | Recipient phone (or use group_id) |
| message | string | Required | Text to send |
| sendAt | string | Required | ISO 8601 timestamp, e.g. "2026-06-15T14:30:00Z" |
| slot | string | Optional | "a" or "b" |
GET /status
Returns connection state for both phone slots plus daily/total send counts.
GET /groups
List WhatsApp groups your account belongs to. Use ?slot=a|b to choose which phone.
GET /messages
Recent send history. Query parameters: type (single, group, broadcast), status (sent, failed, queued), limit (default 50, max 500). Each row includes slot and slotPhone.
GET /queue
Returns the current bulk send queue — items pending, in progress, and processing rate. Useful for status bars.
GET /scheduled
Returns all your pending scheduled messages. Delete with DELETE /scheduled/:id.
GET /subscription
Returns your active plan, expiry date, daily message limit, and whether bulk/Pro features are unlocked.
Message Templates
Save reusable message snippets with {{variable}} placeholders, and fill them in at send time. Useful for order confirmations, OTP messages, reminders, and any text you reuse with small per-recipient changes.
/use counter work on all plans.
Max 50 templates per account, 60 chars per name, 4096 chars per body.
Template variables follow the pattern {{variable_name}} — alphanumeric and underscores only. The API automatically extracts variable names from your content into a variables array. You then substitute them client-side before calling /send-message:
GET /templates
List all your saved templates, newest first. Available on every plan.
POST /templates Pro
Create a new template. Variables are auto-extracted from content.
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Required | Human-readable name (max 60 chars) |
| content | string | Required | Body with optional {{variable}} placeholders (max 4096 chars) |
| category | string | Optional | Tag for grouping in the dashboard (max 30 chars) |
PUT /templates/:id Pro
Update an existing template. Pass any subset of name, content, category. Variables re-extract on every content change.
DELETE /templates/:id
Delete a template permanently. Returns 404 if the template ID does not exist.
POST /templates/:id/use
Increment the usageCount for a template — optional telemetry call that lets you sort/rank templates by popularity in your own UI. Returns the updated template.
Contact book
A per-account address book of WhatsApp recipients so you don't re-type numbers each time. Saved contacts can be referenced by id in the /broadcast endpoint via contact_ids.
+, 10–15 digits). Duplicates are rejected.
GET /contacts
List your saved contacts, newest first. Optional ?search= matches name, phone, or any tag (case-insensitive). Optional ?limit= caps the response.
POST /contacts
Save a single contact. Returns 403 CONTACTS_CAP_REACHED when your plan's contact cap is full. Returns 409 DUPLICATE_PHONE if another contact already uses the number.
| Field | Type | Required | Description |
|---|---|---|---|
| phone | string | Required | Country code + number (10–15 digits). Non-digits are stripped — "+91 98765 43210" works. |
| name | string | Optional | Display name (max 80 chars) |
| notes | string | Optional | Free-form note (max 200 chars) |
| tags | array | Optional | Up to 8 string tags, max 30 chars each |
POST /contacts/bulk
Import many contacts in one request — perfect for migrating from a CSV or spreadsheet. Up to 1000 rows per call. The endpoint inserts what it can, then returns a per-row outcome explaining why anything got skipped.
Skip reasons:
invalid_phone— number is missing or not 10–15 digitsduplicate_existing— that phone is already savedduplicate_in_batch— appears twice in your requestcap_reached— your plan's contact cap is full
PUT /contacts/:id
Edit a contact. Pass any subset of name, phone, notes, tags. Changing phone to one another contact already has returns 409 DUPLICATE_PHONE.
DELETE /contacts/:id
Remove a single contact. To remove many at once, POST a list of ids to /contacts/delete-many:
Outgoing webhooks
Configure a URL to receive delivery events (sent / failed) for every message your account sends.
Trigger token (no-auth URL)
Each account has a secret trigger token that creates a public URL services like Google Forms, Zapier, Make, or Apps Script can POST to without sending an API key. Useful when the calling service can't add custom headers.
Error responses
All errors return a JSON body with an error string and (when useful) a machine-readable code.
| Status | code | Meaning |
|---|---|---|
| 400 | — | Bad request body — see error for details |
| 401 | — | Missing or invalid x-api-key |
| 402 | NO_SUBSCRIPTION | No active subscription — start a trial or pay |
| 403 | PRO_REQUIRED | Used slot: "b" without Pro plan |
| 403 | TRIAL_BULK_BLOCKED | Bulk/broadcast not available on trial plan |
| 403 | SEND_WINDOW_CLOSED | Outside your configured send window — response includes nextOpenAt |
| 400 | BROADCAST_CAP_EXCEEDED | Sent more than 100 recipients in one broadcast — split into multiple calls |
| 400 | NO_RECIPIENTS | Broadcast call with no groups, contacts, or contact_ids |
| 403 | CONTACTS_CAP_REACHED | Your contact book is full for your plan (Trial 20 / Basic 100 / Pro 300) |
| 409 | DUPLICATE_PHONE | Tried to save a contact whose phone already exists |
| 429 | DAILY_LIMIT_REACHED | Hit trial-plan daily limit. Response includes limit and used. |
| 429 | — | Per-IP rate limit (60 requests/min on /api/*) |
| 500 | — | Server error — retry, then contact support if it persists |
Rate limits & throttling
- API throttle: 60 requests per minute per IP on
/api/*endpoints. - Bulk & broadcast cadence: 40-55 second randomized gap between messages (anti-ban v2), plus a 3-minute rest after every 10 sends, plus random 2-5 min "human breaks" every 7-12 messages. Enforced server-side.
- Hourly cap: 30 messages per slot per hour. After hitting the cap, a 30-minute forced cooldown kicks in.
- Daily cap: 200 messages per slot per day. New contact limit: 50/day (contacts who haven't messaged you first).
- Warm-up: After a fresh connect, sending is throttled — max 5 messages in first 30 min, 15 in first 2 hours.
- Daily limit: Trial accounts have a configurable daily ceiling (see
GET /subscription). Paid plans follow anti-ban caps above. - Send window: Optional per-user "only send during these hours" rule. If outside the window, you get
SEND_WINDOW_CLOSEDwithnextOpenAt.
Need help?
Found an issue or have a question? Email info@aumpfy.com or open the dashboard chat after signing in.