Send customer messages
Queue customer notifications, confirmations, reminders, and support messages.
What the endpoint does
The send endpoint validates the API key, verifies sender ownership, checks plan and sender limits, stores a message record, and queues delivery.
A successful response means the message was accepted into the queue. It does not mean the recipient has already received it. Use the message status endpoint or dashboard history for delivery state.
Endpoint reference
The request must include `receiver_number` and either `message` or `attachment`. Include `sender_id` for an assigned sender, or omit it only when the API key uses random platform sender mode.
Text messages can be up to 4096 characters. Attachments are base64-encoded, limited by the request schema and the decoded storage limit.
/api/messages/sendQueue an outbound WhatsApp customer message.
| Parameter | Type | Description |
|---|---|---|
x-api-keyrequired | header | API key with the `send_message` role. |
sender_id | uuid | Connected sender assigned to the API key. Omit only for a key configured with random platform sender mode. |
receiver_numberrequired | string | Destination phone number. |
message | string | Message body, max 4096 characters. Required unless attachment is present. |
attachment.file_name | string | Attachment name, max 180 characters. |
attachment.mime_type | string | Attachment content type, max 120 characters. |
attachment.content_base64 | string | Base64 content, max 10,000,000 characters. |
priority | integer | Queue priority from 1 to 10. |
source_system | string | Integration name, max 80 characters. |
source_reference | string | Your record ID, max 120 characters. |
idempotency_key | string | Duplicate protection key, max 160 characters. |
{
"sender_id": "9f4b5d4c-0000-4000-9000-123456789abc",
"receiver_number": "212612345678",
"message": "Your appointment is confirmed for tomorrow at 10:00.",
"source_system": "appointments",
"source_reference": "booking_1042",
"idempotency_key": "booking_1042_confirmation"
}{
"message_id": "2b7a0bd5-1a0d-4e6c-85b1-a7f44f92dfb0",
"workspace_id": "f2aa1d49-9f4b-4f37-9918-d8d8f13fb530",
"status": "queued",
"duplicate": false
}Attachment messages
Use `attachment` when sending an image or document. The backend accepts either raw base64 or a `data:*;base64,` URL and stores the decoded file before delivery.
The request field `attachment.content_base64` accepts up to 10,000,000 characters, but the decoded file must be 5 MB or smaller.
{
"sender_id": "9f4b5d4c-0000-4000-9000-123456789abc",
"receiver_number": "212612345678",
"message": "Invoice attached.",
"attachment": {
"file_name": "invoice-1042.pdf",
"mime_type": "application/pdf",
"content_base64": "JVBERi0xLjQK..."
},
"source_system": "billing",
"source_reference": "invoice_1042",
"idempotency_key": "invoice:1042:sent"
}Laravel example
Wrap HookMessage behind a service class so controllers do not know about headers, retry logic, or provider details.
use Illuminate\Support\Facades\Http;
$response = Http::baseUrl(config('services.hookmessage.url'))
->withHeaders([
'x-api-key' => config('services.hookmessage.key'),
])
->post('/api/messages/send', [
'sender_id' => config('services.hookmessage.sender_id'),
'receiver_number' => $order->customer_phone,
'message' => "Your order {$order->number} is confirmed.",
'source_system' => 'checkout',
'source_reference' => (string) $order->id,
'idempotency_key' => "order:{$order->id}:confirmed",
]);
$response->throw();
$message = $response->json();Need help?
Use Book Integration Help if you want setup help for OTP or automated customer messaging.
Next steps
Quickstart
A practical path from empty workspace to a working server-side integration.
Authentication and access
HookMessage separates customer API keys, dashboard sessions, and internal platform access.
Workspaces
A workspace is the tenant boundary for every customer resource.
Senders and sessions
A sender is the WhatsApp number used to deliver messages for a workspace.