SMS API-Dokumentation zum Versenden aus Ihrem eigenen Code

Eine kleine REST-API auf demselben Konto, mit denselben Preisen und demselben Guthaben wie der Arbeitsbereich: Senden Sie eine Nachricht oder einen Stapel von bis zu 5,000 Nummern, schätzen Sie zuerst die Kosten, verfolgen Sie jede Nachricht und erhalten Sie Lieferereignisse an Ihrer Webhook-URL.

Basis-URL: https://sendsmsonline.cc/api/v1

Schnellstart

  1. 1. Schlüssel erstellen. Im Arbeitsbereich API und Webhooks öffnen. Schlüssel werden nach Ihrer ersten Guthabenaufladung freigeschaltet; jeder Schlüssel wird einmal angezeigt, kopieren Sie ihn also oder speichern Sie ihn als Textdatei.
  2. 2. Kosten prüfen. Senden Sie denselben Body als POST an /costs, um Empfänger, Segmente und den Gesamtbetrag ohne Versand zu sehen.
  3. 3. Senden. Senden Sie es als POST an /sends. Die Antwort enthält die Sendungs-ID; Nachrichten werden sofort oder zum Zeitpunkt send_at versendet.
curl https://sendsmsonline.cc/api/v1/sends \
  -H "Authorization: Bearer $SSO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "recipients": [ { "to": "+447700900461", "fields": { "first_name": "Tom" } }, { "to": "+12015550142", "fields": { "first_name": "Ava" } } ], "text": "Hi {{first_name}}, your table is ready at 7:30.", "name": "Friday bookings", "client_ref": "bookings-1107" }'

Authentifizierung

Senden Sie Ihren Schlüssel im Authorization-Header: Authorization: Bearer sso_live_.... Schlüssel sind 49 Zeichen lang und beginnen mit sso_live_. Bis zu 5 Schlüssel pro Konto; widerrufen Sie einen im Arbeitsbereich und er funktioniert sofort nicht mehr. Die Preisliste ist öffentlich und benötigt keinen Schlüssel.

Fehler

Fehler verwenden HTTP-Statuscodes und einen JSON-Body mit einem stabilen Code und einem Satz, den Sie einer Person zeigen können. Es wird nichts berechnet, wenn eine Anfrage fehlschlägt.

HTTP/1.1 402 Payment Required
{ "error": { "code": "insufficient_credit", "message": "Short by $3.20. Add funds to send.", "total": "8.62480", "credit": "5.42000" } }
FeldBedeutung
400Die Anfrage muss geändert werden.
401Fehlender, falscher oder widerrufener Schlüssel.
402Nicht genug Guthaben für den Gesamtbetrag.
404Keine solche Sendung, Nachricht, Land oder Endpunkt.
409Der Versand wurde bereits gestartet.
429Mehr als 240 Anfragen pro Minute.

Limits

  • 240 Anfragen pro Minute pro Schlüssel, angezeigt in X-RateLimit-Limit, X-RateLimit-Remaining und X-RateLimit-Reset (Unix-Sekunden).
  • 5,000 Nummern pro Anfrage, 2,000 Zeichen pro Text, 10 Segmente pro Nachricht.
  • Nachrichten werden mit bis zu 300 pro Minute pro Konto versendet.
  • send_at von 10 Minuten bis 30 Tage im Voraus.

Preise

GET/api/v1/prices

GET/api/v1/prices/{country}

Der Preis pro Nachricht (ein Segment) für jedes Land, in USD mit 5 Dezimalstellen. Kein Schlüssel erforderlich.

{ "price": { "country": "GB", "name": "United Kingdom", "dial_code": "+44", "price_usd": "0.00868" }, "updated": "2026-11-07" }

Kontoguthaben

GET/api/v1/account

{ "account": "SO8K2M4Q7X9TBA", "credit_usd": "41.27660", "currency": "USD" }

Kosten schätzen

POST/api/v1/costs

