SMSCode API Guide für Entwickler: Virtuelle Nummern programmatisch nutzen

SMSCode API Guide für Entwickler: Virtuelle Nummern programmatisch nutzen

Wer virtuelle Nummern regelmäßig oder in größeren Mengen nutzt, kommt an der API nicht vorbei. Statt jede Nummer manuell über das Dashboard zu buchen, lässt sich der gesamte Prozess – von der Nummernbeschaffung bis zum SMS-Empfang – vollständig automatisieren. Dieser Guide erklärt, wie das geht, welche Fallstricke es gibt und wie man die API sicher und effizient in eigene Anwendungen integriert.

TL;DR: Die SMSCode REST API ermöglicht vollautomatische Nummer-Buchung und SMS-Abholung. Mit Bearer-Token-Auth, klaren Endpunkten und Polling-Mechanismus lässt sich die API in wenigen Minuten integrieren. Code-Beispiele in JavaScript, Python und cURL inklusive. Für CI/CD-Pipelines, automatisierte Tests und Konto-Provisioning ist die API das richtige Werkzeug.

Warum die API statt dem Dashboard?

Das Dashboard von SMSCode ist komfortabel für gelegentliche, manuelle Nutzung. Sobald aber wiederkehrende Abläufe entstehen — beim Testen von Registrierungs-Flows in einer CI/CD-Pipeline, beim automatisierten Aufsetzen von Testkonten für verschiedene Plattformen oder beim Aufbau eigener interner Tools — wird manuelle Bedienung zum Engpass.

Die API löst dieses Problem auf mehreren Ebenen:

  • Skalierbarkeit: Hunderte Nummern in einem einzigen Skript buchen, ohne manuellen Eingriff
  • Integration: Direkt in CI/CD-Pipelines, Test-Frameworks (Playwright, Cypress, Selenium) oder eigene Backend-Services einbauen
  • Echtzeit: SMS-Empfang über Polling ohne manuelles Nachschauen im Browser — der Code landet direkt in der Anwendung
  • Zuverlässigkeit: Programmatische Fehlerbehandlung, automatische Retry-Logik und sauberes Stornieren nicht genutzter Nummern
  • Reproduzierbarkeit: Verifizierungsflows können als Code versioniert, getestet und reproduziert werden

Typische Szenarien für API-Nutzung:

  • Automatisierte End-to-End-Tests, die echte SMS-Verifizierung erfordern
  • Provisioning von Unternehmenskonten auf verschiedenen Plattformen
  • Entwicklertools und interne Portale für Teams
  • Massenregistrierung bei Datenerhebungsprojekten (unter Einhaltung der jeweiligen Nutzungsbedingungen)

Authentifizierung

Die SMSCode API verwendet Bearer-Token-Authentifizierung. Den API-Token findet man im Dashboard unter den Account-Einstellungen. Token generieren, sicher verwahren und im Code niemals hartcodiert hinterlegen.

Authorization: Bearer <dein-api-token>

Sicherheitsregeln für den API-Token:

  • Den Token niemals in öffentlichen Repositories, client-seitigem Code oder Anwendungs-Logs speichern
  • Umgebungsvariablen (process.env.SMSCODE_API_TOKEN) oder dedizierte Secret-Manager (HashiCorp Vault, AWS Secrets Manager, GitHub Secrets, GitLab CI/CD Variables) verwenden
  • Bei Verdacht auf Kompromittierung sofort im Dashboard invalidieren und einen neuen Token generieren
  • Token regelmäßig rotieren, besonders nach dem Ausscheiden von Teammitgliedern mit Zugang

Der Token ist direkt mit dem SMSCode-Konto verknüpft — alle API-Anfragen werden entsprechend abgerechnet. Es gibt keine granulare Rechteverwaltung pro Token; jeder Token hat vollen Kontozugang.

Basis-URL und Versioning

https://api.smscode.gg/v1/

Die API ist semantisch versioniert. Die aktuelle Version ist v1. Breaking Changes werden mit einer neuen Versionsnummer eingeführt; ältere Versionen bleiben für eine Übergangszeit aktiv, bevor sie depreciert werden. Empfehlung: Versionspräfix hart in die API-Basis-URL kodieren, nicht dynamisch auflösen.

