BulkSMSRates

API Documentation

Base URL: https://api.bulksmsrates.com

Format: JSON • Encoding: UTF-8

All endpoints require authentication unless noted. Responses include standard HTTP status codes.

Authentication

All API requests require a Bearer token in the Authorization header. Get your API key from the dashboard.

Authorization: Bearer bsr_live_abc123def456...

API keys start with bsr_live_ (production) or bsr_test_ (sandbox). Test keys send to a simulated network — no messages are delivered and no balance is charged.

Security: Never expose your API key in client-side code, public repositories, or logs. Use environment variables and server-side calls only.

Endpoints

MethodEndpointDescription
POST/v1/messagesSend single or batch SMS
GET/v1/messages/{id}Get message status and DLR
GET/v1/messagesList messages with filters and pagination
DELETE/v1/messages/{id}Cancel a scheduled message
GET/v1/balanceCheck account balance
POST/v1/webhooksCreate delivery report webhook
GET/v1/webhooksList configured webhooks
PUT/v1/webhooks/{id}Update a webhook
DELETE/v1/webhooks/{id}Delete a webhook
POST/v1/templatesCreate message template
GET/v1/templatesList templates
PUT/v1/templates/{id}Update a template
DELETE/v1/templates/{id}Delete a template
GET/v1/ratesList all country rates
GET/v1/rates/{country}Get per-network rates for a country
POST/v1/verifyValidate a phone number
GET/v1/accountGet account details and usage

Sending Messages

Single message

POST /v1/messages
{
  "to": "+447700900000",
  "body": "Hi {{name}}, your code is {{code}}",
  "from": "MyBrand",
  "merge_fields": { "name": "Sarah", "code": "482910" },
  "callback_url": "https://yourapp.com/dlr",
  "idempotency_key": "order-confirm-4821"
}

Batch send (up to 10,000)

POST /v1/messages
{
  "messages": [
    { "to": "+447700900001", "body": "Hi Alice, sale ends tonight!" },
    { "to": "+447700900002", "body": "Hi Bob, sale ends tonight!" }
  ],
  "from": "MyBrand"
}

Response

{
  "id": "msg_abc123",
  "to": "+447700900000",
  "from": "MyBrand",
  "body": "Hi Sarah, your code is 482910",
  "status": "queued",
  "segments": 1,
  "cost": 0.032,
  "currency": "GBP",
  "created_at": "2024-01-15T10:29:55Z"
}

Delivery Reports

Query message status via the API or receive real-time updates via webhooks.

GET /v1/messages/msg_abc123

{
  "id": "msg_abc123",
  "status": "delivered",       // queued | sent | delivered | failed | expired | rejected
  "status_code": "DELIVRD",    // SMPP status code
  "error_code": null,
  "submitted_at": "2024-01-15T10:29:55Z",
  "delivered_at": "2024-01-15T10:30:00Z",
  "network": "EE",
  "country": "GB"
}

See the Delivery Reports guide for full status code reference and webhook setup.

Webhooks

Configure webhook endpoints to receive real-time delivery reports and inbound SMS. Webhooks are signed with HMAC-SHA256 for security.

POST /v1/webhooks
{
  "url": "https://yourapp.com/sms-webhook",
  "events": ["delivered", "failed", "expired", "inbound"],
  "secret": "whsec_your_secret_key"
}

// Verify webhook signature:
// X-BSR-Signature: sha256=HMAC(payload, secret)

Webhooks retry 3 times with exponential backoff (5s, 30s, 5min) on non-2xx responses. Failed webhooks are logged and visible in the dashboard.

Error Codes

CodeNameDescription
400Bad RequestThe request body is malformed or missing required fields.
401UnauthorizedAPI key is missing, invalid, or expired.
402Payment RequiredInsufficient account balance to send the message(s).
404Not FoundThe requested resource (message, webhook, template) doesn't exist.
409ConflictDuplicate request or resource already exists.
422Unprocessable EntityValidation failed (e.g. invalid phone number, empty body, sender ID too long).
429Too Many RequestsRate limit exceeded.
500Internal Server ErrorSomething went wrong on our end.
503Service UnavailableTemporary maintenance or overload.
// Error response format
{
  "error": {
    "code": "validation_error",
    "message": "Invalid phone number format",
    "details": [
      { "field": "to", "message": "Must be E.164 format (e.g. +447700900000)" }
    ]
  }
}

Rate Limits

PlanRequests/secBatch size
Free trial10100
Pay-as-you-go10010,000
Enterprise1,000+100,000

Rate limit headers are included in every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.

Idempotency

Prevent duplicate sends by including an idempotency_key in your POST requests. If we receive the same key within 24 hours, we return the original response without re-sending.

POST /v1/messages
{
  "to": "+447700900000",
  "body": "Your OTP is 482910",
  "idempotency_key": "otp-user-123-attempt-1"
}

Official SDKs

Python

pip install bulksmsrates

v1.2.0

Node.js

npm install bulksmsrates

v1.1.0

PHP

composer require bulksmsrates/sdk

v1.0.3

Ruby

gem install bulksmsrates

v1.0.1