Vio eSIM API-Referenz
Zwei REST-Oberflächen auf demselben Backend: die kundenseitige API, die die Web-App und unsere iOS/Android-Apps antreibt, und eine separate, per API-Schlüssel authentifizierte Partner-API zum programmatischen Weiterverkauf von Vio eSIM.
https://vioesim.com/api/v1https://vioesim.com/api/public/v1Authentifizierung der mobilen App
Die Web-App und die nativen Apps teilen sich ein Sitzungssystem — eine native App trägt das Token einfach selbst, statt sich auf einen Cookie-Speicher zu verlassen.
Registrieren oder anmelden. Beide Endpunkte geben ein token-Feld neben dem Benutzerobjekt zurück (sowie einen Set-Cookie-Header, den die Web-App stattdessen verwendet). Speichern Sie token im Schlüsselbund (iOS) oder im Keystore-gestützten Speicher (Android).
Zurücksenden bei jeder Anfrage:
Authorization: Bearer <token>Token-Lebensdauer: 30 Tage ab Ausstellung, oder bis /api/v1/auth/logout aufgerufen wird. Es gibt keinen Refresh-Token-Schritt — ein bald ablaufendes Token wird einfach ersetzt, indem der Nutzer sich erneut anmeldet.
Authentifizierung der Partner-API
Für externe Unternehmen, die Vio eSIM über ihre eigene Website oder App weiterverkaufen. Ein Partner ist ein normales Vio-eSIM-Konto: Erzeugen Sie einen Schlüssel unter Dashboard → API-Schlüssel (einmalige Anzeige — speichern Sie ihn, er kann nicht erneut angezeigt werden) und senden Sie ihn dann bei jeder Anfrage:
Authorization: Bearer vio_live_sk_...
# or
X-API-Key: vio_live_sk_...Das Erzeugen eines neuen Schlüssels macht den vorherigen sofort ungültig.
Schnellstart — Partner-API
Katalog durchsuchen und eine eSIM in zwei Aufrufen kaufen:
curl https://vioesim.com/api/public/v1/destinations \
-H "Authorization: Bearer vio_live_sk_..."
curl -X POST https://vioesim.com/api/public/v1/orders \
-H "Authorization: Bearer vio_live_sk_..." \
-H "Content-Type: application/json" \
-d '{ "planId": "cus...", "quantity": 1 }'Fehler & Ratenbegrenzung
Die Mobil-/Web-API gibt { "error": "Nachricht" } zurück (derzeit türkischsprachige Nachrichten). Die Partner-API gibt eine strukturierte Form zurück, damit Sie anhand von code verzweigen können:
{ "error": { "code": "INSUFFICIENT_BALANCE", "message": "Insufficient wallet balance." } }| Status | Bedeutung |
|---|---|
| 401 | Fehlendes/ungültiges/abgelaufenes Token oder API-Schlüssel |
| 402 | Nur Partner-API — Wallet-Guthaben zu niedrig |
| 404 | Ressource nicht gefunden oder nicht im Besitz des Aufrufers |
| 409 | Widersprüchlicher Zustand (z. B. Löschen eines Kontos mit positivem Guthaben) |
| 429 | Ratenbegrenzung erreicht — siehe Retry-After-Header (Sekunden) |
| 502 | Zahlung erfasst, aber eSIM-Bereitstellung fehlgeschlagen — Zahlung nicht wiederholen |
Ratenbegrenzung (Partner-API): 120 Anfragen/Min. pro Schlüssel bei Lesevorgängen, 30 Anfragen/Min. bei POST /orders.
Mobil / Web-API
Authentifizierung
Registrieren
Erstellt ein Konto und eine aktive Sitzung.
{
"firstName": "Ada",
"lastName": "Lovelace",
"email": "[email protected]",
"password": "min 8 chars"
}{
"success": true,
"user": {
"id", "firstName", "lastName", "fullName", "email",
"emailVerified", "walletBalance", "currency", "locale", "createdAt"
},
"token": "..."
}Anmelden
Body: { email, password }. Gleiche Antwortform wie Registrieren. 401 bei falschen Anmeldedaten, 403 wenn das Konto gesperrt ist.
Abmelden
Kein Body. Löscht die Sitzung serverseitig — rufen Sie dies bei einer echten Abmeldung auf, nicht nur beim lokalen Verwerfen des Tokens, damit ein gestohlenes Token nicht weiter funktioniert.
Aktueller Benutzer
Gibt { "user": null } zurück (nie einen Fehler), wenn abgemeldet — nutzen Sie dies beim App-Start, um zu entscheiden, ob der Login-Bildschirm angezeigt wird.
Passwort vergessen
Body: { email, locale }. Gibt immer { success: true } zurück, unabhängig davon, ob die Adresse existiert, damit sie nicht zum Enumerieren von Konten genutzt werden kann. Sendet eine E-Mail mit Reset-Link/Token (1 Stunde gültig).
Passwort zurücksetzen
Body: { token, newPassword }. GET mit ?token= prüft die Gültigkeit, bevor das Formular angezeigt wird ({ "valid": true|false }).
Passwort ändern
Body: { currentPassword, newPassword }. currentPassword ist erforderlich, außer das Konto hat noch kein Passwort (z. B. Social Login).
Konto
Profil aktualisieren
Senden Sie nur die Felder, die Sie ändern möchten.
| Field | Notes |
|---|---|
| firstName, lastName | optional · Text |
| preferredCurrency | optional · einer von USD EUR GBP TRY |
| locale | optional · 2-Buchstaben-Code, z. B. de |
{ "success": true, "user": { ...same shape as /auth/me } }Avatar aktualisieren
Body: { "avatarUrl": "data:image/..." } — ein Base64-Data-URI, max. ~1,5 MB.
API-Schlüssel erzeugen
Erzeugt einen neuen Partner-API-Schlüssel für dieses Konto und ersetzt einen vorherigen. Der rohe Schlüssel wird nur einmal in dieser Antwort angezeigt — danach ist nur noch sein Präfix abrufbar.
{
"success": true,
"key": "vio_live_sk_...",
"apiKeyPrefix": "vio_live_sk_ab12…9f8e",
"apiKeyGeneratedAt": "2026-08-22T17:00:00.781Z"
}Konto löschen
Erforderlich für die App-Store-Prüfung (Apps mit Kontoerstellung müssen die Löschung in der App anbieten). Anonymisiert das Konto (E-Mail wird verschleiert und für eine erneute Registrierung freigegeben, Name/Avatar/Passwort werden gelöscht), statt Zeilen endgültig zu löschen, damit vergangene Bestellungen für Steuer-/Buchhaltungszwecke erhalten bleiben. Löscht alle Sitzungen und registrierten Push-Geräte des Nutzers.
Katalog
Reiseziele auflisten
Länder und Regionen mit aktiven Tarifen, bepreist und UI-formatiert (dies ruft auch der Storefront selbst auf). Optional ?filter=popular|regional|global|<Suchtext>.
Reiseziel-Detail
Vollständige Details (Beschreibung, Tarife) für ein Land nach ISO-Code, z. B. /api/v1/destinations/jp.
Käufe
Kasse
Kauft einen Tarif direkt (statt zuerst Guthaben in die Wallet einzuzahlen).
| Field | Notes |
|---|---|
| planId* | |
| quantity | optional · 1–10, Standard 1 |
| paymentMethod* | wallet | stripe | crypto |
| successUrl, cancelUrl | optional · für stripe/crypto-Weiterleitungen. Verwenden Sie einen Universal-/App-Link statt einer reinen Web-URL, damit die Weiterleitung die App wieder öffnet. |
{ "success": true, "orderId": "..." }{ "success": true, "orderId": "...", "url": "https://checkout.stripe.com/..." }Stripe-Wallet-Aufladung
Lädt die Wallet per Karte auf — ein separater Ablauf zur Kasse. Body: { amount (Cent, min. 200), currency, successUrl, cancelUrl }. Gibt { sessionId, url } zurück.
Krypto-Wallet-Aufladung
Body: { amount (Dezimal-String, min. $2), currency, url_return }. Gibt das Cryptomus-Rechnungsobjekt inklusive url zurück.
Bestellungen auflisten
Alle Bestellungen des Aufrufers, neueste zuerst.
Bestell-Detail
Eine Bestellung inklusive esimIds — vollständige eSIM-Details (QR, Aktivierungscode) über GET /api/v1/user/esims abrufen und per id zuordnen.
Meine eSIMs
Jede eSIM des Aufrufers: iccid, activationCode, qrCodeUrl, smdpAddress, status, dataUsage/totalVolume (MB), activatedAt, expiresAt. Dies speist den Bildschirm "Meine eSIMs" und die QR-Anzeige.
Wallet-Verlauf
Einzahlungs-/Auszahlungs-/Kauf-/Rückerstattungsverlauf für das in /auth/me angezeigte Wallet-Guthaben.
Support
Tickets auflisten
Die Tickets des Aufrufers mit vollständigen Nachrichtenverläufen, neueste zuerst.
Neues Ticket
Body: { subject, category, message } (category optional).
Auf Ticket antworten
Body: { message }. Eine Antwort auf ein RESOLVED/CLOSED-Ticket öffnet es automatisch wieder.
Push-Benachrichtigungsgeräte
Registriert nur Gerätetoken — für den tatsächlichen Versand sind APNs/FCM-Anmeldedaten nötig, siehe Hinweis unten.
Gerät registrieren
Nach Erhalt eines APNs- oder FCM-Tokens aufrufen. Body: { platform: "IOS"|"ANDROID", pushToken, appVersion }. Führt ein Upsert nach Token durch, ein erneuter Aufruf bei jedem App-Start ist also unbedenklich und empfohlen (Token können sich ändern).
Geräteregistrierung aufheben
Body: { pushToken }. Bei der Abmeldung aufrufen, damit ein geteiltes/zurückgesetztes Gerät keine Benachrichtigungen eines anderen Nutzers mehr erhält.
Partner-API
Für alles Folgende ist der oben beschriebene API-Schlüssel-Header erforderlich — hier gilt kein Sitzungscookie.
Katalog
Reiseziele auflisten
Vollständiger Katalog in einer partnerorientierten Form (nicht der UI-Form des Storefronts).
{
"countries": [
{
"code": "JP",
"name": { "en": "Japan", "tr": "Japonya", "...": "..." },
"flagEmoji": "🇯🇵",
"continent": "Asia",
"plans": [
{ "id": "cus...", "dataAmountMb": 1024, "durationDays": 7, "priceUsd": 4.25, "isTopUp": false }
]
}
],
"regions": [ { "code": "...", "name": {...}, "countryCount": 15, "plans": [...] } ]
}Reiseziel-Detail
Ein Land nach ISO-Code (z. B. /api/public/v1/destinations/JP), gleiche Tarifform wie oben.
Bestellungen
Bestellung erstellen
Kauft einen Tarif gegen das Wallet-Guthaben des Aufrufers und stellt die eSIM synchron bereit — die Antwort enthält bereits die QR-/Aktivierungsdaten, bereit zur Übergabe an Ihren Endkunden. Kein Polling im Regelfall nötig.
{ "planId": "cus...", "quantity": 1 }{
"id": "...", "orderNumber": "VIO-API-...", "status": "COMPLETED", "amountUsd": 4.25,
"esims": [
{ "id": "...", "iccid": "...", "activationCode": "...",
"qrCodeUrl": "https://...", "smdpAddress": "...", "status": "PENDING" }
]
}Bestellungen auflisten
Optional ?limit= (Standard 25, max. 100). Zusammenfassende Form — für eSIM-Daten den Detail-Endpunkt nutzen.
Bestell-Detail
Vollständiges Bestell-Detail inklusive QR-/Aktivierungsdaten und Live-Nutzung (dataUsageMb / totalVolumeMb) jeder eSIM — pollen Sie dies, um Ihrem Kunden das verbleibende Datenvolumen zu zeigen.
Wallet
Wallet-Guthaben
Vor einer größeren Bestellcharge abfragen oder sich bei niedrigem Guthaben benachrichtigen lassen.
{ "balanceUsd": 128.40, "currency": "USD" }Was noch nicht gebaut ist
Damit hier nichts als funktionierend vorausgesetzt wird, das es nicht ist.
Zustellung von Push-Benachrichtigungen
Die Token-Registrierung funktioniert; der tatsächliche Versand benötigt APNs/FCM-Anmeldedaten.
Partnerspezifische Preisgestaltung
Die Partner-API berechnet derzeit denselben Einzelhandelspreis wie der Storefront. Großhandels-/Sonderpreise würden eine Schemaänderung plus eine Geschäftsentscheidung erfordern.
Refresh-Token
Sitzungen sind langlebige (30 Tage) flache Token, keine Paare aus kurzlebigem Access- und Refresh-Token. Vorerst ausreichend; für eine strengere Sicherheitslage später überdenken.
Native Stripe-Zahlungsoberfläche
Die Stripe-Integration nutzt gehostetes Checkout (Weiterleitung/WebView). Eine native Karteneingabe würde stattdessen PaymentIntents + das Stripe-SDK verwenden.
Webhooks für Partner
Partner müssen GET /orders/:id für den Status abfragen; es gibt noch keinen ausgehenden Webhook (z. B. "eSIM aktiviert").