Kernendpunkte im Überblick

Katalog abfragen

Bevor eine Nummer gebucht wird, empfiehlt sich die Katalogabfrage — um verfügbare Länder, Dienste und aktuelle Preise zu kennen. Preise ändern sich dynamisch je nach Verfügbarkeit; immer die aktuellen Preise beim Buchen prüfen.

Alle Länder abfragen:

GET /v1/catalog/countries

Antwort (Auszug):

{
  "success": true,
  "data": [
    { "id": 1, "name": "United States", "code": "US", "flag": "🇺🇸" },
    { "id": 2, "name": "Germany", "code": "DE", "flag": "🇩🇪" },
    { "id": 3, "name": "United Kingdom", "code": "GB", "flag": "🇬🇧" }
  ]
}

Alle Dienste für ein Land abfragen:

GET /v1/catalog/services?country_id=1

Preis für eine bestimmte Kombination:

GET /v1/catalog/price?country_id=1&service_id=wa

Die Antwort enthält den aktuellen Preis, die Verfügbarkeit und — falls mehrere Preisstufen (Tiers) existieren — alle verfügbaren Optionen. Tiers unterscheiden sich in Qualität und Preis; höhere Tiers haben in der Regel bessere Erfolgsraten.

Nummer buchen (Order erstellen)

POST /v1/orders
Content-Type: application/json

{
  "country_id": 1,
  "service_id": "wa",
  "price_tier": "S1"
}

Erfolgreiche Antwort:

{
  "success": true,
  "data": {
    "order_id": "ord_abc123",
    "phone_number": "+12025551234",
    "status": "waiting",
    "expires_at": "2026-03-16T12:15:00Z"
  }
}

Die Nummer ist nun reserviert und aktiv. Der externe Dienst (z. B. WhatsApp, eBay, Discord) kann jetzt SMS an diese Nummer senden. Das Guthaben wird in diesem Moment belastet.

Wichtig: Die Bestellung hat eine Ablaufzeit (expires_at). Wenn innerhalb dieser Zeit keine SMS empfangen wird und die Bestellung nicht storniert wird, verfällt sie — das Guthaben wird nicht erstattet. Storniere nicht genutzte Bestellungen immer aktiv.

SMS-Status pollen

GET /v1/orders/{order_id}

Antwort mit eingegangener SMS:

{
  "success": true,
  "data": {
    "order_id": "ord_abc123",
    "status": "completed",
    "sms_code": "123456",
    "sms_text": "Dein WhatsApp-Code: 123456",
    "received_at": "2026-03-16T12:03:45Z"
  }
}

Status-Werte im Überblick:

StatusBedeutungNächste Aktion
waitingNummer aktiv, noch keine SMSWeiter pollen
completedSMS empfangen, Code verfügbarCode verwenden
cancelledBestellung storniertNeue Bestellung
expiredZeitlimit überschrittenNeue Bestellung

Bestellung stornieren

Falls die SMS nicht ankommt, eine andere Nummer benötigt wird oder der Prozess abgebrochen werden soll:

DELETE /v1/orders/{order_id}

Bei erfolgreicher Stornierung innerhalb der Stornofrist wird das Guthaben automatisch erstattet. Die Stornofrist variiert je nach Anbieter und Dienst — in der Regel 2–5 Minuten nach der Buchung. Nach dieser Frist ist eine Stornierung und damit Erstattung nicht mehr möglich.

Kontostand abfragen

GET /v1/balance
{
  "success": true,
  "data": {
    "balance": 5.42,
    "currency": "USD"
  }
}

Nützlich, um vor Massenoperationen sicherzustellen, dass ausreichend Guthaben vorhanden ist.

Code-Beispiele

JavaScript (Node.js)

Ein vollständiges Beispiel mit Fehlerbehandlung, Polling und automatischer Stornierung bei Timeout:

const API_TOKEN = process.env.SMSCODE_API_TOKEN;
const BASE_URL = 'https://api.smscode.gg/v1';

const headers = {
  'Authorization': `Bearer ${API_TOKEN}`,
  'Content-Type': 'application/json'
};

