মূল অংশে যান

অনুগ্রহ করে অপেক্ষা করুন...

Amarseba API

Developer documentation

ইউনিয়ন সনদপত্র যাচাই

Sending SMS

Send one SMS, the same SMS to many numbers, a different SMS to each number, or an SMS to a saved group. Every send endpoint validates the whole request, charges your wallet once for the total, and returns 202 Accepted with the batch and message IDs you use for tracking.

Send modes

Mode Endpoint Batch type
One number, one bodyPOST /bulk-sms/send with exactly one number in to, as a string or a one-item arraysingle
Many numbers, same bodyPOST /bulk-sms/send with to as an array of 2 to 10,000 numbersbroadcast
Many numbers, own body eachPOST /bulk-sms/send-many with messages, up to 10,000 items of {to, body}personalized
A saved groupPOST /bulk-sms/groups/{group_id}/sendgroup

Recipients

  • Accepted formats: 01XXXXXXXXX, 8801XXXXXXXXX and +8801XXXXXXXXX, with an operator prefix from 013 to 019. Numbers are normalized to 8801XXXXXXXXX in responses.
  • Duplicates within one broadcast or group send are removed, so each number is sent and charged once. send-many keeps a repeated number only when its bodies differ.
  • Any invalid number rejects the whole request with 422 validation_error, one entry per bad number under its input path (to.4, messages.2.to). The API never partially accepts a request, so a charge is never a surprise.
  • More than 10,000 recipients in one request returns 422 under to or messages. Group sends have no 10,000-recipient cap: large groups are sent in background chunks.

Sender ID

  • Omit from to send from the default non-masking sender at the non-masking rate.
  • Set from to one of your approved masking names to send with your brand name at the masking rate. Any other value returns 422 under from. Group sends honour from too.
  • Call GET /bulk-sms/senders to list every sender you can use, with the price per part your account pays for it.

Body

The SMS text goes in body. It can be up to 10 parts long; see Encoding, parts and pricing for how parts are counted. A longer body returns 422 under body (or messages.N.body) stating the actual part count.

Every body is checked automatically for harmful content before anything is charged. A rejected body returns 422 content_rejected and nothing is charged or queued. The response never says which words matched. If a normal, harmless message is rejected, contact support.

What happens after 202

  • The total cost is debited from your wallet once, when the request is accepted. If the wallet cannot cover it you get 402 insufficient_balance and nothing is charged or queued.
  • Every message starts as queued. Messages are sent in the background in chunks and move to sending, then sent or failed.
  • Every failed message is refunded to your wallet exactly once.
  • When the batch has 1,000 recipients or fewer, the response embeds messages. Above 1,000, messages is omitted and messages_url points to /bulk-sms/batches/{batch_id}/messages.

Endpoints

GET /bulk-sms/senders Scope: bulk-sms:read

List the sender IDs you can put in from. The default sender comes first with is_default true, followed by your approved masking names. rate_per_part is the price your account pays for one SMS part from that sender.

Request
curl -X GET https://e-amarseba.com/api/v1/bulk-sms/senders \
  -H "Authorization: Bearer $AMARSEBA_API_KEY" \
  -H "Accept: application/json"
use Illuminate\Support\Facades\Http;

$response = Http::withToken(config('services.amarseba.key'))
    ->acceptJson()
    ->get('https://e-amarseba.com/api/v1/bulk-sms/senders');

