BeaconBox
Esc

Type to search.

Dashboard

Quickstart

A key, a pushed update, and the delivery status read back. Every call below is real and runs against your own account.

1. Get a key

In the dashboard, open Settings, name a key after whatever will hold it, and generate it.

Keys start with bbx_live_. The full value is shown once and never again, so copy it before you leave the page.

shell
export BEACONBOX_API_KEY=bbx_live_...

2. Install a client, if you want one

# Nothing to install. Every call is JSON over HTTPS.

The Python client reads BEACONBOX_API_KEY when you pass no key. The PHP client takes the key as its first argument and reads no environment variable, so pass it in yourself.

3. Push an update

This is the call you will spend your integration in. Everything else is optional.

curl https://api.beaconbox.eu/api/v1/messages \
-H "Authorization: Bearer $BEACONBOX_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-4711-shipped" \
-d '{
  "recipient_email": "buyer@example.com",
  "subject": "Your order has shipped",
  "body": "Tracking XY123456789EE. Estimated delivery Thursday.",
  "reference": "#A-10294",
  "order_status": "shipped",
  "kind": "updateable"
}'
Response · 201 Created
{
"id": "v55favd767qu",
"recipient_email": "buyer@example.com",
"subject": "Your order has shipped",
"kind": "updateable",
"status": "active",
"created": true,
"scheduled_for": null,
"nudged": true,
"email": {
  "sending": true,
  "skipped_reason": null
},
"sms": {
  "queued": false,
  "credits": 0,
  "skipped_reason": "no_phone",
  "escalates_at": null
},
"sms_units": 0,
"whatsapp": {
  "queued": false,
  "credits": 0,
  "skipped_reason": "no_phone",
  "sms_fallback": false,
  "escalates_at": null
},
"whatsapp_opt_in": null,
"reference": "#A-10294",
"order_status": "shipped",
"created_at": "2026-10-02T20:11:10.674762Z",
"updated_at": "2026-10-02T20:11:10.674762Z"
}

That is a success, and it is worth sitting with for a moment because it is the shape of every response here.

The update is in the customer’s inbox and an email is on its way. created: true means this made a new update rather than rewriting one, and nudged: true means a nudge was queued.

The two skipped_reason: "no_phone" entries are not errors. This account has SMS and WhatsApp switched on, the push carried no phone number, so both paid channels reported why they did not send and the request succeeded anyway. On an account with those channels off, sms and whatsapp are null instead: there was nothing to decide.

That is the convention the whole API runs on, and Reading outcomes is the page about it.

4. Push it again

Send the same subject to the same recipient with kind: "updateable" and the second push rewrites the first rather than joining it.

curl https://api.beaconbox.eu/api/v1/messages \
-H "Authorization: Bearer $BEACONBOX_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-4711-delivered" \
-d '{
  "recipient_email": "buyer@example.com",
  "subject": "Your order has shipped",
  "body": "Delivered and signed for at 14:20.",
  "reference": "#A-10294",
  "order_status": "delivered",
  "kind": "updateable"
}'

created is now false and nudged is false. The customer’s inbox is current and nobody was interrupted twice.

The rewrite takes its order_status and reference from the second push, so the update now reads as delivered. Leave order_status out of a rewrite and the status is cleared: the next nudge about this update has no status wording and no WhatsApp message.

5. Read what happened

Delivery is asynchronous, so it is not in the push response. Read the message back:

curl https://api.beaconbox.eu/api/v1/messages/v55favd767qu \
-H "Authorization: Bearer $BEACONBOX_API_KEY"

Polling is fine for a handful of messages and wrong for a shop. In production, subscribe to webhooks and let BeaconBox tell you.

Where to go next