REST API
Use the HTTP API directly from your backend for sender discovery, OTP, custom messages, message status, and OpenAPI reference.
Base URL and headers
Use your deployed HookMessage backend URL as `HOOKMESSAGE_BASE_URL`. In local development that is usually the API server origin; in production it is the public API origin configured for your deployment.
Customer integration requests must be sent from your backend with JSON headers and `x-api-key`. Do not call API-key endpoints from browser JavaScript.
Do not use the dashboard URL unless the dashboard and API share the same origin in your deployment. The base URL must be the server that mounts `/api/senders`, `/api/messages`, `/api/otp`, and `/health`.
curl "$HOOKMESSAGE_BASE_URL/api/senders" \
-H "content-type: application/json" \
-H "x-api-key: $HOOKMESSAGE_API_KEY"Core customer endpoints
These are the endpoints a normal customer integration can use with an API key. Management tasks such as creating keys, assigning senders, configuring webhooks, and billing are handled in the dashboard.
A successful send response means the message was accepted into the queue. Store `message_id` and check delivery through polling, webhooks, or dashboard history.
/api/sendersList senders assigned to the API key.
| Parameter | Type | Description |
|---|---|---|
x-api-keyrequired | header | Customer API key. |
curl "$HOOKMESSAGE_BASE_URL/api/senders" \
-H "x-api-key: $HOOKMESSAGE_API_KEY"[
{
"sender_id": "9f4b5d4c-0000-4000-9000-123456789abc",
"workspace_id": "f2aa1d49-9f4b-4f37-9918-d8d8f13fb530",
"phone_number": "212612345678",
"display_name": "Main support",
"status": "connected",
"trust_tier": "trusted",
"daily_limit": 500,
"messages_sent_today": 12,
"is_active": true,
"connected_at": "2026-06-29T16:00:00.000Z",
"created_at": "2026-06-29T15:50:00.000Z"
}
]/api/senders/{sender_id}/statusCheck sender connection state before sending.
| Parameter | Type | Description |
|---|---|---|
x-api-keyrequired | header | Customer API key assigned to the sender. |
sender_idrequired | path uuid | Sender ID returned by `GET /api/senders`. |
curl "$HOOKMESSAGE_BASE_URL/api/senders/$HOOKMESSAGE_SENDER_ID/status" \
-H "x-api-key: $HOOKMESSAGE_API_KEY"{
"sender_id": "9f4b5d4c-0000-4000-9000-123456789abc",
"workspace_id": "f2aa1d49-9f4b-4f37-9918-d8d8f13fb530",
"phone_number": "212612345678",
"status": "connected",
"connected_at": "2026-06-29T16:00:00.000Z"
}/api/messages/sendQueue a custom WhatsApp message.
| Parameter | Type | Description |
|---|---|---|
x-api-keyrequired | header | API key with the `send_message` role. |
sender_idrequired | uuid | Connected sender assigned to the API key. |
receiver_numberrequired | string | Recipient phone number. |
message | string | Text body. Required unless sending an attachment. |
curl -X POST "$HOOKMESSAGE_BASE_URL/api/messages/send" \
-H "content-type: application/json" \
-H "x-api-key: $HOOKMESSAGE_API_KEY" \
-d '{
"sender_id": "9f4b5d4c-0000-4000-9000-123456789abc",
"receiver_number": "212612345678",
"message": "Your order is confirmed.",
"idempotency_key": "order:1042:confirmed"
}'{
"message_id": "2b7a0bd5-1a0d-4e6c-85b1-a7f44f92dfb0",
"workspace_id": "f2aa1d49-9f4b-4f37-9918-d8d8f13fb530",
"status": "queued",
"duplicate": false
}/api/otp/sendSend an OTP message through an assigned sender.
| Parameter | Type | Description |
|---|---|---|
x-api-keyrequired | header | API key with the `otp` role. |
sender_idrequired | uuid | Connected sender assigned to the API key. |
receiver_numberrequired | string | Recipient phone number. |
code | string | Optional 4-10 digit code. If omitted, the server generates one. |
curl -X POST "$HOOKMESSAGE_BASE_URL/api/otp/send" \
-H "content-type: application/json" \
-H "x-api-key: $HOOKMESSAGE_OTP_KEY" \
-d '{
"sender_id": "9f4b5d4c-0000-4000-9000-123456789abc",
"receiver_number": "212612345678",
"app_name": "My Store",
"ttl_minutes": 10
}'{
"message_id": "6d92aa83-8fb4-40f8-8ef2-83c2b8f0319f",
"status": "queued",
"duplicate": false,
"otp_code": "482913",
"expires_in_minutes": 10
}/api/messages/{message_id}Read the latest status for a queued message.
| Parameter | Type | Description |
|---|---|---|
x-api-keyrequired | header | API key with access to the sender used by the message. |
message_idrequired | path uuid | Message ID returned by send or OTP endpoint. |
curl "$HOOKMESSAGE_BASE_URL/api/messages/$MESSAGE_ID" \
-H "x-api-key: $HOOKMESSAGE_API_KEY"{
"message_id": "2b7a0bd5-1a0d-4e6c-85b1-a7f44f92dfb0",
"workspace_id": "f2aa1d49-9f4b-4f37-9918-d8d8f13fb530",
"sender_id": "9f4b5d4c-0000-4000-9000-123456789abc",
"api_client_id": "38b7bbd3-0631-4ea1-a93b-09d560a645d3",
"receiver_number": "212612345678",
"message_text": "Your order is confirmed.",
"status": "sent",
"wamid": "wamid.HBgM...",
"source_system": "checkout",
"source_reference": "order_1042",
"error_message": null,
"attempts": 1,
"queued_at": "2026-06-29T16:12:01.000Z",
"sent_at": "2026-06-29T16:12:04.000Z",
"failed_at": null,
"created_at": "2026-06-29T16:12:01.000Z"
}OpenAPI file
The docs home links to `/openapi.yaml`, which proxies the backend OpenAPI YAML when `BACKEND_BASE_URL` is configured for the frontend.
Use that file to generate clients, inspect request schemas, and keep integration tests aligned with the deployed backend.
If `/openapi.yaml` returns `BACKEND_BASE_URL is not configured`, set the frontend environment variable to the backend API origin. If it returns `OpenAPI document is unavailable`, verify the backend serves `/openapi.yaml` and is reachable from the frontend server.
curl "$FRONTEND_BASE_URL/openapi.yaml" -o hookmessage.openapi.yaml
# Or fetch directly from the backend when you know the API origin.
curl "$HOOKMESSAGE_BASE_URL/openapi.yaml" -o hookmessage.openapi.yamlGenerate clients and import Postman
Use the OpenAPI file when you want generated types, generated HTTP clients, or a Postman collection for manual testing.
Generated clients should still be wrapped by your backend service layer so API keys, retries, idempotency, and logging stay consistent.
# TypeScript fetch client
npx @openapitools/openapi-generator-cli generate \
-i hookmessage.openapi.yaml \
-g typescript-fetch \
-o generated/hookmessage
# Python client
npx @openapitools/openapi-generator-cli generate \
-i hookmessage.openapi.yaml \
-g python \
-o generated/hookmessage-python
# Postman import
# Open Postman > Import > Files > choose hookmessage.openapi.yaml.
# Add x-api-key as a collection variable or authorization header.Error handling
Treat non-2xx responses as rejected requests. Treat queued messages as asynchronous work and use status polling or webhooks for final delivery state.
Retry network failures and 5xx responses with backoff. Do not retry validation errors, sender access errors, or quota errors until the input or workspace state changes.
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.