Nimmt denselben Körper wie ein Versand und gibt die Kosten zurück, ohne zu senden oder zu berechnen. Der zusammengeführte Text jedes Empfängers bestimmt seine Segmente, sodass die Summe exakt ist.

{
  "recipients": 2, "segments_min": 1, "segments_max": 1, "encoding": "gsm7", "messages_billed": 2,
  "total_usd": "0.01426", "credit_usd": "41.27660", "enough_credit": true,
  "countries": [ { "country": "GB", "recipients": 1, "price_usd": "0.00868", "subtotal_usd": "0.00868" },
                 { "country": "US", "recipients": 1, "price_usd": "0.00558", "subtotal_usd": "0.00558" } ],
  "dropped": [], "too_long": null
}

Sendung erstellen

POST/api/v1/sends

Ein Text an eine oder mehrere Nummern. Das Guthaben für den gesamten Versand wird abgebucht, wenn er akzeptiert wird; fehlgeschlagene Nachrichten werden einzeln erstattet.

FeldBedeutung
toNummern im internationalen Format (+447700900461). Verwenden Sie dies oder Empfänger.
recipientsObjekte mit to und fields, für Zusammenführungsfelder: { "to": "+1...", "fields": { "first_name": "Ava" } }.
textDie Nachricht, bis zu 2,000 Zeichen. {{field}} wird pro Empfänger ersetzt; fehlende Werte werden leer.
send_atOptionale ISO 8601 Zeit mit Offset oder Z. Ohne sie beginnt der Versand sofort.
nameOptionales Label, das im Arbeitsbereich angezeigt wird (80 Zeichen).
client_refOptionaler Verweis, der in Webhooks zurückgegeben wird (64 Zeichen).
opt_outFügt die in den Einstellungen gespeicherte Opt-Out-Zeile am Ende des Textes hinzu.
default_countryISO-Code für Nummern, die ohne Landescode geschrieben sind.
HTTP/1.1 201 Created
{
  "send": { "id": "CA7Q29XMAB4DFK", "status": "queued", "source": "api", "recipients": 2, "segments_max": 1,
            "encoding": "gsm7", "cost_usd": "0.01426", "refunded_usd": "0.00000", "client_ref": "bookings-1107",
            "send_at": null, "created_at": "2026-11-07T10:12:03.120Z", "started_at": null, "finished_at": null },
  "dropped": [ { "value": "+4412", "code": "too_short", "message": "Too short" } ]
}

Nummern, die nicht gesendet werden können, sind in dropped aufgeführt und werden nie berechnet. Codes: no_country_code, too_short, too_long, not_a_number, wrong_length, not_covered, duplicate und suppressed (auf Ihrer Nicht-Senden-Liste).

Sendungen abrufen oder auflisten

GET/api/v1/sends/{id}

GET/api/v1/sends?limit=25&before={id}

Ein einzelner Versand enthält counts pro Nachrichtenstatus. Listen sind nach Neuheit sortiert; übergeben Sie next_before als before für die nächste Seite. Versand aus dem Arbeitsbereich erscheint hier ebenfalls, mit source: "web".

Nachrichten

GET/api/v1/sends/{id}/messages?status=failed&limit=100

GET/api/v1/messages/{id}

{ "message": { "id": "MS3D8RW0K2QJ7N", "send_id": "CA7Q29XMAB4DFK", "to": "+447700900461", "country": "GB",
  "segments": 1, "price_usd": "0.00868", "status": "delivered", "reason": null, "reason_text": null,
  "created_at": "2026-11-07T10:12:03.120Z", "sent_at": "2026-11-07T10:12:04.010Z", "done_at": "2026-11-07T10:12:09.400Z" } }

Sendung stornieren

POST/api/v1/sends/{id}/cancel

Nur geplante Versand, die noch nicht gestartet sind, können storniert werden. Die vollen Kosten werden Ihrem Guthaben gutgeschrieben und die Antwort enthält refunded_usd.

Webhooks

