API REFERENCE
AUTHENTICATION
All requests require your API key as a Bearer token. Store it as an environment variable. Never hardcode it in scripts.
export WA_API_KEY="sk_..."
Authorization: Bearer $WA_API_KEY
Sign in to get your API key.
RATE LIMITS
All limits are per API key. Exceeded requests return 429 Too Many Requests with a Retry-After header indicating seconds until the window resets.
| Endpoint | Limit | Window |
|---|---|---|
POST /api/instances (provision) | 10 req | per minute |
/api/instances/:id/proxy/* | 120 req | per minute |
/api/* (all other endpoints) | 120 req | per minute |
| All endpoints (per IP, global floor) | 300 req | per minute |
HTTP/1.1 429 Too Many Requests
Retry-After: 42
Content-Type: application/json
{"error":"rate limit exceeded"}
Implement exponential backoff. Check Retry-After before retrying.
QUICK START
1. Provision a bridge
curl -X POST https://wabridges.com/api/instances \
-H "Authorization: Bearer $WA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"customer_ref":"user-123","webhook_url":"https://yourbackend.com/hook"}'
{"id":42,"customer_ref":"user-123","state":"running"}
2. Pair the phone
curl -X POST https://wabridges.com/api/instances/{customer_ref}/proxy/pair \
-H "Authorization: Bearer $WA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phone":"15550001234"}'
# → {"code":"ABCD-EFGH"} Enter this on the phone in WhatsApp → Linked Devices
3. Check status
curl https://wabridges.com/api/instances/{customer_ref}/proxy/status \
-H "Authorization: Bearer $WA_API_KEY"
# → {"status":"connected","phone":"15550001234","jid":"15550001234@s.whatsapp.net","name":"Alice"}
4. Send a message
curl -X POST https://wabridges.com/api/instances/{customer_ref}/proxy/send/text \
-H "Authorization: Bearer $WA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"chat":"15559876543","body":"Hello from the API"}'
# → {"message_id":"ACE41E...","timestamp":1777180605}
BRIDGES
Manage bridge instances. All routes require Authorization: Bearer $WA_API_KEY.
https://wabridges.com/api/instances
Provision a new bridge. If customer_ref already exists, returns the existing record.
curl -X POST https://wabridges.com/api/instances \
-H "Authorization: Bearer $WA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_ref": "user-123",
"webhook_url": "https://yourbackend.com/hook"
}'
{
"id": 42,
"customer_ref": "user-123",
"state": "running"
}
https://wabridges.com/api/instances
List all bridges for this account.
curl https://wabridges.com/api/instances \ -H "Authorization: Bearer $WA_API_KEY"
[
{
"id": 42,
"customer_ref": "user-123",
"state": "running",
"created_at": 1777180605
}
]
https://wabridges.com/api/instances/:id
Get a single bridge including live container state from the manager.
curl https://wabridges.com/api/instances/{customer_ref} \
-H "Authorization: Bearer $WA_API_KEY"
{
"id": 42,
"customer_ref": "user-123",
"state": "running",
"created_at": 1777180605,
"manager": {
"health": "healthy",
"started_at": "2025-06-17T10:00:00Z",
"fail_count": 0
}
}
https://wabridges.com/api/instances/:id
Permanently delete a bridge. Stops the container and removes all data. Cannot be undone.
curl -X DELETE https://wabridges.com/api/instances/{customer_ref} \
-H "Authorization: Bearer $WA_API_KEY"
204 No Content
SESSION
https://wabridges.com/api/instances/{customer_ref}/proxy/status
Connection state. When connected, includes phone, jid, and name.
{"status":"connected","phone":"15550001234","jid":"15550001234@s.whatsapp.net","name":"Alice"}
https://wabridges.com/api/instances/{customer_ref}/proxy/qr
QR code PNG, open in browser (unpaired state only)
(image/png)
https://wabridges.com/api/instances/{customer_ref}/proxy/pair
Link-code pairing. WhatsApp shows 8-digit code on phone
{"phone":"15550001234"}
{"code":"ABCD-EFGH"}
https://wabridges.com/api/instances/{customer_ref}/proxy/logout
Unpair and destroy session. Requires re-pair after.
{"ok":true}
MESSAGING
https://wabridges.com/api/instances/{customer_ref}/proxy/send/text
Send a text message. chat = phone number or full JID
{"chat":"15550001234","body":"Hello!"}
{"message_id":"ACE41E...","timestamp":1777180605}
https://wabridges.com/api/instances/{customer_ref}/proxy/send/media
Send image, video, audio, or document. Media type inferred from Content-Type of URL response
{"chat":"15550001234","url":"https://example.com/photo.jpg","caption":"check this out"}
{"message_id":"ACE41E...","timestamp":1777180605}
https://wabridges.com/api/instances/{customer_ref}/proxy/send/reaction
React to a message with an emoji. Empty string removes the reaction
{"chat":"15550001234","message_id":"ACE41E...","emoji":"👍"}
{"message_id":"ACE41E...","timestamp":1777180605}
https://wabridges.com/api/instances/{customer_ref}/proxy/send/poll
Send a poll. max_answers=1 is single choice, higher = multiple choice
{"chat":"15550001234","question":"Favorite color?","options":["Red","Green","Blue"],"max_answers":1}
{"message_id":"ACE41E...","timestamp":1777180605}
https://wabridges.com/api/instances/{customer_ref}/proxy/send/location
Send a location pin with optional name and address
{"chat":"15550001234","lat":19.432608,"lng":-99.133209,"name":"Zócalo","address":"Plaza de la Constitución"}
{"message_id":"ACE41E...","timestamp":1777180605}
https://wabridges.com/api/instances/{customer_ref}/proxy/send/event
Send a calendar event (WhatsApp EventMessage). Contacts can RSVP and trigger event_response webhooks.
{"chat":"15550001234","name":"Team sync","start_time":1777334400,"end_time":1777338000}
{"message_id":"ACE41E...","timestamp":1777180605}
https://wabridges.com/api/instances/{customer_ref}/proxy/send/typing
Send typing indicator. state=composing|paused, mode=text|voice
{"chat":"15550001234","state":"composing","mode":"text"}
{"ok":true}
https://wabridges.com/api/instances/{customer_ref}/proxy/messages/:id?chat=15550001234
Revoke a sent message for everyone
{"message_id":"ACE41E...","timestamp":1777180605}
https://wabridges.com/api/instances/{customer_ref}/proxy/messages/:id/edit
Edit a sent text message
{"chat":"15550001234@s.whatsapp.net","body":"corrected text"}
{"message_id":"ACE41E...","timestamp":1777180605}
https://wabridges.com/api/instances/{customer_ref}/proxy/messages/:id/read
Send a read receipt. Include sender for group messages
{"chat":"15550001234@s.whatsapp.net"}
{"ok":true}
https://wabridges.com/api/instances/{customer_ref}/proxy/messages/:id/media
Download inbound media by message_id. Cached 3 hours from receipt
(raw bytes: image/jpeg, video/mp4, audio/ogg, etc.)
CONTACTS
https://wabridges.com/api/instances/{customer_ref}/proxy/contacts
List all contacts the bridge knows about
[{"jid":"15550001234@s.whatsapp.net","phone":"15550001234","name":"Alice","is_business":false}]
https://wabridges.com/api/instances/{customer_ref}/proxy/contacts/:jid
Get info for a single contact. Pass phone number or full JID
{"jid":"...","phone":"15550001234","name":"Alice","about":"Hey!","is_business":false}
https://wabridges.com/api/instances/{customer_ref}/proxy/contacts/:jid/avatar
Download contact avatar as JPEG
(image/jpeg)
https://wabridges.com/api/instances/{customer_ref}/proxy/contacts/check
Check which phone numbers are registered on WhatsApp
{"phones":["15550001234","00000000000"]}
[{"phone":"15550001234","registered":true,"is_business":false},{"phone":"00000000000","registered":false}]
PROFILE
https://wabridges.com/api/instances/{customer_ref}/proxy/profile
Your own profile
{"jid":"15550001234@s.whatsapp.net","phone":"15550001234","name":"My Name","about":"Hey there!"}
https://wabridges.com/api/instances/{customer_ref}/proxy/profile/status
Set your About status text
{"status":"Hey there! I am using WA Bridges."}
{"ok":true}
https://wabridges.com/api/instances/{customer_ref}/proxy/profile/avatar
Download your own avatar as JPEG
(image/jpeg)
https://wabridges.com/api/instances/{customer_ref}/proxy/profile/avatar
Set your profile picture from a URL (must return JPEG)
{"url":"https://example.com/me.jpg"}
{"picture_id":"12345678901"}
https://wabridges.com/api/instances/{customer_ref}/proxy/profile/avatar
Remove your profile picture
{"ok":true}
https://wabridges.com/api/instances/{customer_ref}/proxy/profile/qr
Get your shareable wa.me/qr link
{"link":"https://wa.me/qr/ABCDEFGHIJKL"}
PRESENCE
https://wabridges.com/api/instances/{customer_ref}/proxy/presence
Set your online/offline presence
{"state":"available"}
{"ok":true}
https://wabridges.com/api/instances/{customer_ref}/proxy/presence/subscribe
Subscribe to a contact's typing/online state. Requires global presence to be available. Refresh every few minutes.
{"chat":"15550001234"}
{"ok":true}
PRIVACY
https://wabridges.com/api/instances/{customer_ref}/proxy/status/privacy
Get who can see your status updates
[{"type":"contacts","list":[],"is_default":true}]
DEBUG
https://wabridges.com/api/instances/{customer_ref}/proxy/healthz
Process liveness probe (unauthenticated). Returns 200 while the process is up. Does not check WA connection; use /status for that.
{"ok":true}
https://wabridges.com/api/instances/{customer_ref}/proxy/debug/stats
Runtime stats: goroutines, heap usage, GC cycles, media cache size
{"goroutines":12,"heap_alloc_mb":14,"heap_sys_mb":32,"heap_objects":84201,"total_alloc_mb":50,"gc_cycles":3,"next_gc_mb":28,"media_cache_size":4}
WEBHOOKS
Every inbound event fires a POST to your webhook_url.
Respond 200 quickly. Delivery is async, single-attempt. Process asynchronously.
message
Fields: event, message_id, contact_id, phone, chat_id, name, body, type, media_type, is_group, from_me, timestamp
{"event":"message","message_id":"ACE41E...","contact_id":"15550001234@s.whatsapp.net","phone":"15550001234","chat_id":"15550001234@s.whatsapp.net","name":"Alice","body":"Hello!","type":"text","media_type":"","is_group":false,"from_me":false,"timestamp":1777180605}
connected
Fields: event, phone
{"event":"connected","phone":"15550001234"}
disconnected
Fields: event
{"event":"disconnected"}
typing
Fields: event, contact_id, chat_id, state (composing|paused), mode (text|voice)
{"event":"typing","contact_id":"15550001234@s.whatsapp.net","chat_id":"15550001234@s.whatsapp.net","state":"composing","mode":"text"}
poll_vote
Fields: event, contact_id, phone, chat_id, poll_id, message_id, name, from_me, timestamp, selected_options
{"event":"poll_vote","contact_id":"15550001234@s.whatsapp.net","phone":"15550001234","chat_id":"15550001234@s.whatsapp.net","poll_id":"ACPOLL0001","message_id":"ACVOTE0001","name":"Alice","from_me":false,"timestamp":1777330500,"selected_options":["Red"]}
event_response
Fields: event, contact_id, phone, chat_id, event_id, message_id, name, from_me, timestamp, response (going|not_going|maybe), extra_guest_count
{"event":"event_response","contact_id":"15550001234@s.whatsapp.net","phone":"15550001234","chat_id":"15550009999@g.us","event_id":"ACEVENT0001","message_id":"ACEVRESP0001","name":"Alice","from_me":false,"timestamp":1777330700,"response":"going","extra_guest_count":0}
call_incoming
Fields: event, call_id, contact_id, platform, timestamp
{"event":"call_incoming","call_id":"ABCDEF123456","contact_id":"15550001234@s.whatsapp.net","platform":"android","timestamp":1777180605}
call_terminated
Fields: event, call_id, contact_id, reason (timeout|hangup|decline|busy), timestamp
{"event":"call_terminated","call_id":"ABCDEF123456","contact_id":"15550001234@s.whatsapp.net","reason":"hangup","timestamp":1777180720}
offline_sync_preview
Fields: event, total, messages, notifications, receipts, app_data_changes
{"event":"offline_sync_preview","total":142,"messages":120,"notifications":8,"receipts":14,"app_data_changes":0}
offline_sync_completed
Fields: event, count
{"event":"offline_sync_completed","count":142}
profile_picture_updated
Fields: event, remove (bool), picture_id?, timestamp
{"event":"profile_picture_updated","remove":false,"picture_id":"12345678901","timestamp":1777180605}
GUIDES
Step-by-step guides for common integration patterns.