SMS-API integrieren: Schritt-für-Schritt-Anleitung in 5 Minuten
SMS-API an Shop oder App anbinden: Konto, API-Schlüssel, erste SMS per REST, Zustellberichte per Webhook. Beispiele in curl, PHP, Node.js und Python, ohne SDK.
Diese Anleitung richtet sich an Entwickler, die ihre erste SMS so schnell wie möglich über die TopSMS-API senden möchten. Grundkenntnisse in HTTP und JSON werden vorausgesetzt.
1. Registrierung + API-Schlüssel (2 Minuten)
- Konto anlegen: Sie erhalten 10 Test-SMS
- Mobilnummer mit dem per SMS zugesandten Code bestätigen
- Im Dashboard zu API-Zugang → „Schlüssel erstellen“
- Ausfüllen:
- Name:
dev-test(nur für Sie) - Scopes:
send(Versand) undread(Statusabfrage) ankreuzen - IP-Whitelist: für den Produktivbetrieb ausfüllen, für den Test überspringen
- Testschlüssel: ankreuzen, wenn Sie die Integration ohne echten Versand testen möchten. Ein solcher Schlüssel sendet und berechnet nichts, liefert dieselben Antworten wie ein Produktivschlüssel (zusätzlich
"test": true) und simuliert Zustellberichte und Webhooks; Nummern mit der Endung0000simulieren einen Fehlschlag,0001einen Ablauf. Die Nummer+420600000000in den Beispielen unten ist nur ein Platzhalter; mit einem Produktivschlüssel setzen Sie Ihre eigene Nummer ein
- Name:
- „Erstellen“ klicken: Sie sehen clientId und secret (das Secret wird nur einmal angezeigt, speichern Sie es)
Die Authentifizierung erfolgt per Bearer-Token im Format clientId:secret.
2. Erste SMS mit curl (30 Sekunden)
curl -X POST https://www.topsms.cz/api/sms/send \
-H "Authorization: Bearer YOUR_CLIENT_ID:YOUR_SECRET" \
-H "Content-Type: application/json" \
-d '{
"to": "+420600000000",
"from": "TopSMS",
"text": "Ahoj z API!"
}'Antwort:
{
"ok": true,
"id": "cmp7a1b2c3...",
"externalId": "a1b2c3d4-...",
"to": "+420600000000",
"from": "TopSMS",
"smsCount": 1,
"price": 0.98,
"status": "sent"
}Speichern Sie die id; darüber fragen Sie den Zustellstatus ab. price ist der Betrag, der soeben vom Guthaben abgezogen wurde, smsCount die Anzahl der berechneten Teile. Die API gibt Beträge in CZK zurück, der internen Abrechnungswährung der Plattform: 0,98 im Beispiel ist der Preis eines Teils an eine tschechische Nummer (0,040 €); ein Teil nach Deutschland, Österreich oder in die übrige EU kostet 0,084 €. Die Nachrichtentexte in den Beispielen sind Platzhalter; setzen Sie Ihren eigenen Text ein.
Die Laufzeit von Ende zu Ende (Ihr Terminal → Telefon des Empfängers) liegt in der Regel bei Sekunden, nicht Minuten; die genaue Dauer hängt von der aktuellen Auslastung der Mobilfunknetze ab.
3. PHP (3 Zeilen)
$ch = curl_init('https://www.topsms.cz/api/sms/send');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('TOPSMS_CLIENT_ID') . ':' . getenv('TOPSMS_SECRET'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'to' => '+420600000000',
'from' => 'TopSMS',
'text' => 'Ahoj z PHP!',
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if ($response['ok'] ?? false) {
echo "SMS odeslána, ID: {$response['id']}";
}Für den Produktivbetrieb empfehlen wir den Guzzle HTTP Client wegen der besseren Fehlerbehandlung. Optional gibt es auch eine Bibliothek: composer require topsms/topsms-php.
4. Node.js (natives fetch)
const response = await fetch('https://www.topsms.cz/api/sms/send', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.TOPSMS_CLIENT_ID}:${process.env.TOPSMS_SECRET}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
to: '+420600000000',
from: 'TopSMS',
text: 'Ahoj z Node.js!',
}),
})
const data = await response.json()
if (data.ok) {
console.log('SMS odeslána, ID:', data.id)
} else {
console.error('Chyba:', data.error)
}Node.js 18+ bringt fetch nativ mit. Für ältere Versionen verwenden Sie node-fetch oder axios.
5. Python (requests)
import os
import requests
response = requests.post(
'https://www.topsms.cz/api/sms/send',
headers={
'Authorization': f'Bearer {os.environ["TOPSMS_CLIENT_ID"]}:{os.environ["TOPSMS_SECRET"]}',
'Content-Type': 'application/json',
},
json={
'to': '+420600000000',
'from': 'TopSMS',
'text': 'Ahoj z Pythonu!',
},
)
data = response.json()
if data.get('ok'):
print(f"SMS odeslána, ID: {data['id']}")
else:
print(f"Chyba: {data.get('error')}")6. Format der Telefonnummer
Wir empfehlen das E.164-Format mit dem Präfix +:
+49301234567(DE)+431234567(AT)+420600000000(CZ)+421900123456(SK)
Die API ist tolerant und wandelt auch diese Schreibweisen in E.164 um:
0049301234567(00 statt +)49301234567(Ländervorwahl ohne +)600000000oder600 000 000: eine Nummer ohne Ländervorwahl wird als tschechische Nummer behandelt (Leerzeichen werden entfernt)
Für deutsche und österreichische Empfänger geben Sie daher immer die Ländervorwahl an: Ein nationales Format wie 0170 … oder 0664 … wird nicht akzeptiert (ebenso wenig eine slowakische Nummer in der Form 0905 …). In der Antwort erhalten Sie die normalisierte Nummer im Feld to.
7. Absendername (Parameter from)
- Ohne eigenen Absendernamen: senden Sie
TopSMS(unser Standardabsender), für den Test ausreichend - Mit eigenem Absendernamen: senden Sie den freigegebenen Namen (z. B.
Eshop123). Den Namen beantragen Sie im Dashboard; deutsche, österreichische und die meisten anderen europäischen Netze stellen alphanumerische Absendernamen ohne Registrierung beim Netzbetreiber zu. Tschechische und slowakische Netzbetreiber verlangen eine einmalige Registrierung (20,58 €), die wir für Sie übernehmen - Max. 11 Zeichen, nur Buchstaben, Ziffern, Bindestrich und Unterstrich
- Freigegeben, aber bei den Netzbetreibern noch nicht aktiv: Die Nachricht wird mit dem Absender
TopSMSgesendet, und die Antwort enthält"senderFallback": trueund"requestedFrom": "Eshop123". Nach der Aktivierung wird ohne Änderung an Ihrem Code unter Ihrem Namen gesendet.
8. Status einer Nachricht abfragen
Nach dem Versand haben Sie eine id. Den Status fragen Sie so ab:
curl -H "Authorization: Bearer YOUR_CLIENT_ID:YOUR_SECRET" \
https://www.topsms.cz/api/sms/status/MESSAGE_IDAntwort:
{
"id": "cmp7a1b2c3...",
"externalId": "a1b2c3d4-...",
"to": "+420600000000",
"from": "TopSMS",
"text": "Ahoj z API!",
"status": "delivered",
"price": 0.98,
"carrier": "230.2",
"createdAt": "2026-05-19T10:23:42.000Z",
"deliveredAt": "2026-05-19T10:23:45.000Z",
"failedAt": null,
"errorMessage": null,
"errorCode": null
}Mögliche Zustände: pending (wird gerade gesendet), queued (in der Warteschlange oder geplant), sent, delivered, failed, expired. Bei failed und expired finden Sie den Grund in errorCode (undelivered, rejected, expired, repeated_failure und weitere) und in errorMessage. carrier ist der Netzcode des Empfängers im Format MCC.MNC; im Beispiel steht 230.2 für O2 Tschechien (230.1 T-Mobile CZ, 230.3 Vodafone CZ).
Alternativ legen Sie beim API-Schlüssel eine Webhook-URL fest; der Zustellbericht kommt dann in Echtzeit als POST. Siehe Webhooks in der Dokumentation.
9. Typische Fehler (HTTP-Status)
| Status | Grund | Lösung |
|---|---|---|
| 401 | Ungültiges Token | Header Authorization prüfen |
| 400 | to/text fehlt, ungültige Nummer oder Nummer auf der Blacklist | Nummer prüfen, idealerweise E.164 mit + |
| 403 | Nicht freigegebener Absendername in from | Freigegebenen Namen verwenden oder from weglassen (Standard TopSMS) |
| 402 | Guthaben reicht nicht | Guthaben im Dashboard aufladen |
| 403 | Scope send fehlt | API-Schlüssel bearbeiten, send ankreuzen |
| 429 | Rate-Limit des Schlüssels (Standard 60 Anfragen/min) | Gemäß Header Retry-After warten oder das Limit im Dashboard erhöhen (bis 1000) |
500 record_failed | SMS gesendet, aber nicht gespeichert, Guthaben gutgeschrieben | Nicht wiederholen, an den Support schreiben |
| 500 sonstige | Unerwarteter Fehler | Mit demselben Idempotency-Key wiederholen |
| 502 | Netzbetreiber hat die Nachricht nicht angenommen, Guthaben gutgeschrieben | Später erneut versuchen |
10. Empfohlene Architektur für den Produktivbetrieb
[Ihre Anwendung]
↓ POST /api/sms/send
[TopSMS API]
↓ asynchron
[Mobilfunknetze]
↓
[Telefon des Empfängers]
↓ Zustellbericht
[TopSMS API]
↓ POST Webhook
[Ihre Anwendung]
↓ DB aktualisierenDie wichtigsten Prinzipien:
- Idempotenz: Senden Sie den Header
Idempotency-Key(etwa die Bestellnummer). Eine wiederholte Anfrage sendet die SMS dann nicht ein zweites Mal, siehe API-Dokumentation - Webhook-Signatur: Validieren Sie die HMAC-Signatur (pro API-Schlüssel einstellbar)
- Rate-Limit-Budget: Planen Sie das Tagesvolumen so, dass Lastspitzen 30 % Reserve behalten
- Fallback: Fällt das Guthaben unter einen Schwellenwert, weichen Sie auf einen Ersatzkanal aus
11. Sicherheit: Was Sie NICHT tun sollten
- Legen Sie den API-Schlüssel niemals ins Frontend (JavaScript im Browser), jeder könnte ihn auslesen. API-Aufrufe nur vom Server.
- Niemals in Git einchecken:
.env-Datei plus.gitignoreverwenden. - Secret nicht weitergeben, auch nicht in Discord, Slack oder Screenshots. Bei einem Leck sofort einen neuen Schlüssel erstellen und den alten widerrufen.
- Testdaten nicht missbrauchen: Senden Sie keine SMS an zufällige Nummern.
+420600000000aus den Beispielen ist nur ein Platzhalter; zum Ausprobieren verwenden Sie einen Testschlüssel, der nichts sendet und nichts berechnet.
12. Wie es weitergeht
Sobald die Antwort die erste id enthält, funktioniert Ihre Integration. Nächste Schritte:
- Eigener Absendername: im Dashboard beantragen; für tschechische und slowakische Netze geben die Netzbetreiber neue Namen gesammelt etwa einmal im Monat frei (rechnen Sie mit rund 3 Wochen), einmalig 20,58 €
- Webhooks: Push-Zustellberichte mit HMAC-Signatur
- Massenversand:
/api/sms/send-bulknimmt bis zu 500 Empfänger in einer Anfrage an, siehe Massenversand - Shop anbinden: für WooCommerce das offizielle Plugin, andere Plattformen über die REST-API oder Webhooks: Integrationen
Für höhere Volumen (ab 20.000 SMS pro Monat) richten wir auf Anfrage eine individuelle SMPP-Anbindung ein.