async function getVirtualNumber(countryId, serviceId, priceTier = null) {
  const body = { country_id: countryId, service_id: serviceId };
  if (priceTier) body.price_tier = priceTier;

  const orderRes = await fetch(`${BASE_URL}/orders`, {
    method: 'POST',
    headers,
    body: JSON.stringify(body)
  });

  const order = await orderRes.json();
  if (!order.success) {
    throw new Error(`Bestellfehler: ${order.error.code} — ${order.error.message}`);
  }

  const { order_id, phone_number } = order.data;
  console.log(`Nummer reserviert: ${phone_number} (Order: ${order_id})`);

  try {
    const smsCode = await pollForSms(order_id);
    return { number: phone_number, code: smsCode, orderId: order_id };
  } catch (err) {
    // Stornieren, falls SMS nicht ankam
    await cancelOrder(order_id);
    throw err;
  }
}

async function pollForSms(orderId, maxAttempts = 40, intervalMs = 4000) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    await sleep(intervalMs);

    const res = await fetch(`${BASE_URL}/orders/${orderId}`, { headers });
    const data = await res.json();

    if (!data.success) {
      throw new Error(`Statusabfrage fehlgeschlagen: ${data.error?.message}`);
    }

    const { status, sms_code } = data.data;

    if (status === 'completed') {
      console.log(`SMS empfangen: Code ${sms_code}`);
      return sms_code;
    }

    if (status === 'cancelled' || status === 'expired') {
      throw new Error(`Bestellung beendet mit Status: ${status}`);
    }

    console.log(`Warte auf SMS... (Versuch ${attempt + 1}/${maxAttempts})`);
  }

  throw new Error('Timeout: SMS nicht innerhalb des Zeitlimits empfangen');
}

async function cancelOrder(orderId) {
  try {
    const res = await fetch(`${BASE_URL}/orders/${orderId}`, {
      method: 'DELETE',
      headers
    });
    const data = await res.json();
    if (data.success) {
      console.log(`Bestellung ${orderId} storniert, Guthaben erstattet`);
    }
  } catch (err) {
    console.error('Stornierung fehlgeschlagen:', err.message);
  }
}

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

// Verwendung
getVirtualNumber(1, 'wa')  // USA, WhatsApp
  .then(({ number, code }) => {
    console.log(`Bereit: Nummer ${number}, Code ${code}`);
  })
  .catch(err => {
    console.error('Fehler:', err.message);
    process.exit(1);
  });

Python

import os
import time
import requests
from typing import Optional

API_TOKEN = os.environ['SMSCODE_API_TOKEN']
BASE_URL = 'https://api.smscode.gg/v1'
HEADERS = {
    'Authorization': f'Bearer {API_TOKEN}',
    'Content-Type': 'application/json'
}

class SmscodeError(Exception):
    def __init__(self, code: str, message: str):
        self.code = code
        self.message = message
        super().__init__(f"{code}: {message}")

def get_virtual_number(
    country_id: int,
    service_id: str,
    price_tier: Optional[str] = None
) -> dict:
    body = {'country_id': country_id, 'service_id': service_id}
    if price_tier:
        body['price_tier'] = price_tier

    response = requests.post(f'{BASE_URL}/orders', json=body, headers=HEADERS)
    order = response.json()

    if not order['success']:
        raise SmscodeError(
            order['error']['code'],
            order['error']['message']
        )

    order_id = order['data']['order_id']
    phone_number = order['data']['phone_number']
    print(f'Nummer reserviert: {phone_number} (Order: {order_id})')

    try:
        sms_code = poll_for_sms(order_id)
        return {'number': phone_number, 'code': sms_code, 'order_id': order_id}
    except Exception as e:
        cancel_order(order_id)
        raise

def poll_for_sms(
    order_id: str,
    max_attempts: int = 40,
    interval: float = 4.0
) -> str:
    for attempt in range(max_attempts):
        time.sleep(interval)

        response = requests.get(f'{BASE_URL}/orders/{order_id}', headers=HEADERS)
        data = response.json()

        if not data['success']:
            raise SmscodeError('POLL_ERROR', data.get('error', {}).get('message', 'Unbekannt'))

        status = data['data']['status']

        if status == 'completed':
            code = data['data']['sms_code']
            print(f'SMS empfangen: Code {code}')
            return code

        if status in ('cancelled', 'expired'):
            raise SmscodeError('ORDER_ENDED', f'Bestellung beendet: {status}')

        print(f'Warte auf SMS... (Versuch {attempt + 1}/{max_attempts})')

    raise TimeoutError('SMS nicht innerhalb des Zeitlimits empfangen')

