Overview
The Hawk Send API lets you send WhatsApp messages, deliver OTP verification codes, and manage contacts programmatically. All endpoints are RESTful and return JSON.
Base URLhttps://api.hawksend.com/api/v1
Authentication
All API requests require authentication via a Bearer token. Use your API key (starts with wsa_) in the Authorization header.
Authorization: Bearer wsa_your_api_key_hereGenerate API keys from the Dashboard → API Keys section. Keys are shown once on creation — store them securely.
Login
/auth/login/— Get JWT tokenscurl -X POST https://api.hawksend.com/api/v1/auth/login/ \
-H "Content-Type: application/json" \
-d '{"email": "john@company.com", "password": "securepassword"}'OTP Verification
Send and verify one-time passwords via WhatsApp. OTP codes are hashed before storage and automatically expire.
Send OTP
/otp/send/— Send a verification codecurl -X POST https://api.hawksend.com/api/v1/otp/send/ \
-H "Authorization: Bearer wsa_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"to": "+2348012345678",
"code_length": 6,
"expiry": 300
}'{
"otp_id": "a3f8e4b2-9c1d-4e5f...",
"to": "+2348012345678",
"expires_at": "2026-04-05T10:05:00Z",
"status": "pending"
}code_length — 4 to 8 digits (default: 6)
expiry — 60 to 600 seconds (default: 300)
waba_id — Optional. UUID of the WhatsApp account to send from.
Verify OTP
/otp/verify/— Verify a codecurl -X POST https://api.hawksend.com/api/v1/otp/verify/ \
-H "Authorization: Bearer wsa_your_api_key" \
-H "Content-Type: application/json" \
-d '{"to": "+2348012345678", "code": "845291"}'{
"verified": true,
"to": "+2348012345678",
"verified_at": "2026-04-05T10:02:30Z"
}Messages
Send WhatsApp messages in multiple formats. All messages are queued and processed asynchronously.
Send Message
/messages/— Send a WhatsApp messageText Message
curl -X POST https://api.hawksend.com/api/v1/messages/ \
-H "Authorization: Bearer wsa_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"to": "+2348012345678",
"type": "text",
"body": "Hello from Hawk Send!"
}'Template Message
curl -X POST https://api.hawksend.com/api/v1/messages/ \
-H "Authorization: Bearer wsa_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"to": "+2348012345678",
"type": "template",
"template_name": "hello_world",
"language": "en_US"
}'Image Message
{
"to": "+2348012345678",
"type": "image",
"url": "https://example.com/photo.jpg",
"caption": "Check this out"
}Document Message
{
"to": "+2348012345678",
"type": "document",
"url": "https://example.com/invoice.pdf",
"filename": "invoice.pdf"
}List Messages
/messages/list/— List all messages with paginationcurl https://api.hawksend.com/api/v1/messages/list/?status=delivered&page=1 \
-H "Authorization: Bearer wsa_your_api_key"Filters: status, direction, message_type, page
Statuses: queued, sent, delivered, read, failed
Directions: outbound, inbound
Types: text, template, image, document, otp
Contacts
/messages/contacts/— List contacts/messages/contacts/— Create a contact/messages/contacts/{id}/— Update a contact/messages/contacts/{id}/— Delete a contact/messages/contacts/import/— Import contacts from CSV/messages/contacts/bulk-delete/— Bulk delete contacts/messages/contacts/segments/— List segments with countscurl -X POST https://api.hawksend.com/api/v1/messages/contacts/ \
-H "Authorization: Bearer wsa_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Amina",
"last_name": "Kofi",
"phone": "+233554239901",
"tags": ["VIP", "Lagos"],
"segment": "Premium"
}'Campaigns
Send bulk messages to a contact segment or a list of phone numbers.
/messages/campaigns/— List campaigns/messages/campaigns/— Create and send a campaign/messages/campaigns/{id}/— Campaign detailscurl -X POST https://api.hawksend.com/api/v1/messages/campaigns/ \
-H "Authorization: Bearer wsa_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Q1 Promo",
"segment": "Premium",
"message_type": "template",
"template_name": "promo_q1_2026",
"template_language": "en_US"
}'Webhooks
Hawk Send delivers real-time events to your webhook URL via POST requests. Each WhatsApp account has its own webhook URL and signing secret.
Event Types
message.status — Delivery status updates (sent, delivered, read, failed)
message.received — Inbound messages from customers
otp.verified — OTP code verified successfully
Payload Example
{
"event": "message.status",
"data": {
"message_id": "a3f8e4b2-9c1d-4e5f...",
"status": "delivered",
"to": "+2348012345678",
"timestamp": "2026-04-05T09:30:00Z"
},
"event_id": "evt_...",
"timestamp": "2026-04-05T09:30:01Z"
}Signature Verification
Verify the X-HawkSend-Signature header by computing the HMAC SHA-256 of the raw body using your webhook secret.
import hmac, hashlib
def verify(payload_bytes, signature, secret):
expected = hmac.new(
secret.encode(), payload_bytes, hashlib.sha256
).hexdigest()
return hmac.compare_digest(
f"sha256={expected}", signature
)Billing
/billing/usage/— Get current month usage/billing/checkout/— Create Stripe checkout sessioncurl https://api.hawksend.com/api/v1/billing/usage/ \
-H "Authorization: Bearer wsa_your_api_key"Errors
The API returns standard HTTP status codes. Error responses include a JSON body with an error field.
| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 202 | Accepted (queued for processing) |
| 204 | No content (successful delete) |
| 400 | Bad request — invalid parameters |
| 401 | Unauthorized — invalid or missing API key |
| 403 | Forbidden — email not verified or plan limit reached |
| 404 | Not found |
| 429 | Rate limit exceeded |
| 500 | Internal server error |
Rate Limits
API requests are rate-limited per tenant based on your plan.
| Plan | Requests/min | Credits/mo | WhatsApp Accounts |
|---|---|---|---|
| Free | 10 | $0 | 0 |
| Starter ($29) | 60 | $14 | 1 |
| Growth ($99) | 500 | $60 | 5 |
| Enterprise ($299) | 1,000 | $200 | Unlimited |
OTP requests are additionally limited to 5 per phone number per hour. When rate limited, the API returns 429 Too Many Requests.