Developer Tools

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`.

Required headers
bash
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.

GET/api/senders

List senders assigned to the API key.

ParameterTypeDescription
x-api-keyrequiredheaderCustomer API key.
Request
bash
curl "$HOOKMESSAGE_BASE_URL/api/senders" \
  -H "x-api-key: $HOOKMESSAGE_API_KEY"
200 response
json
[
  {
    "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"
  }
]
GET/api/senders/{sender_id}/status

Check sender connection state before sending.

ParameterTypeDescription
x-api-keyrequiredheaderCustomer API key assigned to the sender.
sender_idrequiredpath uuidSender ID returned by `GET /api/senders`.
Request
bash
curl "$HOOKMESSAGE_BASE_URL/api/senders/$HOOKMESSAGE_SENDER_ID/status" \
  -H "x-api-key: $HOOKMESSAGE_API_KEY"
200 response
json
{
  "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"
}
POST/api/messages/send

Queue a custom WhatsApp message.

ParameterTypeDescription
x-api-keyrequiredheaderAPI key with the `send_message` role.
sender_idrequireduuidConnected sender assigned to the API key.
receiver_numberrequiredstringRecipient phone number.
messagestringText body. Required unless sending an attachment.
Request
bash
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"
  }'
201 response
json
{
  "message_id": "2b7a0bd5-1a0d-4e6c-85b1-a7f44f92dfb0",
  "workspace_id": "f2aa1d49-9f4b-4f37-9918-d8d8f13fb530",
  "status": "queued",
  "duplicate": false
}
POST/api/otp/send

Send an OTP message through an assigned sender.

ParameterTypeDescription
x-api-keyrequiredheaderAPI key with the `otp` role.
sender_idrequireduuidConnected sender assigned to the API key.
receiver_numberrequiredstringRecipient phone number.
codestringOptional 4-10 digit code. If omitted, the server generates one.
Request
bash
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
  }'
201 response
json
{
  "message_id": "6d92aa83-8fb4-40f8-8ef2-83c2b8f0319f",
  "status": "queued",
  "duplicate": false,
  "otp_code": "482913",
  "expires_in_minutes": 10
}
GET/api/messages/{message_id}

Read the latest status for a queued message.

ParameterTypeDescription
x-api-keyrequiredheaderAPI key with access to the sender used by the message.
message_idrequiredpath uuidMessage ID returned by send or OTP endpoint.
Request
bash
curl "$HOOKMESSAGE_BASE_URL/api/messages/$MESSAGE_ID" \
  -H "x-api-key: $HOOKMESSAGE_API_KEY"
200 response
json
{
  "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.

download-openapi.sh
bash
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.yaml

Generate 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.

OpenAPI tools
bash
# 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