def cancel_order(order_id: str) -> bool:
    try:
        response = requests.delete(f'{BASE_URL}/orders/{order_id}', headers=HEADERS)
        data = response.json()
        if data['success']:
            print(f'Bestellung {order_id} storniert, Guthaben erstattet')
            return True
    except Exception as e:
        print(f'Stornierung fehlgeschlagen: {e}')
    return False

def get_balance() -> float:
    response = requests.get(f'{BASE_URL}/balance', headers=HEADERS)
    data = response.json()
    if data['success']:
        return data['data']['balance']
    raise SmscodeError('BALANCE_ERROR', 'Kontostand konnte nicht abgerufen werden')

# Verwendung
if __name__ == '__main__':
    try:
        balance = get_balance()
        print(f'Guthaben: ${balance:.4f}')

        result = get_virtual_number(country_id=1, service_id='wa')
        print(f"Code: {result['code']}")
    except SmscodeError as e:
        print(f'API-Fehler: {e}')
    except TimeoutError as e:
        print(f'Timeout: {e}')

cURL (für schnelle Tests und Shell-Skripte)

#!/bin/bash
# Guthaben prüfen
curl -s https://api.smscode.gg/v1/balance \
  -H "Authorization: Bearer $SMSCODE_API_TOKEN" | jq .

# Länder abfragen
curl -s https://api.smscode.gg/v1/catalog/countries \
  -H "Authorization: Bearer $SMSCODE_API_TOKEN" | jq '.data[] | {id, name, code}'

# Nummer buchen (USA, WhatsApp)
ORDER=$(curl -s -X POST https://api.smscode.gg/v1/orders \
  -H "Authorization: Bearer $SMSCODE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"country_id": 1, "service_id": "wa"}')

echo $ORDER | jq .
ORDER_ID=$(echo $ORDER | jq -r '.data.order_id')
PHONE=$(echo $ORDER | jq -r '.data.phone_number')
echo "Nummer: $PHONE (Order: $ORDER_ID)"

# Status pollen (10x, alle 5 Sekunden)
for i in $(seq 1 10); do
  sleep 5
  STATUS=$(curl -s "https://api.smscode.gg/v1/orders/$ORDER_ID" \
    -H "Authorization: Bearer $SMSCODE_API_TOKEN")
  echo "Status: $(echo $STATUS | jq -r '.data.status')"
  if [ "$(echo $STATUS | jq -r '.data.status')" = "completed" ]; then
    echo "Code: $(echo $STATUS | jq -r '.data.sms_code')"
    break
  fi
done

# Stornieren (falls kein Code)
curl -s -X DELETE "https://api.smscode.gg/v1/orders/$ORDER_ID" \
  -H "Authorization: Bearer $SMSCODE_API_TOKEN" | jq .

TypeScript-Typdefinitionen

Für TypeScript-Projekte empfehlen sich explizite Typdefinitionen:

interface ApiResponse<T> {
  success: boolean;
  data?: T;
  error?: {
    code: string;
    message: string;
    details?: unknown;
  };
}

interface Order {
  order_id: string;
  phone_number: string;
  status: 'waiting' | 'completed' | 'cancelled' | 'expired';
  sms_code?: string;
  sms_text?: string;
  expires_at: string;
  received_at?: string;
}

interface Balance {
  balance: number;
  currency: string;
}

interface Country {
  id: number;
  name: string;
  code: string;
}

interface Service {
  id: string;
  name: string;
  price: number;
  available: boolean;
}

Polling-Strategie und Best Practices

Der SMS-Empfang ist grundsätzlich asynchron — nach dem Buchen der Nummer muss der Status periodisch abgefragt werden. Dabei sind mehrere Aspekte zu beachten:

Optimales Polling-Intervall: 3–5 Sekunden zwischen den Abfragen ist ein guter Ausgangspunkt. Kürzere Intervalle (< 2 Sekunden) führen zu unnötigem Traffic und können Rate Limits auslösen. Längere Intervalle (> 10 Sekunden) verzögern den Prozess unnötig — die meisten SMS kommen innerhalb von 10–60 Sekunden an.

Maximale Anzahl von Versuchen: Abhängig vom Zeitlimit der Bestellung und dem eigenen Timeout-Ziel. Bei einer 15-minütigen Bestelllaufzeit und 5-Sekunden-Intervallen kann man 180 Versuche einplanen. Praxisempfehlung: 40–60 Versuche (entspricht 3–5 Minuten), dann stornieren.

Exponentielles Backoff bei Netzwerkfehlern: Bei 5xx-Antworten oder Netzwerkproblemen sollte ein exponentielles Backoff implementiert werden, damit die API bei vorübergehenden Problemen nicht mit Anfragen überflutet wird:

async function withRetry(fn, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (err) {
      if (attempt === maxRetries - 1) throw err;
      const delay = Math.pow(2, attempt) * 1000 + Math.random() * 500;
      await sleep(delay);
    }
  }
}