$result = $response->json();
const response = await fetch("https://e-amarseba.com/api/v1/bulk-sms/senders", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.AMARSEBA_API_KEY}`,
    Accept: "application/json",
  },
});

const result = await response.json();
import os

import requests

response = requests.get(
    "https://e-amarseba.com/api/v1/bulk-sms/senders",
    headers={
        "Authorization": f"Bearer {os.environ['AMARSEBA_API_KEY']}",
        "Accept": "application/json",
    },
)

result = response.json()
Response
200application/json
{
    "success": true,
    "message": "Sender IDs retrieved",
    "data": [
        {
            "sender": "Amarseba",
            "is_masking": false,
            "is_default": true,
            "rate_per_part": "0.30",
            "currency": "BDT"
        },
        {
            "sender": "MyShop",
            "is_masking": true,
            "is_default": false,
            "rate_per_part": "0.50",
            "currency": "BDT"
        }
    ],
    "code": 200,
    "timestamp": "2026-09-26T10:00:00.000000Z"
}
POST /bulk-sms/send Scope: bulk-sms:send

Send one body to one number or to a list of numbers.

Parameters
Name Type Required Description
to string or string[] Yes One number, or an array of up to 10,000 numbers.
body string Yes The SMS text, up to 10 parts.
from string No An approved masking name. Omit for the default sender.
Request
curl -X POST https://e-amarseba.com/api/v1/bulk-sms/send \
  -H "Authorization: Bearer $AMARSEBA_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "to": [
        "01712345678",
        "01812345678"
    ],
    "body": "Your OTP is 4821. It expires in 5 minutes."
}'
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;

$response = Http::withToken(config('services.amarseba.key'))
    ->acceptJson()
    ->withHeaders(['Idempotency-Key' => (string) Str::uuid()])
    ->post('https://e-amarseba.com/api/v1/bulk-sms/send', [
        'to' => [
            '01712345678',
            '01812345678',
        ],
        'body' => 'Your OTP is 4821. It expires in 5 minutes.',
    ]);

$result = $response->json();
const response = await fetch("https://e-amarseba.com/api/v1/bulk-sms/send", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.AMARSEBA_API_KEY}`,
    Accept: "application/json",
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
      "to": [
          "01712345678",
          "01812345678"
      ],
      "body": "Your OTP is 4821. It expires in 5 minutes."
  }),
});

const result = await response.json();
import os
import uuid

import requests

response = requests.post(
    "https://e-amarseba.com/api/v1/bulk-sms/send",
    headers={
        "Authorization": f"Bearer {os.environ['AMARSEBA_API_KEY']}",
        "Accept": "application/json",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "to": [
            "01712345678",
            "01812345678",
        ],
        "body": "Your OTP is 4821. It expires in 5 minutes.",
    },
)

result = response.json()
Response
202application/json
{
    "success": true,
    "message": "SMS queued for delivery",
    "data": {
        "batch_id": "bat_01j8z3k6q9w2m4n7p5r8t1v3x6",
        "type": "broadcast",
        "status": "queued",
        "mode": "live",
        "sender": "Amarseba",
        "is_masking": false,
        "recipient_count": 2,
        "total_parts": 2,
        "total_cost": "0.60",
        "balance_after": "99.40",
        "messages": [
            {
                "message_id": "msg_01j8z3k6qa4b8c2d6e0f3g7h1j",
                "to": "8801712345678",
                "encoding": "gsm7",
                "parts": 1,
                "cost": "0.30",
                "status": "queued"
            },
            {
                "message_id": "msg_01j8z3k6qb5c9d3e7f1g4h8j2k",
                "to": "8801812345678",
                "encoding": "gsm7",
                "parts": 1,
                "cost": "0.30",
                "status": "queued"
            }
        ]
    },
    "code": 202,
    "timestamp": "2026-09-26T10:00:00.000000Z"
}
Error response
402application/json
{
    "success": false,
    "message": "Your wallet balance is too low for this request",
    "data": {
        "required": "0.60",
        "available": "0.20",
        "shortfall": "0.40",
        "currency": "BDT"
    },
    "errors": {
        "balance": [
            "This request costs 0.60 BDT but your wallet balance is 0.20 BDT"
        ]
    },
    "code": 402,
    "error_code": "insufficient_balance",
    "timestamp": "2026-09-26T10:00:00.000000Z"
}
POST /bulk-sms/send-many Scope: bulk-sms:send

Send a different body to each number in one request.

Parameters
Name Type Required Description
messages object[] Yes Up to 10,000 items.
messages.*.to string Yes The recipient number.
messages.*.body string Yes The SMS text for this recipient, up to 10 parts.
from string No An approved masking name, used for every message.
Request
curl -X POST https://e-amarseba.com/api/v1/bulk-sms/send-many \
  -H "Authorization: Bearer $AMARSEBA_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "messages": [
        {
            "to": "01712345678",
            "body": "Hi Rahim, your order #1042 has shipped."
        },
        {
            "to": "01812345678",
            "body": "Hi Karim, your order #1043 has shipped."
        }
    ]
}'
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;

