Bulk SMS API-Referenz

Die BulkSMSOnline REST API sendet Textnachrichten an 227 Länder von Ihrer eigenen Software aus, mit den gleichen Preisen, Segmentregeln, Zeitplanung und Rückerstattungen wie die Konsole. Anfragen und Antworten sind JSON über HTTPS, und jeder endgültige Zustellstatus kann als signierter Webhook an Ihren Server gepusht werden.

Basis-URLhttps://bulksmsonline.cc/api/v1

Überblick

Nutzen Sie die API, wenn Nachrichten durch Ihre eigenen Systeme ausgelöst werden: Bestellbestätigungen aus einem Shop, Codes aus einem Login-Formular, Erinnerungen von einem Buchungstool. Eine Anfrage an POST /v1/messages mit bis zu 10,000 Nummern erstellt eine Kampagne, belastet Ihr Guthaben und reiht jede Nachricht in die Warteschlange ein. Über die API erstellte Kampagnen erscheinen ebenfalls in der Konsole mit ihren Zustellberichten.

  • Alle Beträge sind in US-Dollar als Zeichenketten mit fünf Dezimalstellen angegeben, zum Beispiel "0.00534".
  • Telefonnummern sind international, mit oder ohne führendes +; Leerzeichen und Bindestriche werden entfernt.
  • Zeiten sind im ISO-8601-Format in UTC, zum Beispiel 2026-12-01T09:00:00Z.
  • Nachrichten- und Kampagnen-IDs sehen aus wie MSG-XXXX-XXXX-XXXX und CMP-XXXX-XXXX-XXXX.

Authentifizierung

Erstellen Sie einen API-Schlüssel unter API in der Konsole (Schlüssel werden nach Ihrer ersten Aufladung freigeschaltet). Senden Sie ihn im Authorization-Header jeder Anfrage. Ein Schlüssel sieht aus wie bso_api_ gefolgt von 36 Zeichen; er wird nur einmal angezeigt, speichern Sie ihn also als Geheimnis auf Ihrem Server. Das Erstellen eines neuen Schlüssels ersetzt den vorherigen sofort.

Authorization: Bearer bso_api_0123456789abcdef0123456789abcdef0123
Content-Type: application/json

Grenzwerte

Anfragen300 pro Minute pro Schlüssel; mehr Anfragen erhalten die Antwort 429 rate_limited
Nummern pro Anfrage10,000
Nachrichtentext2,000 Zeichen wie geschrieben, bis zu 10 Segmenten
Zeitplanungsend_at von 5 Minuten bis 60 Tage im Voraus
Sendetempo400 Nachrichten pro Minute pro Warteschlange
Webhook-Wiederholungsversuche9 Versuche über etwa 22 Stunden

Nachrichten senden

POST/v1/messages

Sendet einen Text an eine oder mehrere Nummern. Die gesamten Kosten werden bei Annahme der Anfrage vom Guthaben abgebucht; jede nicht zustellbare Nachricht wird später erstattet. Die Antwort hat den Status 201 und enthält die Kampagne mit jeder Nachricht.

FeldBeschreibung
toerforderlichEine Nummer oder ein Array von bis zu 10,000 Nummern im internationalen Format. Wiederholte Nummern werden einmal gesendet; unlesbare werden in skipped aufgeführt.
texterforderlichDie Nachricht, bis zu 2,000 Zeichen und 10 Segmenten. GSM-7-Text hat 160 Zeichen pro SMS, Unicode 70.
send_atoptionalISO-8601-Zeit zum Planen des Versands, 5 Minuten bis 60 Tage im Voraus. Lassen Sie es weg, um sofort zu senden.
opt_outoptionaltrue fügt Ihre Abmeldezeile aus den Konsoleneinstellungen in einer neuen Zeile am Ende hinzu.
client_refoptionalIhre eigene Referenz, bis zu 64 Buchstaben, Ziffern und _ . : -. Sie wird in Berichten und Webhooks zurückgegeben.
curl -X POST https://bulksmsonline.cc/api/v1/messages \
  -H "Authorization: Bearer $BSO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to":["+447700900412","+33612345678"],"text":"Order 4521 has shipped. Track it at shop.example/t/4521","client_ref":"order-4521"}'
HTTP/1.1 201 Created
{
  "id": "CMP-7KQ2-M9XA-4HTD",
  "status": "sending",
  "channel": "api",
  "recipients": 2,
  "segments": 1,
  "encoding": "GSM-7",
  "cost": "0.02158",
  "refunded": "0.00000",
  "client_ref": "order-4521",
  "send_at": null,
  "counts": { "queued": 2, "submitted": 0, "delivered": 0, "failed": 0, "canceled": 0 },
  "skipped": [],
  "balance": "118.43120",
  "messages": [
    { "id": "MSG-3RTW-81KD-ZQ0P", "to": "+447700900412", "country": "GB", "segments": 1, "price": "0.00834", "status": "queued" },
    { "id": "MSG-5HNA-4C2E-7YVB", "to": "+33612345678", "country": "FR", "segments": 1, "price": "0.01324", "status": "queued" }
  ]
}

Sendung kalkulieren

POST/v1/quote

Nimmt denselben Body wie /v1/messages und gibt die genauen Kosten, Segmente und Kodierung zurück, ohne etwas zu senden oder zu berechnen. Verwenden Sie es, um Ihren Benutzern einen Preis anzuzeigen, bevor sie bestätigen.

{
  "recipients": 2,
  "skipped": [],
  "segments": 1,
  "encoding": "GSM-7",
  "cost": "0.02158",
  "balance": "118.45278",
  "countries": [ { "country": "GB", "recipients": 1, "cost": "0.00834" }, { "country": "FR", "recipients": 1, "cost": "0.01324" } ]
}