// Polling mit Retry
async function pollWithRetry(orderId) {
  return withRetry(() => fetch(`${BASE_URL}/orders/${orderId}`, { headers }));
}

Aktives Stornieren bei eigenem Timeout: Wenn das eigene Timeout überschritten wird, die Bestellung immer aktiv stornieren — andernfalls verfällt das Guthaben automatisch am Ende der Bestelllaufzeit, ohne Erstattung. Dieser Schritt wird in Produktionscode oft vergessen.

Idempotenz der Bestellungen: Jede Bestellung hat eine eindeutige order_id. Falls eine Netzwerkanfrage während der Buchung unterbrochen wird, kann nicht sicher sein, ob die Bestellung erstellt wurde. Implementiere eine Prüfung offener Bestellungen beim Start, bevor neue erstellt werden.

Fehlerbehandlung

Die API gibt konsistente Fehlerantworten in standardisiertem Format zurück:

{
  "success": false,
  "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "Nicht genügend Guthaben für diese Bestellung",
    "details": {
      "required": 0.05,
      "available": 0.02
    }
  }
}

Häufige Fehlercodes und empfohlene Behandlung:

CodeHTTP-StatusBedeutungEmpfohlene Behandlung
UNAUTHORIZED401Ungültiger oder fehlender API-TokenToken prüfen, kein Retry
INSUFFICIENT_BALANCE402Zu wenig GuthabenGuthaben aufladen, dann neu versuchen
SERVICE_UNAVAILABLE503Dienst temporär nicht verfügbarAnderen Tier wählen, nach 60s retry
ORDER_NOT_FOUND404Order-ID existiert nichtOrder-ID prüfen, kein Retry
CANCEL_NOT_ALLOWED400Stornierung außerhalb der FristAkzeptieren — Bestellung läuft weiter
RATE_LIMITED429Zu viele AnfragenRetry-After-Header auslesen, warten
INTERNAL_ERROR500Interner ServerfehlerNach Backoff wiederholen

HTTP-Statuscodes werden korrekt und konsistent verwendet. Code 200 bedeutet immer Erfolg; 4xx-Fehler sind immer auf Client-Probleme zurückzuführen und erfordern Anpassungen am Code oder den Eingaben; 5xx-Fehler sind serverseitig und rechtfertigen Retries.

Integration in CI/CD-Pipelines

Für Entwickler, die Registrierungs-Flows in automatisierten Tests abdecken, ist die API-Integration in CI/CD-Pipelines besonders wertvoll. Damit können echte SMS-Verifizierungen als Teil des Test-Suites ausgeführt werden — nicht mit Mock-Daten, sondern mit real zugestellten Codes.

GitHub Actions Beispiel:

name: E2E Tests mit SMS-Verifizierung

on: [push, pull_request]

