Developer documentation
Build focused WhatsApp workflows with Whatsly
Pair a business number, create scoped API credentials, send supported messages and receive signed events without giving an integration unrestricted workspace access.
Implementation reference
- Device-scoped credentials
- Signed webhook events
- Idempotent message requests
- Workspace-controlled access
Quickstart
Whatsly uses workspace-controlled devices and scoped API keys. A connected WhatsApp number must be available before an external system can send a message.
- 1
Connect a number
Pair the company WhatsApp number from the Whatsly workspace and confirm that its connection status is healthy.
- 2
Create a dedicated API key
Create credentials for the specific device and workflow. Copy the secret when it is shown and store it in a secret manager.
- 3
Copy the API base URL
Use the API base URL displayed in your Whatsly workspace or integration settings. Do not assume that an example or old hostname is valid for your account.
- 4
Send a test message
Use an opted-in test recipient, a supported message type and a unique idempotency key.
- 5
Add a webhook
Subscribe to the message and device events your system needs, then verify every signature before processing the payload.
Use test contacts that you are authorized to message. API access does not remove your responsibility for consent, opt-outs or WhatsApp policy compliance.
Authentication and scopes
Public API requests use a key identifier and a secret. Credentials should belong to one approved integration and include only the permissions that workflow needs.
- X-Api-Key-ID
- The public identifier for the device-scoped credential.
- X-Api-Key-Secret
- The secret copied when the credential is created. Keep it outside source control and browser code.
- messages:send
- Allows the integration to send supported outbound messages through the selected device.
- messages:read
- Allows supported conversation or message reads where enabled for the plan and credential.
- device:status
- Allows the integration to inspect the selected device connection state.
Rotate a credential if it may have been exposed. Revoke credentials when the integration is removed or no longer needs access.
Send a message
Use the message endpoint for supported outbound types. Whatsly checks device ownership, subscription access, quotas, rate limits and abuse controls before accepting the send.
- text — a plain text body.
- media — a supported file delivered from an accessible HTTPS URL, with an optional caption.
- template — a saved Whatsly template populated with approved variables.
- location — latitude, longitude and an optional place name.
curl -X POST "$WHATSLY_API_BASE_URL/api/v1/messages/send" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "X-Api-Key-ID: <your-api-key-id>" \
-H "X-Api-Key-Secret: <your-api-key-secret>" \
-d '{
"device_id": 1,
"to": "+966500000000",
"message_type": "text",
"text": {
"body": "Hello from Whatsly"
},
"idempotency_key": "order-1001"
}'Set WHATSLY_API_BASE_URL to the value shown in your workspace. Phone numbers should use the international format expected by your configured workflow.
Templates and variables
Templates are created inside the Whatsly workspace and can be used for repeated operational messages. Variables personalize the message without rebuilding the body for every request.
- Named variables include {name}, {phone_number}, {my_name}, {my_email} and {my_contact_number}.
- Numbered API variables can use practical placeholders from {1} through {20}.
- The integration remains responsible for supplying accurate values and reviewing the final message workflow.
{
"device_id": 1,
"to": "+966500000000",
"message_type": "template",
"template_id": 12,
"variables": {
"name": "Ahmed",
"1": "Order #1001",
"2": "SAR 250"
},
"idempotency_key": "order-1001"
}Receive signed webhook events
Webhooks can notify an approved system about inbound messages, outbound outcomes and device state. Configure only the event types the receiving system needs.
- message.received
- A supported inbound message was received by the connected number.
- message.sent
- An outbound message reached the corresponding sent state.
- message.failed
- An outbound attempt failed and should be reviewed.
- device.connected
- The selected WhatsApp device is connected.
- device.disconnected
- The device connection is no longer available.
- device.connection.failed / device.revoked
- The connection failed or access was revoked and may require operator action.
{
"event_id": "evt_01H...",
"event_type": "message.received",
"occurred_at": "2026-06-03T10:00:00Z",
"tenant_id": 1,
"device_id": 1,
"data": {
"message": {
"id": 101,
"direction": "inbound",
"from_phone": "+966500000000",
"message_type": "text",
"body": "Hi, is my order ready?"
}
}
}Verify X-Whatsly-Signature with HMAC SHA-256 over the documented timestamp and raw request body. Reject invalid signatures before reading or storing event data.
Commerce integrations
Shopify and WooCommerce integrations turn selected store events into operational WhatsApp messages while leaving the commerce platform as the system of record.
- WooCommerce
- The available plugin supports selected order, payment, status, COD, cancellation and refund workflows.
- Shopify
- The hosted Shopify connector is in Early Access and supports selected order, payment, fulfillment and checkout workflows.
Use the dedicated integration guides for setup requirements, supported workflows and security guidance.
Handle errors predictably
Store the returned message identifier, keep idempotency keys stable for retries and treat rate or quota responses as a signal to slow down or review the integration.
- 401 / 403
- Check the key identifier, secret, scopes, device ownership, plan access and workspace permissions.
- 422
- Check the recipient number, required fields, body length, media URL, template variables and current device state.
- 429
- Slow the request rate and review device or workspace usage controls before retrying.
Do not retry every failure indefinitely. Use bounded retries, retain enough context for diagnosis and alert an operator when the connected number needs attention.