ReachBellDocs

Transactional API

Transactional messages are sent to one recipient at a time, triggered by something happening in your application — a password reset, an order confirmation, a shipment update, a one-time code. They bypass the campaign builder.

Every transactional route authenticates with x-api-key (server-to-server only). The rate limit on each ingest endpoint is 120 requests per minute per IP.

Push

POST /transactional/send

Send a single push to one subscriber. You identify the subscriber either by externalId (preferred — your internal user ID, set via identify) or by their raw token.

curl -X POST https://api.reachbell.com/transactional/send \
  -H "x-api-key: rb_live_yourkey" \
  -H "Content-Type: application/json" \
  -d '{
    "externalId": "user_42",
    "title":      "Your order has shipped",
    "body":       "Tracking: 1Z999AA10123456784",
    "url":        "https://example.com/orders/A123",
    "iconUrl":    "https://cdn.example.com/icon-192.png",
    "imageUrl":   "https://cdn.example.com/order-hero.jpg",
    "badge":      "https://cdn.example.com/badge.png"
  }'

Response envelope

Transactional responses always come back with 200 OK and a structured envelope. Treat "not delivered" as a normal outcome, not an exception.

{
  "success":         true,
  "subscriberFound": true,
  "delivered":       true,
  "deactivated":     false,
  "reason":          null
}

Common reasons when delivered is false:

reasonWhat it means
subscriber_not_foundNo subscriber with that externalId or token on this project.
subscriber_unsubscribedThe user revoked permission.
frequency_cappedThe project's delivery policy blocks another push within the window.
quiet_hoursQuiet hours are active in the subscriber's timezone.
provider_errorFCM / APNs / VAPID rejected. Details in the dashboard.

Error responses are NORMAL, not exceptional. Your code should branch on delivered rather than throwing on every miss. Genuine bugs (bad payload, bad auth) still return non-2xx with the standard error envelope.

Email

POST /transactional/email
curl -X POST https://api.reachbell.com/transactional/email \
  -H "x-api-key: rb_live_yourkey" \
  -H "Content-Type: application/json" \
  -d '{
    "to":           "ada@example.com",
    "subject":      "Welcome to Acme",
    "htmlContent":  "<h1>Welcome</h1><p>Glad youre here.</p>",
    "textContent":  "Welcome. Glad youre here.",
    "senderEmail":  "hello@acme.com",
    "senderName":   "Acme Support",
    "replyTo":      "support@acme.com"
  }'

You can also send by template:

curl -X POST https://api.reachbell.com/transactional/email \
  -H "x-api-key: rb_live_yourkey" \
  -H "Content-Type: application/json" \
  -d '{
    "to":         "ada@example.com",
    "templateId": "tmpl_welcome",
    "variables":  { "name": "Ada", "ctaUrl": "https://acme.com/start" }
  }'

Sender domain enforcement

The senderEmail you pass must be on the project's verified email domain (the project.emailConfig.domain field) or a subdomain. If it isn't, the request returns 422 Unprocessable Entity with reason: "sender_domain_not_verified".

Verify your domain in Settings → Email → Domain setup before going live. Sending from an unverified domain blocks the API call outright — it doesn't silently rewrite the sender.

WhatsApp

POST /transactional/whatsapp
curl -X POST https://api.reachbell.com/transactional/whatsapp \
  -H "x-api-key: rb_live_yourkey" \
  -H "Content-Type: application/json" \
  -d '{
    "to":           "+14155551234",
    "message":      "Your verification code is 482910.",
    "templateName": "verification_code"
  }'

templateName is required for messages sent outside the 24-hour customer service window. The template must be pre-approved by Meta in the dashboard.

SMS

POST /transactional/sms
curl -X POST https://api.reachbell.com/transactional/sms \
  -H "x-api-key: rb_live_yourkey" \
  -H "Content-Type: application/json" \
  -d '{
    "to":       "+14155551234",
    "message":  "Your code is 482910. It expires in 5 minutes.",
    "senderId": "Acme"
  }'

senderId is the alphanumeric sender shown to the recipient. Carrier rules vary by country — in the US it's ignored in favor of a short code or long code provisioned in the dashboard.

Rate limits

Each ingest endpoint (send, email, whatsapp, sms) is independently capped at 120 requests per minute per IP. Exceeding a cap returns 429 Too Many Requests with a Retry-After header.

If you're sending more than 120/min sustained from one IP, batch via campaigns instead or contact support to raise the cap.

What's next?

  • Wire up your backend with the Subscribers API to identify users before sending.
  • Set up error handling for non-delivery reasons.
  • Automate multi-touch flows with Automations instead of one-off transactional calls.