jobs:
  e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Node.js einrichten
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Abhängigkeiten installieren
        run: npm ci

      - name: Playwright installieren
        run: npx playwright install --with-deps

      - name: E2E-Tests ausführen
        env:
          SMSCODE_API_TOKEN: ${{ secrets.SMSCODE_API_TOKEN }}
          BASE_URL: ${{ vars.TEST_BASE_URL }}
        run: npx playwright test

Der API-Token wird als verschlüsseltes Secret in GitHub Actions hinterlegt — niemals als Klartext in workflow.yml oder im Repository.

GitLab CI Beispiel:

e2e_with_sms:
  stage: test
  image: mcr.microsoft.com/playwright:v1.41.0-jammy
  script:
    - npm ci
    - npx playwright test
  variables:
    SMSCODE_API_TOKEN: $SMSCODE_API_TOKEN
  only:
    - main
    - merge_requests

Playwright-Testbeispiel (TypeScript):

import { test, expect } from '@playwright/test';

async function getSmsCode(countryId: number, serviceId: string): Promise<{ number: string; code: string }> {
  const token = process.env.SMSCODE_API_TOKEN!;
  const baseUrl = 'https://api.smscode.gg/v1';
  const headers = {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  };

  const orderRes = await fetch(`${baseUrl}/orders`, {
    method: 'POST',
    headers,
    body: JSON.stringify({ country_id: countryId, service_id: serviceId })
  });
  const order = await orderRes.json();
  const { order_id, phone_number } = order.data;

  for (let i = 0; i < 30; i++) {
    await new Promise(r => setTimeout(r, 5000));
    const statusRes = await fetch(`${baseUrl}/orders/${order_id}`, { headers });
    const status = await statusRes.json();
    if (status.data.status === 'completed') {
      return { number: phone_number, code: status.data.sms_code };
    }
  }
  throw new Error('SMS-Code nicht empfangen');
}

test('Registrierung mit SMS-Verifizierung', async ({ page }) => {
  const { number, code } = await getSmsCode(1, 'myapp');

  await page.goto('/register');
  await page.fill('[name="phone"]', number);
  await page.click('button[type="submit"]');

  // Warte auf SMS-Eingabefeld
  await page.waitForSelector('[name="sms_code"]');
  await page.fill('[name="sms_code"]', code);
  await page.click('[data-testid="verify-button"]');

  await expect(page).toHaveURL('/dashboard');
});

Rate Limits

Die API hat Rate Limits, um Missbrauch zu verhindern und faire Kapazitätsverteilung zu gewährleisten. Aktuelle Limits sind in der API-Dokumentation beschrieben. Bei normalem Nutzungsverhalten werden diese nicht erreicht.

Falls Rate Limits greifen, antwortet die API mit 429 Too Many Requests und einem Retry-After-Header:

HTTP/1.1 429 Too Many Requests
Retry-After: 15
Content-Type: application/json

{"success": false, "error": {"code": "RATE_LIMITED", "message": "Zu viele Anfragen"}}

Die korrekte Behandlung:

async function apiRequest(url, options = {}) {
  const res = await fetch(url, { ...options, headers });

  if (res.status === 429) {
    const retryAfter = parseInt(res.headers.get('Retry-After') || '10');
    await sleep(retryAfter * 1000);
    return apiRequest(url, options);  // Einmaliger Retry
  }

  return res.json();
}

Sicherheits-Best-Practices für die API

Token-Isolation: Nutze separate API-Tokens für verschiedene Anwendungen und Umgebungen. Ein Token für Produktion, ein anderer für CI/CD, ein dritter für manuelle Tests. Bei Kompromittierung eines Tokens sind nur die Ressourcen dieser einen Anwendung betroffen.

Token-Rotation: Rotiere API-Tokens regelmäßig, besonders nach dem Ausscheiden von Teammitgliedern, die Zugang hatten, oder nach einem Sicherheitsvorfall. Im SMSCode-Dashboard kann jederzeit ein neuer Token generiert werden; der alte wird sofort invalidiert.

Logging mit Bedacht: Logge API-Antworten niemals vollständig in persistenten, dauerhaften Logs. SMS-Codes sind einmalige Sicherheitscodes — ein Log davon ist ein Sicherheitsrisiko. Logge Order-IDs und Status, aber nicht den sms_code-Wert selbst.

