sendbaze
Menu

Reference

API reference

Base URL https://api.sendbaze.com/v1. JSON in, JSON out. Bearer authentication on every endpoint.

Request and response headers

FieldTypeDescription
AuthorizationrequiredrequestBearer sk_live_… or Bearer sk_test_….
Idempotency-KeyrequestUp to 255 characters. Makes a POST safe to retry for 24 hours.
x-request-idresponseUnique per request. Quote it when you contact support.
x-ratelimit-limitresponseRequests per second allowed for your organisation.
x-ratelimit-remainingresponseRequests left in the current second.
Retry-AfterresponseSeconds to wait. Sent with 429 responses only.
Idempotent-Replayedresponsetrue when the response was served from an earlier request with the same key.

Emails

Send an email

POST/v1/emails

Validates the request, writes the message, queues it and returns the id. The email leaves through Amazon SES in the Africa (Cape Town) region within seconds. Requires the emails:send scope and a verified sending domain.

FieldTypeDescription
fromrequiredstringA verified sender. orders@yourshop.co.za or Yourshop <orders@yourshop.co.za>.
torequiredstring | string[]One address or up to 50.
ccstring | string[]Up to 50.
bccstring | string[]Up to 50.
replyTostringWhere replies go if not the sender.
subjectrequiredstringUp to 998 characters.
htmlstringHTML body, up to 2 MB. One of html, text or templateId is required.
textstringPlain-text body. Sent alongside html if both are set.
templateIdstringA template from the dashboard. Cannot be combined with html or text.
variablesobjectString, number or boolean values for template placeholders. Requires templateId.
headersobjectCustom headers. Standard headers such as From, To, Subject and DKIM-Signature cannot be overridden.
tagsstring[]Up to 10 tags of 64 characters, returned on events and searchable in the logs.
class"transactional" | "marketing"Defaults to transactional. Marketing mail gets List-Unsubscribe headers and requires a lawful basis for each recipient.
attachmentsobject[]Coming in the private beta. Requests with attachments are rejected until then.
terminal
curl https://api.sendbaze.com/v1/emails \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042-shipped" \
  -d '{
    "from": "Yourshop <orders@yourshop.co.za>",
    "to": ["thandi@example.com"],
    "replyTo": "help@yourshop.co.za",
    "subject": "Your order #1042 has shipped",
    "html": "<p>Tracking: <b>CG123456789ZA</b></p>",
    "text": "Tracking: CG123456789ZA",
    "tags": ["order-shipped"]
  }'

# 200 OK
# { "id": "em_01j9x7k2r4m8q3v5n6b7c8d9e0", "status": "queued" }

Send a batch of emails

POST/v1/emails/batch

Up to 1 000 emails in one request. Each item is validated and queued on its own, so a bad item fails alone. Results come back in input order. Idempotency-Key is not applied to individual items; use tags to reconcile.

terminal
curl https://api.sendbaze.com/v1/emails/batch \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "emails": [
      { "from": "orders@yourshop.co.za", "to": "a@example.com", "subject": "Hi", "text": "..." },
      { "from": "orders@yourshop.co.za", "to": "not-an-email", "subject": "Hi", "text": "..." }
    ]
  }'

# 200 OK
# {
#   "results": [
#     { "index": 0, "ok": true,  "data": { "id": "em_01j9...", "status": "queued" } },
#     { "index": 1, "ok": false, "error": { "code": "validation_error", "message": "...",
#                                           "fields": { "to": ["must be a valid email address"] } } }
#   ]
# }

Retrieve an email

GET/v1/emails/{id}

Returns the message object with its full event timeline. Requires the read scope.

SMS

Send an SMS

POST/v1/sms

Counts segments (GSM-7 or UCS-2), checks credits, applies the compliance rules for the message class, debits credits and queues the message. Credits are refunded automatically if the message never leaves our platform. Requires the sms:send scope.

FieldTypeDescription
torequiredstringE.164, for example +27821234567.
bodyrequiredstringUp to 1,600 characters or 10 segments. The response tells you how many segments it used.
classrequired"transactional" | "marketing"Marketing messages need a consent record for the number, an opt-out footer, and are held to 08:00 to 20:00 SAST on weekdays and Saturdays.
senderIdstringAn approved alphanumeric sender of up to 11 characters, or a number you own. Defaults to your organisation's shared sender.
scheduledAtstringISO 8601 timestamp up to 30 days ahead. The response status is "scheduled".
tagsstring[]Up to 10 tags.
terminal
curl https://api.sendbaze.com/v1/sms \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+27821234567",
    "body": "Your OTP is 482 913. It expires in 5 minutes.",
    "class": "transactional"
  }'

# 200 OK
# { "id": "sm_01j9x7n4q6r8s0t2u4v6w8x0y2", "status": "queued", "segments": 1, "credits": 1 }
Marketing SMS outside the legal window is not rejected. It is held and sent at 08:00 SAST on the next permitted day, and the response status is scheduled.

Send a batch of SMS

POST/v1/sms/batch

Same shape as the email batch with a messages array of up to 1 000 items. If credits run out part-way, the remaining items fail with insufficient_credits and the earlier ones still send.

Retrieve an SMS

GET/v1/sms/{id}

Returns the message object with segments, credits, scheduledAt and the event timeline.

The message object

FieldTypeDescription
idstringem_… for email, sm_… for SMS.
channel"email" | "sms"
classstringtransactional or marketing.
statusstringqueued, sent, delivered, bounced, complained, failed, expired or rejected. See below.
tostringRecipient address or number.
fromstringSender address or sender ID.
subjectstring | nullEmail only.
segmentsnumberSMS only.
creditsnumberSMS only. Credits debited for this message.
tagsstring[]
error{ code, message } | nullSet once the message has failed, bounced or been rejected.
createdAtstring
sentAtstring | null
deliveredAtstring | null
eventsobject[]The full timeline, oldest first: { type, occurredAt, detail }.

Statuses

  • queued: accepted and waiting for a worker. Usually under a second.
  • sent: handed to Amazon SES or the mobile network.
  • delivered: the receiving server or handset confirmed delivery.
  • bounced and complained: email only. Both suppress the address.
  • failed: permanent failure after retries. error says why.
  • expired: SMS only. The network could not deliver within its validity period.
  • rejected: blocked before sending, for example a suppressed address or a missing consent record.

Idempotency

Send an Idempotency-Key with any POST. For 24 hours the same key and body return the original response with an Idempotent-Replayed: true header. The same key with a different body or on a different channel returns 409. If a request fails before the message is queued, the key is released so your retry goes through.

terminal
# First request
curl https://api.sendbaze.com/v1/sms -H "Idempotency-Key: otp-4821-1" ...
# 200 { "id": "sm_01j9...", ... }

# Same key, same body, within 24 hours
curl https://api.sendbaze.com/v1/sms -H "Idempotency-Key: otp-4821-1" ...
# 200 { "id": "sm_01j9...", ... }   header: Idempotent-Replayed: true

# Same key, different body
# 409 { "error": { "code": "idempotency_conflict", ... } }

Rate limits

100 requests per second per organisation, shared across all its keys. The batch endpoints count as one request each, so bulk sends should use them. Above the limit the API returns 429 with Retry-After.

Test mode

Keys that start with sk_test_ run every validation and compliance check and return an id, but never enqueue, never debit credits and never send. Test messages appear in the logs with a test badge and in GET lookups with status sent. Use them in CI and staging.

Errors

Every error shares one envelope with a stable code. See the errors reference.