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
Hosted HookMessage customers use `https://api.hookmessage.com` as `HOOKMESSAGE_BASE_URL`. Only self-hosted contributors should replace it with another backend origin.
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.
The customer website is `https://www.hookmessage.com`; it is not the API base URL.
- Hosted production API`https://api.hookmessage.com`.
- Local contributor API`http://localhost:8080` when the backend runs locally.
- Required header`x-api-key: $HOOKMESSAGE_API_KEY`.
- JSON body header`content-type: application/json`.
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_id | uuid | Paid mode only: connected sender assigned to the API key. Omit for managed routing. |
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 '{
"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/sendGenerate and queue an OTP through managed routing or an assigned connected sender.
| Parameter | Type | Description |
|---|---|---|
x-api-keyrequired | header | API key with the `otp` role. |
sender_id | uuid | Paid mode only: connected sender assigned to the API key. Omit for managed routing. |
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 '{
"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"
}Sender field depends on the plan mode
Omit `sender_id` for managed Free Sandbox or an API key configured for automatic platform routing. Include an assigned connected sender ID when a paid integration must use your own number.
OpenAPI file
Download the hosted contract from `https://api.hookmessage.com/openapi.yaml`. Use it to inspect schemas, import endpoints into an API client, or generate types.
The documentation website also exposes `/openapi.yaml` as a convenience proxy.
- Direct contract`https://api.hookmessage.com/openapi.yaml`.
- Toolsimport into Postman, Insomnia, Stoplight, or OpenAPI Generator.
- Securitygenerated clients must receive the API key from server-only secret storage.
curl "https://api.hookmessage.com/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.
Continue building
Next steps
SDK setup and examples
Choose a sender mode, configure server-only secrets, then call the same REST contract from your language.
Complete integration examples
Use these end-to-end examples after cURL succeeds.
Errors and limits
Use status codes and message status records to decide whether to retry, fix input, reconnect a sender, or upgrade limits.
Troubleshooting
Use this page when a new integration does not send, status stays queued, or webhook verification fails.