HTTPS immer: Alle API-Anfragen müssen über HTTPS laufen. Die SMSCode API ist ausschließlich über HTTPS erreichbar und lehnt HTTP-Verbindungen ab.

Token nie im Frontend: API-Token dürfen niemals in Browser-JavaScript, React-Apps, mobilen Apps oder anderen client-seitigen Anwendungen verwendet werden. Der Token hat Vollzugang zum Konto und würde in Client-Code für jeden Nutzer sichtbar sein. Immer einen Backend-Proxy verwenden:

Browser → eigenes Backend (mit Token) → SMSCode API

Guthaben-Monitoring: Bei automatisierten Prozessen regelmäßig den Kontostand prüfen und Alerts einrichten, bevor das Guthaben auf null fällt. Eine leere Balance führt zu Fehlern in Produktionsprozessen:

async function checkBalance(minimumBalance = 1.0) {
  const res = await fetch(`${BASE_URL}/balance`, { headers });
  const data = await res.json();
  const balance = data.data.balance;

  if (balance < minimumBalance) {
    // Alert senden (z. B. via Slack, PagerDuty, E-Mail)
    throw new Error(`Niedriger Kontostand: $${balance} < $${minimumBalance}`);
  }

  return balance;
}

Praktische Anwendungsfälle

Automatisierte E2E-Tests: Registrierungs-Flows mit echter SMS-Verifizierung in Playwright-, Cypress- oder Selenium-Tests abdecken. Damit wird der komplette Registrierungsweg — inklusive SMS-Bestätigung — ohne manuelle Eingriffe und ohne Mocking reproduzierbar getestet.

Konto-Provisioning: Bei der automatisierten Einrichtung neuer Unternehmenskonten auf Plattformen wie eBay, LinkedIn oder anderen B2B-Diensten. Der gesamte Registrierungsflow — Formular ausfüllen, Nummer eingeben, Code abfragen, Konto aktivieren — läuft automatisch ab.

Multi-Konto-Management: Verschiedene Konten auf Plattformen mit jeweils eigenen Nummern ausstatten, ohne jede Nummer manuell zu buchen. Besonders nützlich bei der Verwaltung vieler Konten für verschiedene Kunden.

Interne Entwicklertools: Eigene interne Portale bauen, die Mitarbeitern die Nummernbeschaffung über ein zentrales Interface ermöglichen, ohne dass jeder Mitarbeiter direkten Zugang zum SMSCode-Dashboard braucht. Die SMSCode API wird dabei vom Backend des internen Tools angesprochen.

Load-Tests und Performance-Tests: Große Mengen Registrierungen simulieren, um Load-Verhalten der eigenen Plattform zu testen. Jede simulierte Registrierung braucht eine eigene Nummer — die API liefert diese programmatisch.

Monitoring und Alerting: Regelmäßige synthetische Checks, die den eigenen Registrierungsflow inklusive SMS testen, und bei Problemen Alerts auslösen. Damit werden Ausfälle im SMS-Versand der eigenen Plattform frühzeitig erkannt.

Erste Schritte

  1. Kostenloses Konto erstellen
  2. Guthaben aufladen — mindestens 1–2 € für erste Tests genügen (siehe Zahlungsmethoden)
  3. API-Token im Dashboard generieren
  4. Ersten API-Call mit cURL testen: curl -H "Authorization: Bearer TOKEN" https://api.smscode.gg/v1/balance
  5. Einfaches Skript in der bevorzugten Sprache schreiben (die Beispiele oben als Ausgangspunkt nutzen)
  6. In die eigene Anwendung oder CI/CD-Pipeline integrieren

Die vollständige API-Referenz mit allen Endpunkten, Parametern, Antwortformaten und Fehlercodes ist in der Entwickler-Dokumentation zu finden.

Weitere Anleitungen


FAQ

Brauche ich Programmierkenntnisse, um die SMSCode API zu nutzen?

Grundlegende Kenntnisse in einer Programmiersprache (JavaScript, Python, PHP, Ruby, Go etc.) sind hilfreich, aber nicht zwingend erforderlich für einfachere Anwendungsfälle. Shell-Skripte mit cURL reichen für viele Automationsszenarien aus. Die Beispiele in diesem Guide sind so aufgebaut, dass sie auch ohne tiefe Programmierkenntnisse angepasst werden können. Für komplexe Integrationen in bestehende Systeme sind Entwicklerkenntnisse empfehlenswert.