Setzen Sie eine HTTPS-URL im Arbeitsbereich (API und Webhooks). Wir POSTen ein Ereignis, wenn eine Nachricht zugestellt wird oder fehlschlägt, für Versand sowohl über die API als auch den Arbeitsbereich. Antworten Sie mit einem beliebigen 2xx-Status innerhalb von 10 Sekunden. Fehlgeschlagene Zustellungen werden insgesamt bis zu 7 Mal erneut versucht: sofort, dann nach 1 Minute, 5 Minuten, 30 Minuten, 1 Stunde, 2 Stunden und 3 Stunden. Der Arbeitsbereich zeigt jeden Versuch mit seinem Status und der Antwort an.

POST https://your-server.example/sms-events
X-SSO-Event: message.delivered
X-SSO-Delivery: evt_5a0c9e31d2b7f4a68c
X-SSO-Timestamp: 1794132729
X-SSO-Signature: sha256=8f1c...e42a

{ "id": "evt_5a0c9e31d2b7f4a68c", "event": "message.delivered", "created": "2026-11-07T10:12:09.000Z",
  "data": { "message": { "id": "MS3D8RW0K2QJ7N", "send_id": "CA7Q29XMAB4DFK", "to": "+447700900461", "country": "GB",
  "segments": 1, "price_usd": "0.00868", "status": "delivered", "reason": null, "reason_text": null,
  "client_ref": "bookings-1107", "created_at": "...", "sent_at": "...", "done_at": "..." } } }

Die Signatur ist HMAC-SHA256 von timestamp + "." + raw body mit Ihrem Signaturgeheimnis (es beginnt mit sso_whk_). Überprüfen Sie es am Rohkörper vor dem Parsen, lehnen Sie Zeitstempel ab, die älter als 5 Minuten sind, und verwenden Sie die Liefer-ID, um Wiederholungen zu ignorieren.

import crypto from "node:crypto";

// rawBody: the request body exactly as received (a string), before JSON.parse
export function verify(rawBody, headers, secret) {
  const ts = headers["x-sso-timestamp"];
  const sig = headers["x-sso-signature"] || "";
  const want = "sha256=" + crypto.createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
  return fresh && sig.length === want.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(want));
}

Ereignisse: message.delivered, message.failed und test von der Schaltfläche Testereignis senden.

Status und Gründe

FeldBedeutung
queuedWarten darauf, unsere Warteschlange zu verlassen.
sentAn das Netzwerk übergeben, warte auf den Zustellbericht. Die meisten Berichte kommen innerhalb von Minuten an; einige Netzwerke benötigen bis zu 24 Stunden.
deliveredDas Netzwerk hat bestätigt, dass das Telefon die Nachricht erhalten hat.
failedNicht zugestellt. Der Betrag wurde auf Ihr Guthaben zurückerstattet.
canceledNicht gesendet, da Sie den Vorgang abgebrochen haben. Rückerstattet.

Fehlergründe (das Feld reason):

FeldBedeutung
network_errorNetzwerkfehler
absentTelefon ausgeschaltet oder außerhalb des Empfangsbereichs
not_in_serviceNummer nicht in Betrieb
blockedVom Netzwerk oder Empfänger blockiert
landlineFestnetz oder Nummer, die keine SMS empfangen kann
content_filterVom Inhaltsfilter des Netzwerks abgelehnt
expiredAbgelaufen: Kein Bericht vor der Zeitbegrenzung des Netzwerks
canceledVor dem Senden abgebrochen
unknownUnbekannte Netzwerkantwort

Serviceprüfungen finden Sie auf der Statusseite und API-Änderungen im Changelog.

Holen Sie sich Ihren API-Schlüssel

Erstellen Sie ein Konto, laden Sie einmal Guthaben auf und aktivieren Sie API und Webhooks im Arbeitsbereich. Derselbe Schlüssel funktioniert für jedes Land.

Kostenloses Konto erstellen
SMS API-Dokumentation: Senden Sie Massen-SMS aus Ihrem Code | SendSMSOnline