POSThttps://voice-api.edesy.in/v1/whatsapp/messages sends a WhatsApp message from a connected Edesy number. Set type to text, template, image, audio, video or document, give the recipient in E.164 format, and authenticate with your API key. The response returns the stored message with its WhatsApp message ID and status.
Facts#
| Item | Detail |
|---|---|
| Base URL | https://voice-api.edesy.in/v1/whatsapp |
| Auth | Authorization: Bearer sk_... (create keys on the API Keys page) |
| Send | POST/messages |
| Message types | text, template, image, audio, video, document |
| Recipient | to in E.164, e.g. +919876543210 |
| Free-form messages | Only within 24 hours of the customer's last message; otherwise use template |
| Status values | queued, sent, delivered, read, failed |
| Response | 201 with data and meta (request_id, timestamp) |
Authentication#
Create an API key on the API Keys page in wa-connect.edesy.in and send it on every request:
Authorization: Bearer sk_your_api_key_here
How it works#
- Find your number's ID. GET
/v1/whatsapp/configlists your connected numbers. Use thephone_number_idvalue (Edesy's UUID for the number). - Send with POST
/v1/whatsapp/messages. - Store the returned
idandwamid. - Receive status updates on your webhook as the message is sent, delivered and read.
Request body#
| Field | Type | Required | Description |
|---|---|---|---|
phone_number_id |
string (UUID) | Required | The Edesy number to send from. channel_id is accepted as an alias |
to |
string | Required | Recipient in E.164 |
type |
string | Required | text, template, image, audio, video or document |
text.body |
string | for text |
Message text |
template.name |
string | for template |
Approved template name |
template.language.code |
string | for template |
e.g. en_US, hi |
template.components |
array | Optional | Values for template variables (header, body, button) |
media.link |
string | for media, or media.id |
Public URL of the file |
media.id |
string | for media, or media.link |
Meta media ID |
media.caption |
string | Optional | Caption |
media.filename |
string | Optional | File name for documents |
reply_to |
string | Optional | Message ID to reply to |
Examples#
Text#
curl -X POST https://voice-api.edesy.in/v1/whatsapp/messages \
-H "Authorization: Bearer sk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phone_number_id": "your-edesy-phone-number-uuid",
"to": "+919876543210",
"type": "text",
"text": { "body": "Your order has been packed." }
}'
Template#
curl -X POST https://voice-api.edesy.in/v1/whatsapp/messages \
-H "Authorization: Bearer sk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"phone_number_id": "your-edesy-phone-number-uuid",
"to": "+919876543210",
"type": "template",
"template": {
"name": "order_update",
"language": { "code": "en_US" },
"components": [
{ "type": "body", "parameters": [ { "type": "text", "text": "Asha" }, { "type": "text", "text": "#1042" } ] }
]
}
}'
Document#
{
"phone_number_id": "your-edesy-phone-number-uuid",
"to": "+919876543210",
"type": "document",
"media": { "link": "https://example.com/invoice-1042.pdf", "filename": "invoice-1042.pdf", "caption": "Your invoice" }
}
Response 201#
{
"data": {
"id": "5b1c2d3e-0000-4000-8000-000000000000",
"conversation_id": "7d8e9f00-0000-4000-8000-000000000000",
"wamid": "wamid.HBgM...",
"direction": "outbound",
"type": "text",
"status": "sent",
"from": "+911234567890",
"to": "+919876543210",
"content": "Your order has been packed.",
"created_at": "2026-10-28T10:15:12Z"
},
"meta": { "request_id": "...", "timestamp": "2026-10-28T10:15:12Z" }
}
Other message endpoints#
| Method | Path | Description |
|---|---|---|
| GET | /messages |
List. Query: direction, status, type, from, to, conversation_id, page, per_page (default 20) |
| GET | /messages/{id} |
One message |
| POST | /messages/text |
Text shortcut. Body: phone_number_id, to, text, reply_to |
| POST | /messages/template |
Template shortcut. Body: phone_number_id, to, template_name, language, components |
Errors#
Errors return {"error": {"code": "...", "message": "..."}}.
| Code | Meaning |
|---|---|
VALIDATION_ERROR |
Missing or invalid field |
PHONE_NOT_WHATSAPP_ENABLED |
The number is not connected to WhatsApp, or messaging is off |
MESSAGING_WINDOW_EXPIRED |
More than 24 hours since the customer's last message; send a template |
TEMPLATE_NOT_FOUND |
No template with that name |
TEMPLATE_NOT_APPROVED |
The template is not approved yet |
RECIPIENT_BLOCKED |
The recipient has blocked the number |
META_API_ERROR |
Meta rejected the request |
RATE_LIMITED |
Too many requests; slow down and retry |
MESSAGE_NOT_FOUND |
No message with that ID |
FAQ#
Which number does the message come from?#
The Edesy number whose phone_number_id you send. Get the IDs from GET/v1/whatsapp/config.
Can I message a customer who has never written to me?#
Yes, with an approved template (type: "template"). Free-form text needs an open 24-hour window.
What phone format does to use?#
E.164, with the country code, e.g. +919876543210.
Can I send PDFs and images?#
Yes. Use type document or image with media.link (a public URL) or media.id.
How do I know a message was delivered or read?#
Subscribe to message.status on a webhook, or call GET/v1/whatsapp/messages/{id} and check status, delivered_at and read_at.
Are there official Node or Python SDKs?#
No. The API is plain HTTPS and JSON, so any HTTP client works.
Is there a test tool in the portal?#
Yes. The API Keys page has a "Try it - send a test message" panel that also shows the equivalent API request.