Gibt es einen Sandbox- oder Testmodus?

Aktuell gibt es keinen separaten Sandbox-Modus. Tests können direkt mit dem produktiven System durchgeführt werden — Kosten entstehen nur bei erfolgreich abgeschlossenen Bestellungen (empfangene SMS). Stornierungen innerhalb der Stornofrist werden vollständig erstattet. Für Entwicklertests reichen wenige Euro Guthaben für viele Testläufe.

Welche Programmiersprachen werden unterstützt?

Da es sich um eine Standard-REST-API mit JSON handelt, ist sie mit jeder Programmiersprache nutzbar, die HTTP-Anfragen senden kann — also praktisch jede moderne Sprache: JavaScript/TypeScript, Python, PHP, Ruby, Go, Java, C#, Rust, Swift, Kotlin und viele mehr. Offizielle Codebeispiele gibt es für JavaScript und Python. Die API-Dokumentation enthält weitere Beispiele.

Wie sicher ist der API-Token?

Der API-Token gewährt vollen Zugang zu allen API-Funktionen des Kontos — er ist äquivalent zu einem Passwort. Er sollte ausschließlich serverseitig verwendet werden, niemals in Browser-Code oder öffentlichen Repositories. Bei Verdacht auf Kompromittierung kann im Dashboard sofort ein neuer Token generiert und der alte invalidiert werden. Token-Rotation alle 30–90 Tage ist empfehlenswert.

Was passiert bei einem Netzwerkfehler während einer Bestellung?

Falls die Verbindung während der Buchungsanfrage unterbrochen wird, bleibt die Bestellung im System aktiv — sofern sie vor dem Timeout vollständig übertragen wurde. Bei erneutem Verbindungsaufbau kann der Status über die Order-ID abgefragt werden. Falls die Order-ID nicht mehr bekannt ist, können alle offenen Bestellungen über den entsprechenden Listenendpunkt abgerufen werden. Eine robuste Fehlerbehandlung mit idempotenten Operationen ist für Produktionscode unerlässlich.

Kann ich die API für mehrere Projekte gleichzeitig nutzen?

Ja. Ein API-Token kann von mehreren Anwendungen gleichzeitig verwendet werden — alle greifen auf dasselbe Guthaben und dieselben Ressourcen zu. Für bessere Kontrolle, Sicherheitsisolation und einfachere Fehlerdiagnose empfiehlt sich jedoch, separate Tokens für verschiedene Projekte und Umgebungen zu erstellen.

Was ist der Unterschied zwischen der API und dem Dashboard?

Das Dashboard ist die grafische Benutzeroberfläche für manuelle, gelegentliche Nutzung — man klickt, kauft und liest Codes manuell. Die API ist die programmatische Schnittstelle für automatisierte Nutzung — sie wird von Skripten, Anwendungen und CI/CD-Systemen angesteuert. Beide greifen auf dasselbe Konto und dasselbe Guthaben zu. Das Dashboard eignet sich für Einzelverwendung und Tests; die API für Automatisierung, Skalierung und Integrationen.

Wie gehe ich mit dem Fall um, dass eine Nummer von der Zielplattform abgelehnt wird?

Wenn eine Plattform die Nummer ablehnt (häufig bei VoIP-Erkennung oder gesperrten Nummernbereichen), sollte die aktuelle Bestellung storniert werden (Guthaben wird erstattet, sofern noch innerhalb der Stornofrist) und eine neue Nummer aus einem anderen Land oder Tier gebucht werden. Im Code empfiehlt sich eine Retry-Logik mit alternativer Länderwahl: erst USA versuchen, dann UK, dann Deutschland — oder basierend auf aktuellen Verfügbarkeitsdaten aus dem Katalog-Endpunkt entscheiden.

Bereit, SMSCode auszuprobieren?

Erstellen Sie ein Konto und erhalten Sie Ihre erste virtuelle Nummer in unter zwei Minuten.

Jetzt starten →