Für Entwickler
API-Dokumentation
Lesen Sie Ihr Guthaben und den aktuellen Preis jedes Dienstes in jedem Land direkt aus Ihrem eigenen Code aus. Ein Bearer-Schlüssel, JSON über HTTPS, keine Installation eines SDK nötig.
Erste Schritte #
Alles läuft über JSON per HTTPS, authentifiziert mit einem einzigen Schlüssel, den Sie selbst erstellen. Kein SDK zu installieren, kein Vertrag zu unterschreiben, keine Sandbox zu beantragen — ein Schlüssel und curl genügen.
- 1 Schlüssel anlegen Öffnen Sie das Kontomenü, dann API-Schlüssel, dann Schlüssel erstellen. Er wird nur einmal angezeigt: Wir speichern nur seinen Fingerabdruck, sodass er danach nicht mehr abgerufen werden kann.
- 2 Als Bearer-Token senden Jede Anfrage trägt einen Authorization-Header. Einen anderen Weg gibt es nicht — keinen Schlüssel im Query-String, kein Cookie, keine Sitzung.
- 3 Antwort lesen Jede Antwort ist ein JSON-Objekt mit einem Feld ok. Ist ok false, nennt ein Feld error den Grund als stabile, maschinenlesbare Zeichenkette.
Authentifizierung #
Ein Schlüssel pro Konto. Jeder andere Weg als der Header unten wird nicht unterstützt — ein Schlüssel im Query-String landet in Server-Logs, im Browserverlauf und in Referrer-Headern, deshalb wird er abgelehnt statt stillschweigend akzeptiert.
Authorization: Bearer sk_your_key_here
Schlüssel gibt Geld aus Er liest heute das Guthaben aus, und es ist derselbe Schlüssel, der später Nummern bestellen wird, sobald die Bestellung existiert. Behandeln Sie ihn wie ein Passwort: nicht in der Versionskontrolle, nicht in Screenshots, ersetzt statt geteilt. Das Ersetzen eines Schlüssels schließt den alten sofort.
Konventionen #
| Basisadresse | https://simsms.com/api/v1 |
|---|---|
| Transport | Nur HTTPS. Reines HTTP wird umgeleitet, und die Weiterleitung trägt Ihren Header nicht mit. |
| Format | JSON rein, JSON raus. Jede Antwort ist ein Objekt, nie ein reines Array. |
| Erfolg | HTTP 200 mit "ok": true. |
| Fehler | Ein 4xx- oder 5xx-Code mit "ok": false und einer stabilen "error"-Zeichenkette. |
| Geld | Zahlen in US-Dollar, nie als Zeichenkette, nie in Cent. 0.84 bedeutet 84 Cent. |
| Unbekannte Felder | Jeder Antwort können neue Felder hinzugefügt werden. Ignorieren Sie, was Sie nicht kennen, statt daran zu scheitern. |
Fehler #
Die error-Zeichenkette ist der Teil, auf dem Sie verzweigen. Der Satz daneben ist für Sie, nicht für Ihren Code — er kann umformuliert werden; die Zeichenkette nicht.
| HTTP | Fehler | Wann |
|---|---|---|
| 401 | missing_key |
Kein Authorization-Header, oder es ist kein Bearer-Token. |
| 401 | bad_key |
Der Schlüssel ist unbekannt, oder er wurde geschlossen oder ersetzt. |
| 400 | unknown_service |
Kein Dienst mit diesem Code. Codes stammen aus dem Katalog, nicht aus dem Anzeigenamen. |
| 404 | no_stock |
Für diese Kombination aus Dienst und Land ist im Moment keine Nummer verfügbar. Das ist ein Live-Wert — er kann sich wieder ändern. |
| 404 | unknown_country |
Kein Land mit diesem Code für dieses Produkt. Die Kataloge für Proxy und Miete führen jeweils eigene Listen — rufen Sie die Route ohne Land auf, um sie zu erhalten. |
| 400 | unknown_tech |
Diese Netzgeneration gibt es in diesem Land nicht. Nur die Vereinigten Staaten bieten sowohl 4g als auch 5g an. |
| 429 | rate_limited |
Zu viele Anfragen. Ein Retry-After-Header gibt an, wie viele Sekunden Sie warten müssen. |
Rate Limits #
600 Anfragen pro Minute, gezählt pro Konto statt pro Adresse. Ein Schlüssel soll von einem Server aus laufen — einer Adresse —, daher würde ein Limit pro Adresse normale Nutzung bestrafen und einem gestohlenen Schlüssel erlauben, anderswo frei zu laufen. Über dem Limit erhalten Sie 429 und einen Retry-After-Header in Sekunden.
Endpunkte #
Konto- und Katalogabfragen. Jede Route listet jeden Parameter, den sie annimmt, jedes Feld, das sie zurückgibt, und jeden Fehler, mit dem sie antworten kann — kein undokumentiertes Verhalten.
Guthaben abfragen #
GET
/api/v1/balance
Was das Konto gerade enthält, und wie viele Codes das zum aktuell günstigsten Preis im Katalog kauft.
Antwortfelder
| Feld | Typ | Beschreibung |
|---|---|---|
ok |
boolean | Immer true bei 200. |
balance |
number | Verfügbare Dollar, auf den Cent gerundet. |
currency |
string | Immer "USD". Vorhanden, damit Sie es nie annehmen müssen. |
codes_at_cheapest |
integer | Wie viele Codes das Guthaben zum günstigsten Preis im Katalog kauft. Ein grober Richtwert, kein Angebot — null, wenn der Katalog leer ist. |
cheapest_code |
number | Dieser günstigste Preis, damit Sie den Richtwert selbst gegen eine andere Zahl berechnen können. |
Anfrage
curl -s "https://simsms.com/api/v1/balance" \
-H "Authorization: Bearer $SIMSMS_KEY"
Antwort
{
"ok": true,
"balance": 42.5,
"currency": "USD",
"codes_at_cheapest": 425,
"cheapest_code": 0.1
}
Mögliche Fehler missing_key bad_key rate_limited
Preis für einen Dienst in einem Land #
GET
/api/v1/pricing?service={service}&country={country}
Der Live-Preis und die Live-Verfügbarkeit für ein einzelnes Paar. Beide Werte bewegen sich — der Preis folgt dem günstigsten Netz, das diesen Dienst in diesem Land anbietet, und die Verfügbarkeit ist das, was das Netz gerade meldet.
Parameter
| Parameter | Beschreibung | |
|---|---|---|
service |
Pflicht | Dienst-Code, zum Beispiel telegram. Kleinschreibung, aus dem Katalog. |
country |
optional | Länder-Code, zum Beispiel england. Weglassen, um alle Länder auf einmal zu erhalten — siehe unten. |
Antwortfelder
| Feld | Typ | Beschreibung |
|---|---|---|
ok |
boolean | Immer true bei 200. |
service |
string | Der angefragte Dienst-Code, unverändert zurückgegeben. |
country |
string | Der angefragte Länder-Code, unverändert zurückgegeben. |
price |
number | Dollar für einen Code, beim günstigsten Netz, das ihn führt. |
stock |
integer | Gerade als verfügbar gemeldete Nummern. Das ist ein Live-Wert und er ändert sich. |
Anfrage
curl -s "https://simsms.com/api/v1/pricing?service=telegram&country=england" \
-H "Authorization: Bearer $SIMSMS_KEY"
Antwort
{
"ok": true,
"service": "telegram",
"country": "england",
"price": 0.84,
"stock": 61213
}
Mögliche Fehler missing_key bad_key unknown_service no_stock rate_limited
Preis für einen Dienst überall #
GET
/api/v1/pricing?service={service}
Lassen Sie das Land weg, und Sie erhalten jedes Land, das den Dienst anbietet. Die Reihenfolge ist die eigene der Website: Was tatsächlich zuerst liefert, darunter das Günstigste — nicht der reine Preis, der sonst eine Zwei-Cent-Nummer nach oben stellen würde, von der niemand einen Code erhält.
Parameter
| Parameter | Beschreibung | |
|---|---|---|
service |
Pflicht | Dienst-Code, zum Beispiel telegram. |
Antwortfelder
| Feld | Typ | Beschreibung |
|---|---|---|
ok |
boolean | Immer true bei 200. |
service |
string | Der angefragte Dienst-Code. |
name |
string | Anzeigename, zum Beispiel „Telegram“. |
countries |
array | Ein Objekt pro Land, in der oben beschriebenen Reihenfolge. |
countries[].country |
string | Ländercode, zur Verwendung im pair-Aufruf. |
countries[].name |
string | Englischer Name. |
countries[].price |
number | Dollar für einen Code. |
countries[].stock |
integer | Aktuell verfügbare Nummern. |
Anfrage
curl -s "https://simsms.com/api/v1/pricing?service=telegram" \
-H "Authorization: Bearer $SIMSMS_KEY"
Antwort
{
"ok": true,
"service": "telegram",
"name": "Telegram",
"countries": [
{ "country": "england", "name": "United Kingdom", "price": 0.84, "stock": 61213 },
{ "country": "poland", "name": "Poland", "price": 0.91, "stock": 22140 }
]
}
Mögliche Fehler missing_key bad_key unknown_service rate_limited
Mobil-Proxy bepreisen #
GET
/api/v1/proxy-pricing?country={country}&tech={tech}
Ohne Land erhalten Sie die vier Länder, in denen wir Modems betreiben, mit ihrer Anzahl an Anbietern und dem Einstiegspreis. Mit einem Land erhalten Sie jeden dortigen Anbieter und den Preis für jede Laufzeit. Die Laufzeiten sind in Tagen angegeben: 1, 7, 30, 365.
Parameter
| Parameter | Beschreibung | |
|---|---|---|
country |
optional | Ländercode, zum Beispiel us. Lassen Sie ihn weg, um die Länder aufzulisten. |
tech |
optional | Netzgeneration, 4g oder 5g. Nur die Vereinigten Staaten bieten beides an; anderswo wird das Feld ignoriert und der einzige Bereich zurückgegeben. |
Antwortfelder
| Feld | Typ | Beschreibung |
|---|---|---|
ok |
boolean | Bei 200 immer true. |
country |
string | Das angefragte Land. |
tech |
string | Die tatsächlich bepreiste Generation, nachdem der Standardwert angewendet wurde. |
techs |
array | Jede in diesem Land verkaufte Generation. |
terms |
array | Die angebotenen Laufzeiten, in Tagen. |
carriers |
array | Ein Objekt pro Anbieter. |
carriers[].carrier |
string | Anbietercode, zur Verwendung in der Bestellung. |
carriers[].name |
string | Anzeigename, zum Beispiel „T-Mobile“. |
carriers[].prices |
object | Dollar pro Laufzeit, mit der Anzahl der Tage als Schlüssel. |
Anfrage
curl -s "https://simsms.com/api/v1/proxy-pricing?country=us" \
-H "Authorization: Bearer $SIMSMS_KEY"
Antwort
{
"ok": true,
"country": "us",
"tech": "4g",
"techs": ["4g", "5g"],
"terms": [1, 7, 30, 365],
"carriers": [
{ "carrier": "us-t-mobile", "name": "T-Mobile", "prices": { "1": 8.67, "7": 52, "30": 130, "365": 1300 } },
{ "carrier": "us-verizon", "name": "Verizon", "prices": { "1": 8.67, "7": 52, "30": 130, "365": 1300 } }
]
}
Mögliche Fehler missing_key bad_key unknown_country unknown_tech rate_limited
Mietnummer bepreisen #
GET
/api/v1/rental-pricing?country={country}&days={days}
Ohne Land erhalten Sie jedes Land, in dem eine Nummer gehalten werden kann, mit dem jeweiligen Einstiegspreis. Mit einem Land erhalten Sie jeden dortigen Anbieter und die Kosten für die von Ihnen angefragte Laufzeit.
Parameter
| Parameter | Beschreibung | |
|---|---|---|
country |
optional | Ländercode, zum Beispiel fr. Lassen Sie ihn weg, um die Länder aufzulisten. |
days |
optional | Laufzeit in Tagen: 7, 14 oder 30. Alles andere greift auf die kürzeste zurück. |
Antwortfelder
| Feld | Typ | Beschreibung |
|---|---|---|
ok |
boolean | Bei 200 immer true. |
country |
string | Das angefragte Land. |
days |
integer | Die tatsächlich bepreiste Laufzeit. |
terms |
array | Jede angebotene Laufzeit, in Tagen. |
operators |
array | Ein Objekt pro Anbieter, günstigster zuerst. |
operators[].operator |
string | Anbietercode, zur Verwendung in der Bestellung. |
operators[].name |
string | Anzeigename. |
operators[].type |
string | physical, virtual oder premium. |
operators[].price |
number | Dollar für die gesamte Laufzeit. |
Anfrage
curl -s "https://simsms.com/api/v1/rental-pricing?country=fr&days=30" \
-H "Authorization: Bearer $SIMSMS_KEY"
Antwort
{
"ok": true,
"country": "fr",
"days": 30,
"terms": [7, 14, 30],
"operators": [
{ "operator": "fr-lycamobile", "name": "Lycamobile", "type": "virtual", "price": 14.32 },
{ "operator": "fr-orange", "name": "Orange", "type": "physical", "price": 20.76 }
]
}
Mögliche Fehler missing_key bad_key unknown_country rate_limited
Beispiele #
Vollständige, lauffähige Programme statt einzeiliger Fragmente — einschließlich der zwei Dinge, die Fragmente immer weglassen: den Umgang mit der Fehlerstruktur und das Backoff-Verhalten bei 429.
Shell #
Findet das günstigste Land für einen Dienst und prüft anschließend, ob das Guthaben dafür ausreicht.
#!/usr/bin/env bash
set -euo pipefail
: "${SIMSMS_KEY:?export your key first}"
API="https://simsms.com/api/v1"
auth=(-H "Authorization: Bearer $SIMSMS_KEY")
# The catalogue is already ordered: the first country is the one to take.
best=$(curl -sf "${API}/pricing?service=telegram" "${auth[@]}" \
| jq -r ".countries[0] | \"\(.country) \(.price)\"")
country=${best% *}
price=${best#* }
balance=$(curl -sf "${API}/balance" "${auth[@]}" | jq -r .balance)
# ⚠️ Compare as numbers, not as strings: "9.5" > "10" is true in a string sort.
if awk "BEGIN{exit !($balance >= $price)}"; then
echo "ok: $country at \$$price, balance \$$balance"
else
echo "top up first: need \$$price, have \$$balance" >&2
exit 1
fi
JavaScript #
Dasselbe in Node, mit korrekt behandelter Fehlerstruktur.
const API = "https://simsms.com/api/v1";
const key = process.env.SIMSMS_KEY;
async function call(path) {
const r = await fetch(API + path, {
headers: { Authorization: `Bearer ${key}` },
});
const body = await r.json();
// A non-2xx always carries { ok:false, error }. Branch on `error`, never on
// the sentence — the string is stable, the wording is not.
if (!r.ok || !body.ok) {
if (body.error === "rate_limited") {
const wait = Number(r.headers.get("Retry-After") || 60);
await new Promise((s) => setTimeout(s, wait * 1000));
return call(path);
}
throw new Error(body.error ?? `http_${r.status}`);
}
return body;
}
const { countries } = await call("/pricing?service=telegram");
const { balance } = await call("/balance");
const best = countries[0];
console.log(`${best.name}: $${best.price} (${best.stock} in stock)`);
console.log(balance >= best.price ? "balance covers it" : "top up first");
Python #
Und in Python, mit demselben Wiederholungsversuch bei 429.
import os, time, requests
API = "https://simsms.com/api/v1"
S = requests.Session()
S.headers["Authorization"] = f"Bearer {os.environ['SIMSMS_KEY']}"
def call(path):
r = S.get(API + path, timeout=20)
body = r.json()
if not r.ok or not body.get("ok"):
if body.get("error") == "rate_limited":
time.sleep(int(r.headers.get("Retry-After", 60)))
return call(path)
raise RuntimeError(body.get("error", f"http_{r.status_code}"))
return body
countries = call("/pricing?service=telegram")["countries"]
balance = call("/balance")["balance"]
best = countries[0]
print(f"{best['name']}: ${best['price']} ({best['stock']} in stock)")
print("balance covers it" if balance >= best["price"] else "top up first")
Fahrplan #
Die API deckt heute Konto- und Katalogabfragen ab. Als Nächstes folgt die Bestellfunktion, die unter derselben Basisadresse liegen und denselben Schlüssel verwenden wird — nichts, was Sie jetzt bauen, muss später neu geschrieben werden.
| Nummer bestellen | Geplant Geplant. Bestellungen laufen aktuell über die Website. |
|---|---|
| Code abfragen | Geplant Geplant, zusammen mit der Bestellung. |
| Nummer freigeben | Geplant Geplant, zusammen mit der Bestellung. |
| Miete über API | Geplant Geplant. |
| Webhooks | Geplant Geplant, sobald es Bestellereignisse zum Zustellen gibt. |
Diese Seite wächst mit ihnen: Die Abschnitte unten bleiben, wie sie sind, neue werden unter Endpunkte hinzugefügt.
Änderungen #
- Erste öffentliche Version: Schlüssel, GET /balance, GET /pricing.