$response = Http::withToken(config('services.amarseba.key'))
    ->acceptJson()
    ->withHeaders(['Idempotency-Key' => (string) Str::uuid()])
    ->post('https://e-amarseba.com/api/v1/bulk-sms/send-many', [
        'messages' => [
            [
                'to' => '01712345678',
                'body' => 'Hi Rahim, your order #1042 has shipped.',
            ],
            [
                'to' => '01812345678',
                'body' => 'Hi Karim, your order #1043 has shipped.',
            ],
        ],
    ]);

$result = $response->json();
const response = await fetch("https://e-amarseba.com/api/v1/bulk-sms/send-many", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.AMARSEBA_API_KEY}`,
    Accept: "application/json",
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
      "messages": [
          {
              "to": "01712345678",
              "body": "Hi Rahim, your order #1042 has shipped."
          },
          {
              "to": "01812345678",
              "body": "Hi Karim, your order #1043 has shipped."
          }
      ]
  }),
});

const result = await response.json();
import os
import uuid

import requests

response = requests.post(
    "https://e-amarseba.com/api/v1/bulk-sms/send-many",
    headers={
        "Authorization": f"Bearer {os.environ['AMARSEBA_API_KEY']}",
        "Accept": "application/json",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "messages": [
            {
                "to": "01712345678",
                "body": "Hi Rahim, your order #1042 has shipped.",
            },
            {
                "to": "01812345678",
                "body": "Hi Karim, your order #1043 has shipped.",
            },
        ],
    },
)

result = response.json()
Error response
422application/json
{
    "success": false,
    "message": "Recipient #2 is not a valid Bangladeshi mobile number",
    "data": null,
    "errors": {
        "messages.1.to": [
            "Recipient #2 is not a valid Bangladeshi mobile number"
        ]
    },
    "code": 422,
    "error_code": "validation_error",
    "timestamp": "2026-09-26T10:00:00.000000Z"
}
POST /bulk-sms/groups/{group_id}/send Scope: bulk-sms:send

Send one body to every active contact in a group. An inactive group returns 422 under group_id with "The group is not active", and a group without active contacts returns "The group has no active contacts".

Parameters
Name Type Required Description
group_id path Yes The group ID, for example grp_01j8….
body string Yes The SMS text, up to 10 parts.
from string No An approved masking name. Omit for the default sender.
Request
curl -g -X POST https://e-amarseba.com/api/v1/bulk-sms/groups/{group_id}/send \
  -H "Authorization: Bearer $AMARSEBA_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "body": "Your OTP is 4821. It expires in 5 minutes."
}'
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;

$response = Http::withToken(config('services.amarseba.key'))
    ->acceptJson()
    ->withHeaders(['Idempotency-Key' => (string) Str::uuid()])
    ->post('https://e-amarseba.com/api/v1/bulk-sms/groups/{group_id}/send', [
        'body' => 'Your OTP is 4821. It expires in 5 minutes.',
    ]);

$result = $response->json();
const response = await fetch("https://e-amarseba.com/api/v1/bulk-sms/groups/{group_id}/send", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.AMARSEBA_API_KEY}`,
    Accept: "application/json",
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
      "body": "Your OTP is 4821. It expires in 5 minutes."
  }),
});

const result = await response.json();
import os
import uuid

import requests

response = requests.post(
    "https://e-amarseba.com/api/v1/bulk-sms/groups/{group_id}/send",
    headers={
        "Authorization": f"Bearer {os.environ['AMARSEBA_API_KEY']}",
        "Accept": "application/json",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "body": "Your OTP is 4821. It expires in 5 minutes.",
    },
)

result = response.json()
Error response
422application/json
{
    "success": false,
    "message": "The group is not active",
    "data": null,
    "errors": {
        "group_id": [
            "The group is not active"
        ]
    },
    "code": 422,
    "error_code": "validation_error",
    "timestamp": "2026-09-26T10:00:00.000000Z"
}