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.

Request Header
Authorization: Bearer wsa_your_api_key_here

Generate API keys from the Dashboard → API Keys section. Keys are shown once on creation — store them securely.

Login

POST/auth/login/Get JWT tokens
Request
curl -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

POST/otp/send/Send a verification code
Request
curl -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,
    "waba_id": "a1b2c3d4-5678-..."
  }'
Response (202)
{
  "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 connected WhatsApp account (phone number) to send from. If you have multiple phone numbers connected, use this to choose which one sends the OTP. Find the ID in your Dashboard → WhatsApp Integration. Defaults to your primary number if omitted.

Verify OTP

POST/otp/verify/Verify a code
Request
curl -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"}'
Response (200)
{
  "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

POST/messages/Send a WhatsApp message

to — Recipient phone number in international format (e.g. +2348012345678)

type — Message type: text, template, image, document, video, audio

waba_id — Optional. UUID of the connected WhatsApp account (phone number) to send from. If you have multiple phone numbers connected, use this to choose which one sends the message. Find the ID in your Dashboard → WhatsApp Integration. Defaults to your primary number if omitted.

Text Message

Request
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!",
    "waba_id": "a1b2c3d4-5678-..."
  }'

Template Message

Request
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",
    "waba_id": "a1b2c3d4-5678-..."
  }'

Image Message

Request
{
  "to": "+2348012345678",
  "type": "image",
  "url": "https://example.com/photo.jpg",
  "caption": "Check this out",
  "waba_id": "a1b2c3d4-5678-..."
}

Document Message

Request
{
  "to": "+2348012345678",
  "type": "document",
  "url": "https://example.com/invoice.pdf",
  "filename": "invoice.pdf",
  "waba_id": "a1b2c3d4-5678-..."
}

List Messages

GET/messages/list/List all messages with pagination
Request
curl 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

GET/messages/contacts/List contacts
POST/messages/contacts/Create a contact
PATCH/messages/contacts/{id}/Update a contact
DELETE/messages/contacts/{id}/Delete a contact
POST/messages/contacts/import/Import contacts from CSV
POST/messages/contacts/bulk-delete/Bulk delete contacts
GET/messages/contacts/segments/List segments with counts
Create Contact
curl -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.

GET/messages/campaigns/List campaigns
POST/messages/campaigns/Create and send a campaign
GET/messages/campaigns/{id}/Campaign details
Create Campaign
curl -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",
    "waba_id": "a1b2c3d4-5678-..."
  }'

segment — Send to all contacts in this segment. Alternatively, provide a phones array.

waba_id — Optional. UUID of the connected WhatsApp account to send from. Defaults to your primary number if omitted.

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

POST to your webhook URL
{
  "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.

Python
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

GET/billing/usage/Get current month usage
POST/billing/checkout/Create checkout session
Get Usage
curl 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.

CodeMeaning
200Success
201Created
202Accepted (queued for processing)
204No content (successful delete)
400Bad request — invalid parameters
401Unauthorized — invalid or missing API key
403Forbidden — email not verified or plan limit reached
404Not found
429Rate limit exceeded
500Internal server error

Rate Limits

API requests are rate-limited per tenant based on your plan.

PlanRequests/minCredits/moWhatsApp Accounts
Free10$00
Starter ($29)60$141
Growth ($99)500$605
Enterprise ($299)1,000$200Unlimited

OTP requests are additionally limited to 5 per phone number per hour. When rate limited, the API returns 429 Too Many Requests.