Guthaben

GET/v1/balance

{ "balance": "118.43120", "currency": "USD" }

Preise

GET/v1/rates

GET/v1/rates/{country}

Der Preis eines SMS-Segments für jedes Ziel oder für einen zweistelligen ISO-Ländercode. Diese beiden Endpunkte sind öffentlich und benötigen keinen Schlüssel.

{ "country": "DE", "name": "Germany", "calling_code": "+49", "price": "0.01544", "currency": "USD", "per": "segment" }

Nachrichtenstatus

GET/v1/messages/{id}

{
  "id": "MSG-3RTW-81KD-ZQ0P",
  "campaign_id": "CMP-7KQ2-M9XA-4HTD",
  "to": "+447700900412",
  "country": "GB",
  "segments": 1,
  "price": "0.00834",
  "status": "delivered",
  "error": null,
  "created_at": "2026-11-07T09:00:02Z",
  "submitted_at": "2026-11-07T09:00:03Z",
  "final_at": "2026-11-07T09:00:08Z"
}

Kampagnen

GET/v1/campaigns/{id}

GET/v1/campaigns/{id}/messages?offset=0&limit=100

Der erste gibt die Kampagne mit ihren Zählungen pro Status zurück; der zweite blättert durch ihre Nachrichten, bis zu 1.000 pro Seite. Von der Konsole gesendete Kampagnen können auf dieselbe Weise mit der auf ihrer Seite angezeigten ID gelesen werden.

Geplante Sendung stornieren

POST/v1/campaigns/{id}/cancel

Stoppt eine Kampagne, die mit send_at erstellt wurde und noch nicht begonnen hat. Jede Nachricht wird abgebrochen und die gesamten Kosten werden dem Guthaben gutgeschrieben. Eine bereits sendende Kampagne antwortet mit 409 not_scheduled.

Zustell-Webhooks

Fügen Sie unter API in der Konsole eine HTTPS-URL hinzu, um jeden endgültigen Status (delivered oder failed) als POST-Anfrage zu erhalten. Antworten Sie innerhalb von 8 Sekunden mit einem 2xx-Status. Andere Antworten und Timeouts werden nach 20 Sekunden, 1, 5 und 15 Minuten, dann 1, 3, 6 und 12 Stunden erneut versucht, insgesamt 9 Versuche. Dasselbe Ereignis kann zweimal eintreffen, verwenden Sie daher event_id, um es einmal zu verarbeiten.

POST https://your-server.example/sms-status
Content-Type: application/json
X-BulkSMSOnline-Signature: t=1794042008,v1=5f0c2a...e91b

{
  "type": "message.status",
  "event_id": "ev_8f1c22d0a4b97e63c1f0",
  "sent_at": "2026-11-07T09:00:09Z",
  "data": {
    "message_id": "MSG-3RTW-81KD-ZQ0P",
    "campaign_id": "CMP-7KQ2-M9XA-4HTD",
    "to": "+447700900412",
    "country": "GB",
    "status": "delivered",
    "error": null,
    "segments": 1,
    "price": "0.00834",
    "currency": "USD",
    "client_ref": "order-4521",
    "final_at": "2026-11-07T09:00:08Z"
  }
}

Signatur überprüfen

Der Header enthält die Unix-Zeit t und die Signatur v1 = HMAC-SHA256 der Zeichenkette "t.raw_body" mit Ihrem Webhook-Geheimnis, in hex. Berechnen Sie sie über den Rohbody vor dem Parsen des JSON, vergleichen Sie in konstanter Zeit und lehnen Sie Ereignisse ab, die älter als fünf Minuten sind.

import crypto from "node:crypto";

export function verify(rawBody, header, secret) {
  const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header || "");
  if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;
  const want = crypto.createHmac("sha256", secret).update(m[1] + "." + rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(want), Buffer.from(m[2]));
}

Status

queuedAkzeptiert und wartet auf Verlassen der Warteschlange
submittedAn das Zielnetz übergeben
deliveredVom Handgerät bestätigt (endgültig)
failedKonnte nicht zugestellt werden; der Preis wird erstattet (endgültig)
canceledTeil einer geplanten Kampagne, die vor dem Senden abgebrochen wurde (endgültig)

Kampagnenstatus ist scheduled, sending, complete oder canceled.

Fehler

Fehler antworten mit einem HTTP-Status und einem JSON-Body: { "error": { "code": "insufficient_balance", "message": "..." } }. Nichts wird berechnet, wenn eine Anfrage mit einem Fehler antwortet.

HTTPCodeBedeutung
400invalid_requestEin Feld fehlt oder ist ungültig; die Nachricht sagt, welches.
400invalid_jsonDer Body ist kein JSON.
400no_valid_numbersKeine der Nummern konnte gelesen werden.
401unauthorizedDer Schlüssel fehlt, ist fehlerhaft oder wurde ersetzt.
402insufficient_balanceDas Guthaben deckt die Kosten nicht; laden Sie auf und senden Sie erneut.
404not_foundUnbekannte ID oder Endpunkt.
409not_scheduledNur eine geplante Kampagne, die noch nicht gestartet wurde, kann abgebrochen werden.
413too_many_recipientsMehr als 10,000 Nummern in einer Anfrage.
429rate_limitedMehr als 300 Anfragen in einer Minute.
500server_errorWiederholen Sie die Anfrage; es wurde nichts belastet.

Holen Sie sich einen API-Schlüssel in der Konsole

Erstellen Sie ein Konto, fügen Sie Ihre erste Aufladung hinzu und generieren Sie einen Schlüssel unter API. Ihre erste Anfrage kann eine Minute später versendet werden.

Konto erstellen
Bulk SMS API-Referenz: REST-Endpunkte und Webhooks | BulkSMSOnline