Skip to content

Learn

Quickstart

Send your first SMS in about five minutes. Every step below is a real request against the production API.

1

Get an API key

Create a key in the customer console, under API keys. Copy the full value the moment it is shown — only a hash is stored, so it cannot be retrieved again. Keep it in an environment variable, never in source control.

export SMSEND_API_KEY="sk_live_a1b2c3d4.your_secret_here"
2

Find a sender you may use

The sender is the name or number that appears on the recipient's handset. It must be approved by SMSend and registered with at least one operator before it can carry traffic.

curl https://api.smsend.net/public/v1/sender-ids \
  -H "Authorization: Bearer $SMSEND_API_KEY"

Filter on is_sendable, not on status. A sender that is approved but not yet registered with an operator reads as APPROVED and still cannot send — every message would fail after exhausting its retry budget.

3

Submit a batch

One request sends to one or many recipients. The Idempotency-Key header is required: it is what makes a retried request safe, so a network timeout cannot bill you twice.

curl -X POST https://api.smsend.net/public/v1/batches \
  -H "Authorization: Bearer $SMSEND_API_KEY" \
  -H "Idempotency-Key: quickstart-001" \
  -H "Content-Type: application/json" \
  -d '{
    "sender": "PRESTIGE",
    "body": "Hello from SMSend.",
    "message_class": "TRANSACTIONAL",
    "recipients": [{ "msisdn": "+22670000001" }]
  }'
<?php

$response = Http::withToken(getenv('SMSEND_API_KEY'))
    ->withHeaders(['Idempotency-Key' => 'quickstart-001'])
    ->post('https://api.smsend.net/public/v1/batches', [
        'sender' => 'PRESTIGE',
        'body' => 'Hello from SMSend.',
        'message_class' => 'TRANSACTIONAL',
        'recipients' => [['msisdn' => '+22670000001']],
    ]);

echo $response->json('data.batch_id');
const response = await fetch('https://api.smsend.net/public/v1/batches', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SMSEND_API_KEY}`,
    'Idempotency-Key': 'quickstart-001',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    sender: 'PRESTIGE',
    body: 'Hello from SMSend.',
    message_class: 'TRANSACTIONAL',
    recipients: [{ msisdn: '+22670000001' }],
  }),
})

const { data } = await response.json()
console.log(data.batch_id)
import os
import requests

response = requests.post(
    "https://api.smsend.net/public/v1/batches",
    headers={
        "Authorization": f"Bearer {os.environ['SMSEND_API_KEY']}",
        "Idempotency-Key": "quickstart-001",
    },
    json={
        "sender": "PRESTIGE",
        "body": "Hello from SMSend.",
        "message_class": "TRANSACTIONAL",
        "recipients": [{"msisdn": "+22670000001"}],
    },
)

print(response.json()["data"]["batch_id"])

A successful submission returns 202 Accepted. The batch has been accepted and paid for; the messages have not been delivered yet.

{
  "data": {
    "batch_id": "01K3F7XQZ8V2N4M6P8R0T5CJWE",
    "status": "QUEUED",
    "accepted": 1,
    "rejected": 0,
    "rejections": [],
    "reserved_amount": 25,
    "currency": "XOF",
    "total_segments": 1
  }
}
4

Check what happened

Fetch the batch to see how far it has got. The counts update as messages move through the system.

curl https://api.smsend.net/public/v1/batches/01K3F7XQZ8V2N4M6P8R0T5CJWE \
  -H "Authorization: Bearer $SMSEND_API_KEY"

The counts object holds monotonic counters — how many messages have ever reached each state, not how many are sitting in it right now. They only ever increase.

5

Receive delivery reports

Polling is fine for a first integration, but it does not scale. Register a webhook endpoint to have SMSend push each terminal outcome to your server as it happens, and keep the messages feed as your recovery path for when your endpoint is down.