Send your first message

From API key to a delivered SMS and handling the reply and status callback, in minutes.

This quickstart takes you from an API key to a sent message, then shows how to receive the reply and delivery status. You'll need a manager (or admin) key and a workspace with a provisioned sender.

1. Send a single message

POST /api/v1/messages with exactly one item returns 201 Created with the queued message. {{variable}} tokens are substituted from variables; client_reference is echoed back on the message and every status callback.

curl -X POST https://app.beepmessaging.com/api/v1/messages \
  -H "Authorization: Bearer beep_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "X-Workspace-Id: 11111111-1111-1111-1111-111111111111" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {
        "to": "+15555550100",
        "body": "Hi {{first_name}}, your order shipped.",
        "variables": { "first_name": "Sam" },
        "client_reference": "order-9281"
      }
    ]
  }'
{
  "data": {
    "id": "a1b2c3d4-0000-0000-0000-000000000001",
    "to": "+15555550100",
    "status": "queued",
    "client_reference": "order-9281",
    "person_id": "b2c3d4e5-0000-0000-0000-000000000002",
    "phone_number_id": "c3d4e5f6-0000-0000-0000-000000000003"
  }
}

Every send acknowledgment includes person_id (the Beep contact profile the recipient resolved to) and phone_number_id (the sending number).

Link your own contact ids (identity handshake)

If your system has its own contact ids, pass them on each message item so Beep keeps your records and its profiles in sync:

{
  "to": "+15555550100",
  "body": "Hi Sam, your order shipped.",
  "external_id": "contact-42",
  "source_system": "my-crm"
}
  • An unknown external_id is recorded against the profile resolved from to (created if needed). Store the returned person_id to link the Beep profile from your side.
  • A known external_id is authoritative: future sends resolve to its profile even from a new phone number, and the number is attached to that profile.
  • external_id and source_system must be provided together. An optional external_id_type defaults to contact_id.

Make retries safe

Add an idempotency_key to each message (workspace-scoped, 24 hours). A retried batch can then be regrouped freely: items that already sent come back with their original id and deduplicated: true, an item whose key was reused with different content is rejected on its own (status: "rejected", error.code: "idempotency_conflict") without failing the batch, and the response counts accepted and rejected. The Idempotency-Key header still works for repeating an identical request. See Retries and idempotency for the full walkthrough.

2. Check delivery status

GET /api/v1/messages/{id} returns the current status (queued → sending → sent → delivered, or failed):

curl https://app.beepmessaging.com/api/v1/messages/a1b2c3d4-0000-0000-0000-000000000001 \
  -H "Authorization: Bearer beep_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "X-Workspace-Id: 11111111-1111-1111-1111-111111111111"

Polling works, but for push updates configure a status callback (step 4).

3. Route replies

Replies always land in the Beep inbox. To also forward them to your backend, create a webhook reply destination and pass its id when you send (reply_destination_id). See the Reply Destinations reference for the signed message.received payload and HMAC verification.

4. Subscribe to status callbacks

Set a workspace status-callback URL so Beep POSTs a signed event for each lifecycle transition (message.queued|sent|delivered|failed|opt_out):

curl -X PUT https://app.beepmessaging.com/api/v1/notification-settings \
  -H "Authorization: Bearer beep_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "X-Workspace-Id: 11111111-1111-1111-1111-111111111111" \
  -H "Content-Type: application/json" \
  -d '{
    "status_callback_url": "https://app.example.com/hooks/beep-status",
    "status_callback_secret": "a-strong-shared-secret-value"
  }'

Each callback is HMAC-SHA256 signed (X-Beep-Signature: sha256=<hex> over the raw body). Verify it in constant time — see Reply Destinations → Verifying the signature for the Node snippet.

You're done

You've sent a message, checked its status, and wired replies + status callbacks. Browse the API Reference for every endpoint.


Did this page help you?