SMS
SMS weltweit über Orbits SMPP-Gateway senden. Orbit verbindet sich mit Tier-1-Carriern und Aggregatoren in über 190 Ländern und übernimmt Konkatenation, Kodierung und Zustellverfolgung automatisch. Diese Seite führt Sie durch den Kanal von Anfang bis Ende: welchen Absender Sie anbinden, wo Registrierung vor dem Verkehr erforderlich ist, wie die Kodierung die Kosten pro Sendung bestimmt, was der Status-Lifecycle Ihnen sagt und wie Sie Fehler lesen, wenn sie zurückkommen.Ein SMS senden
to als auch from werden als E.164 validiert — vollständiges internationales Format mit Länder-Präfix, wie +14155552671. Wie Orbit Nummern validiert und normalisiert, steht im Nummern-Lifecycle.
Verwenden Sie während des Prototypings einen Sandbox-Schlüssel (dv_test_sk_… über curl, ORBIT_API_KEY im Code) — Sandbox-Sendungen sind simuliert, kostenlos und erreichen nie einen Carrier. Beim Wechsel zur Produktion tauschen Sie den Live-Schlüssel ein; kein Code oben ändert sich.
Der Node-Tab oben verwendet den generischen orbit.messages.send({ channel: 'sms', ... })-Helper; die typed Per-Channel-Methode orbit.messages.sendSms({ to, body, from }) macht denselben POST — wählen Sie eine Form und bleiben Sie konsistent.
Antwort
Endpunkt antwortet mit HTTP 202 Accepted — die Nachricht ist persisted und zur Zustellung in Warteschlange (noch nicht an Carrier übergeben). Dieid ist eine Plattform-Nachricht-ID der Form msg_ gefolgt von 32 kleingeschriebenen Hex-Zeichen (kein Kanal-Infix); ihren Lifecycle über Zustell-Webhooks verfolgen.
data.id lesen, um später zu pollen oder abzugleichen, und auf data.status verzweigen (beginnt bei queued):
- Node.js / fetch (TypeScript) — SDK- oder
res.json()-Rückgabewert trägt den Umschlag:message.data.id,message.data.status. - Python —
send_smsgibt den rohen JSON-Body als dict zurück:message["data"]["id"],message["data"]["status"]. - Go —
SendSMSunmarshal den Umschlag in ein typed struct:msg.Data.ID,msg.Data.Status. - Ruby / PHP (Escape-Hatch) —
client.requestgibt den rohen JSON-Body zurück:send.dig("data", "id")/$send['data']['id'].
segments und encoding bei jedem Senden lesen — das ist, was die Abrechnung belastet, und Abschnitt Kodierung & Konkatenation unten zeigt, wie Sie beides vor dem Senden vorhersagen.
Häufige Muster
Zwei Muster decken nahezu jede SMS-Produktionsintegration ab: sichere Retries beim Senden und Nachrichten-Historie paginieren.Idempotent senden mit Idempotency-Key
POST-Endpunkte, die Ressourcen erstellen, akzeptieren einenIdempotency-Key-Header. Ein Retry mit demselben Schlüssel gibt den ursprünglichen Umschlag zurück — kein Doppel-Senden, keine zweite Belastung. Die SDKs mintieren einen UUID pro Aufruf automatisch; über rohen HTTP setzen Sie ihn explizit. In beiden Fällen übergeben sie einen stabilen Schlüssel über die Versuche eines logischen Sendens statt jedem Retry seinen eigenen zu mintieren.
Node
Python
GET /messages über SDK-Listenaufrufe paginieren
Nachrichten-Historie ist cursor-paginiert: jede Seite trägtmeta.pagination.cursor und meta.pagination.has_more; den Cursor zurückgeben, bis has_more false ist. Das Node-SDK liefert eine Cursor-Schleife und einen auto-paginierenden Iterator; die anderen SDKs paginieren über ihre Listen-Methoden oder die Escape-Hatch:
Node
Python
Abgearbeitetes Beispiel: senden, pollen und Fehler handhaben
Die Sequenz unten ist die gleiche Ende-zu-Ende: POST die Sendung, pollGET /messages/{id} (oder nehme den webhook — Polling ist der Fallback) und verzweige deterministisch, wenn etwas fehlschlägt. Der Body ist absichtlich ein UCS-2-Senden, damit Sie das Kodierungsverdikt zurückkommen sehen statt GSM-7-Preis zu vermuten.
1. Nachricht senden
from, sender_pool_id, messaging_service_id oder from_extension — sonst gibt der Endpunkt HTTP 422 mit SENDER_REQUIRED (z.B. wenn ein Past wie "from": null in Ihre Anfrage rutscht). Was jeder Selektor bedeutet, siehe Absendertyp wählen.
2. Send-Antwort lesen
status: queued ist der Startzustand — noch nichts zugestellt, und kein external_id (Carrier-Referenz) ist zurückgegeben. segments- und encoding-Felder sind genau das, wogegen Segment-Preisung multipliziert; behandeln Sie sie als die Rechnung, nicht als Hinweis.
3. Zeile pollen
Wenn Sie Webhooks nicht (oder nicht wollen) abonnieren, pollen SieGET /messages/{id} auf der id, die das Senden zurückgab. Die Zeile rückt durch sending → sent → delivered / einen Terminal-Fehler vor. Jede Antwort trägt auch metadata.classified_error_code für Terminal-Fehler und metadata.no_dlr_channel für Meta-DM-Zeilen, also verzweigen Sie auf den maschinenlesbaren status, nie auf Beschriftungsstrings.
sending (Provider hat sie gepackt) oder sent (Provider akzeptierte sie) vor delivered. ?include=webhook_deliveries hinzufügen, wenn Sie die Fan-Out-Historie in einer Rundreise wollen.
4. Auf Fehler verzweigen
Verzweigen Sie auf die Poll-status, die Webhook-data.status oder metadata.classified_error_code — alle erzählen dieselbe Geschichte. Die Fehlerfamilien unten sind die, die Sie realistisch handhaben müssen:
Auf jedem
message.failed-Webhook ist data.status das Verzweigungsfeld — submitted_no_receipt und expired reiten auf diesem Event, und ein späterer message.delivered-Webhook kann noch nach einem davon ankommen.
SMS-Deliverability-Grundlagen
SMS-Deliverability beruht auf drei Dingen, in dieser Reihenfolge: von wem Sie senden, wo, und wie schnell. Das richtig einstellen, und Kodierung wird die einzige Kostenvariable, die bleibt.Absendertyp wählen
Absender existieren aus einem Grund jeweils: Deliverability. Sie brauchen eine Absender-ID, die für die Regeln des Ziellandes genehmigt ist, oder der Carrier filtert den Verkehr, bevor er Ihnen ein Segment kostet — siehe Ländervors-Compliance.
Onboarding über das Dashboard
Der Dashboard-Walkaround dauert weniger als fünf Minuten und fängt die beiden Fehlermodi unten, bevor Sie eine Code-Zeile schreiben.- Öffnen Sie Channels → SMS im Dashboard.
- Klicken Sie Attach Sender und wählen Sie einen Absendertyp oben. Orbit validiert das Format (E.164-Nummer, 3–11-stellige alphanumerische ID oder Pool-Referenz) und prüft, ob die als Default gewählte Destination Registrierung erfordert.
- Senden Sie eine Testnachricht an eine Nummer, die Sie besitzen. Der Komposer zeigt
segmentsundencodinginline, also sehen Sie die geschätzten Pro-Segment-Kosten vor dem Senden. - Wenn Ihr Ziel-Gate die Anbindung ablehnt (US ohne 10DLC-Kampagne, gated Land ohne Absender-ID-Genehmigung), routet der Assistent Sie zum Registrierungsfluss — siehe die nächsten zwei Abschnitte.
GET /api/v1/messaging/senders über API zurückgibt.
10DLC-Registrierung & Kampangentyppen (US)
Wenn Sie zu US-Zielen über numerische Long-Codes senden, erfordern die Carrier Registrierung; unregistrierter Verkehr wird gefiltert, surcharged oder beides. Orbit übermittelt Registrierung durch The Campaign Registry in Ihrem Namen — der vollständige Walkaround (Marke → Kampagne → Genehmigung → Durchsatz-Tiers) ist in der 10DLC-Registrierungsanleitung. Der US-spezifische Punkt, den Sie im Kopf halten: Durchsatz nach Registrierung wird als pro-Tag-, pro-Nummer-Segment-Kappe auf Basis Ihrer Marken-Vetting-Score gewährt — nicht eine pro-Sekunde-Rate. Mehr tägliche Kapazität nötig? Erhöhen Sie Ihre Vetting-Score (vollständige Markendaten, EIN, Website) oder weisen Sie mehr Nummern der Kampagne zu. Für nicht-US-Ziele, die alphanumerische Absender-IDs gaten (meiste Europa, Brasilien, Bangladesh, Teile APAC), ist der parallele Registrierungsfluss Absender-ID-Registrierung, der Ihre Genehmigung pro Land aufzeichnet und die unterstützenden KYC-Dokumente anbindet. Das Sende-Zeit-Gate verweigert Verkehr zu gated Ländern, bis der passende Landeintragapproved ist — keine Stillfilterung, der Fehler kommt als sichtbarer rejected zurück.
Indien ist die Ausnahme: Seine Absender-IDs (“Headers”) registrieren über DLT/TRAI statt dem generischen Fluss — siehe DLT-Indien-Onboarding.
Kodierung & Konkatenation
Kodierung ist die einzige Kostenvariable, die einen ordentlich registrierten Absender überlebt. SMS rechnet pro Segment ab, und die Segmentzahl hängt völlig davon ab, in welche Alphabet der Body passt.GSM-7 vs. UCS-2
- GSM-7 — das 7-Bit-GSM-Alphabet (ASCII plus ein paar Extras:
@,£,€, etwas Griechisch). Ein Body, der hineinpasst, bekommt bis 160 Zeichen pro Segment, oder 153 Zeichen auf Multi-Part (7 pro Segment gehen an den UDH-Konkatenations-Header). - UCS-2 — jedes Zeichen außerhalb GSM-7 (Emoji, CJK, Smart-Anführungszeichen, meiste nicht-Latin-Skripte) flipt die ganze Nachricht auf 16-Bit-Kodierung. Ein Body bekommt bis 70 Zeichen pro Segment oder 67 auf Multi-Part.
Abgearbeitetes Beispiel
Ihre Bestellung versandt — Antwort JA — 30 Zeichen, alle GSM-7 → 1 Segment, GSM-7.
Ein einziges Emoji flipt das Alphabet: 54 Zeichen in UCS-2 → immer noch 1 Segment, aber ein 160-Zeichen-ASCII-Newsletter wird 2 UCS-2-Segmente, sobald ein Emoji hereinkommt. Auf Skala ist das die Zahl, die Kosten treibt.
Die Plattform zählt Segmente vor dem Dispatchen; die Send-Antwort trägt das Verdikt:
wasTruncated: true, damit Sie sehen, statt zu vielen, wo der Schwanz blieb. Das ist es, was die Features-Liste nennt “konkatenierte Nachrichten bis zu 10 Segmente”. Lesen Sie segments auf jeder Sendung und verzweigen Sie Ihre Abrechnungsschätzungen darauf — es ist genau das, wogegen Segment-Preisung multipliziert.
Rate-Limits, Durchsatz & Absender-Pools
Zwei unabhängige Limits auf SMS-Durchsatz, und Sie müssen beide leeren:- API-seitiges Request-Limit. 100 Requests/Minute pro Tenant standardmäßig auf
POST /messages/sms, pro Organisation keyed. Darüber bekommen Sie429 RATE_LIMITED; siehe Rate-Limits-Anleitung für Header und Retry-Handling. Die volle Per-Channel-Tabelle unten. - Absender-seitiger Durchsatz. US 10DLC: pro-Tag, pro-Nummer Segment-Kappe von Ihrer Vetting-Tier. Woanders: was die Zielroute pro Absender unterstützt.
sticky, round_robin, random oder geomatch-Strategie verteilen, und Per-Absender-Durchsatz multipliziert mit Pool-Size. Pools lassen einen degradierten Absender ohne Änderung Ihres Sendcodes rotieren — der Pool-Health-Endpunkt sagt, welches Mitglied degradiert, bevor es ein Deliverability-Problem wird.
Nachrichten-Status-Lifecycle
Jede ausgehende SMS trägt einenstatus, der vorrückt, wenn die Nachricht von Ihrem API-Aufruf zum Handset — oder zum Terminal-Fehler — bewegt:
queued → sending → sent → delivered (oder failed / undelivered / rejected / expired)
Abonnieren Sie Status-Übergänge über Webhooks mit den Events message.sent, message.delivered und message.failed — ein Webhook pro Übergang, jeder trägt die Nachricht-id und den neuen status.
Die Nuance, die Operatoren fängt:
submitted_no_receipt— der Provider akzeptierte die Sendung, keine DLR kam innerhalb des 30-minütigen SMPP-Grace-Fensters zurück. Als Zwischen markiert (is_terminal: false), weil eine spätedeliveredoder Fehler-DLR noch ankommen und überschreiben kann. Behandeln Sie es als Ergebnis unbekannt, nicht eine Zustellung und nicht ein Fehler.expired— eine DLR kam an, nachdem das Spät-Zulassungsfenster schloss. Geschlossene Zeile, unkenntliches Ergebnis; fans aufmessage.failedaus.cancelled— nur von Ihnen erreichbar; kein Webhook feuert je dafür.
is_terminal bedeutet, lebt in Liefer-Lifecycle; die Per-Status-Semantiken und die volle Übergangstabelle stehen in der Nachrichten-Status-Lifecycle-Referenz.
Troubleshooting
Wennmessage.failed ankommt, verzweigen Sie auf den Payload-status, nicht den Event-Typ — submitted_no_receipt und expired fanen auch auf diesem Event aus. Lesen Sie metadata.classified_error_code für Maschinen-Handling, und error_code / error_message für des Carriers eigene Worting, wenn Sie ein Ticket öffnen.
Das Eskalations-Paket, das ein Support-Ticket beim ersten Pass beantwortet: Ihre Tenant-ID, eine Nachricht-ID und die Zeilen-
classified_error_code — plus Provider-Referenz aus dem Liefer-Log für DLR-Symptom-Zeilen. Der Liefer-Log-Anleitung zeigt, wie man den Status filtert; Nummern-Lookup sagt eine tote Nummer von einer lebendigen, bevor Sie wiederholen.
Preisung
SMS-Preisung ist pro Segment und variiert nach Zielland. Prüfen Sie die Preisseite oder fragen Sie den EndpunktGET /api/v1/pricing/messaging?country=<ISO> für Echtzeit-Rates ab (das zurückgegebene channels-Array enthält sms).
Die Planungszahl kommt aus den vorherigen Abschnitten: multiplizieren Sie die Pro-Segment-Rate, die der Preis-Endpunkt zurückgibt, mit dem segments-Wert, den die Send-Antwort trägt. Zwei sonst identische Sendungen rechnen verschieden ab, sobald deren Kodierung auf UCS-2 flipt — siehe Kodierung & Konkatenation, wann das passiert und wie man es zurücknormalisiert.
Features
- A2P- und P2P-Nachrichten — App-an-Person- und Person-an-Person-Support
- Globaler Reach — 190+ Länder über Devotels Aggregator-Netz
- Zustell-Berichte — Echtzeit-Status-Webhooks für jede Nachricht
- Konkatenierte Nachrichten — Multi-Part-SMS transparent gehandhabt (bis 10 Segmente)
- E.164-Validierung — automatische Telefonnummer-Format-Validierung
- Unicode-Support — vollständige GSM-7- und UCS-2-Kodierung mit automatischer Erkennung und Smart-Punctuation-Normalisierung
- Absender-ID — alphanumerische Absender-IDs, wo lokalen Vorschriften unterstützt, registrierungs-gated wo erforderlich
Rate-Limits
SMS-Sendungen sind auf 100 Requests/Minute pro Tenant standardmäßig auf dem/messages/sms-Endpunkt limitiert. Das Limit ist pro Tenant (pro Organisation) keyed, nicht pro IP oder pro Plan, also konkurrierende Aufrufer im selben Tenant teilen einen Pool, während separate Tenants sich nie beeinflussen.
Eine höhere Decke nötig? Die Pro-Tenant-Kappe ist über Ihre Organisation-Nachrichten-Einstellungen (channel_rate_overrides.sms) überbrückbar — Support kontaktieren oder vom Dashboard setzen. Limit-Überschreitung gibt 429 Too Many Requests mit dem RATE_LIMITED-Fehlercode zurück; siehe Rate-Limits-Anleitung für Header und Retry-Handling.
Der gleiche Per-Channel-, Per-Minute-, Pro-Tenant-Modell gilt über Nachrichten-Kanäle (jede unabhängig überbrückbar):