Vio eSIM
REST-API · v1

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.

Mobil / Web-API
https://vioesim.com/api/v1
Partner-API
https://vioesim.com/api/public/v1

Authentifizierung 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.

Eine Sitzung eines gesperrten, gebannten oder gelöschten Kontos funktioniert sofort nicht mehr — bei jeder Anfrage serverseitig geprüft, auch wenn das Token selbst noch nicht abgelaufen ist.

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.

Abrechnungsmodell: Partner-API-Bestellungen werden synchron gegen das Guthaben-Wallet des Kontos abgerechnet — keine Checkout-Weiterleitung, da dies ein Server-zu-Server-Aufruf ist. Laden Sie das Guthaben im Dashboard auf (Karte/Krypto), bevor Sie Bestellungen aufgeben; POST /orders gibt 402 zurück, wenn das Guthaben nicht ausreicht.

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." } }
StatusBedeutung
401Fehlendes/ungültiges/abgelaufenes Token oder API-Schlüssel
402Nur Partner-API — Wallet-Guthaben zu niedrig
404Ressource nicht gefunden oder nicht im Besitz des Aufrufers
409Widersprüchlicher Zustand (z. B. Löschen eines Kontos mit positivem Guthaben)
429Ratenbegrenzung erreicht — siehe Retry-After-Header (Sekunden)
502Zahlung 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

POST/api/v1/auth/registerKeine Authentifizierung

Registrieren

Erstellt ein Konto und eine aktive Sitzung.

Request body
{
  "firstName": "Ada",
  "lastName": "Lovelace",
  "email": "[email protected]",
  "password": "min 8 chars"
}
200 OK
{
  "success": true,
  "user": {
    "id", "firstName", "lastName", "fullName", "email",
    "emailVerified", "walletBalance", "currency", "locale", "createdAt"
  },
  "token": "..."
}
POST/api/v1/auth/loginKeine Authentifizierung

Anmelden

Body: { email, password }. Gleiche Antwortform wie Registrieren. 401 bei falschen Anmeldedaten, 403 wenn das Konto gesperrt ist.

POST/api/v1/auth/logoutSitzungstoken

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.

GET/api/v1/auth/meSitzungstoken · optional

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.

POST/api/v1/auth/forgot-passwordKeine Authentifizierung

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).

POST/api/v1/auth/reset-passwordKeine Authentifizierung

Passwort zurücksetzen

Body: { token, newPassword }. GET mit ?token= prüft die Gültigkeit, bevor das Formular angezeigt wird ({ "valid": true|false }).

POST/api/v1/auth/change-passwordSitzungstoken

Passwort ändern

Body: { currentPassword, newPassword }. currentPassword ist erforderlich, außer das Konto hat noch kein Passwort (z. B. Social Login).

Konto

PATCH/api/v1/user/profileSitzungstoken

Profil aktualisieren

Senden Sie nur die Felder, die Sie ändern möchten.

FieldNotes
firstName, lastNameoptional · Text
preferredCurrencyoptional · einer von USD EUR GBP TRY
localeoptional · 2-Buchstaben-Code, z. B. de
200 OK
{ "success": true, "user": { ...same shape as /auth/me } }
POST/api/v1/user/avatarSitzungstoken

Avatar aktualisieren

Body: { "avatarUrl": "data:image/..." } — ein Base64-Data-URI, max. ~1,5 MB.

POST/api/v1/user/api-key/generateSitzungstoken

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.

200 OK
{
  "success": true,
  "key": "vio_live_sk_...",
  "apiKeyPrefix": "vio_live_sk_ab12…9f8e",
  "apiKeyGeneratedAt": "2026-08-22T17:00:00.781Z"
}
DELETE/api/v1/user/accountSitzungstoken

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.

Gibt 409 zurück, wenn walletBalance > 0 — die App sollte den Nutzer bitten, zuerst abzuheben oder den Support zu kontaktieren, statt Guthaben stillschweigend verfallen zu lassen.

Katalog

GET/api/v1/destinationsKeine Authentifizierung

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>.

GET/api/v1/destinations/:codeKeine Authentifizierung

Reiseziel-Detail

Vollständige Details (Beschreibung, Tarife) für ein Land nach ISO-Code, z. B. /api/v1/destinations/jp.

Käufe

POST/api/v1/checkoutSitzungstoken

Kasse

Kauft einen Tarif direkt (statt zuerst Guthaben in die Wallet einzuzahlen).

FieldNotes
planId*
quantityoptional · 1–10, Standard 1
paymentMethod*wallet | stripe | crypto
successUrl, cancelUrloptional · für stripe/crypto-Weiterleitungen. Verwenden Sie einen Universal-/App-Link statt einer reinen Web-URL, damit die Weiterleitung die App wieder öffnet.
200 OK — wallet (synchronous)
{ "success": true, "orderId": "..." }
200 OK — stripe / crypto (redirect required)
{ "success": true, "orderId": "...", "url": "https://checkout.stripe.com/..." }
Öffnen Sie url in einem In-App-Browser (SFSafariViewController / Chrome Custom Tabs), nicht in einer reinen WebView — sowohl Stripe als auch Cryptomus erwarten einen echten Browserkontext.
POST/api/v1/payments/stripe/create-sessionSitzungstoken

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.

POST/api/v1/payments/cryptomus/create-invoiceSitzungstoken

Krypto-Wallet-Aufladung

Body: { amount (Dezimal-String, min. $2), currency, url_return }. Gibt das Cryptomus-Rechnungsobjekt inklusive url zurück.

GET/api/v1/user/ordersSitzungstoken

Bestellungen auflisten

Alle Bestellungen des Aufrufers, neueste zuerst.

GET/api/v1/user/orders/:idSitzungstoken

Bestell-Detail

Eine Bestellung inklusive esimIds — vollständige eSIM-Details (QR, Aktivierungscode) über GET /api/v1/user/esims abrufen und per id zuordnen.

GET/api/v1/user/esimsSitzungstoken

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.

GET/api/v1/user/wallet/transactionsSitzungstoken

Wallet-Verlauf

Einzahlungs-/Auszahlungs-/Kauf-/Rückerstattungsverlauf für das in /auth/me angezeigte Wallet-Guthaben.

Support

GET/api/v1/support/ticketsSitzungstoken

Tickets auflisten

Die Tickets des Aufrufers mit vollständigen Nachrichtenverläufen, neueste zuerst.

POST/api/v1/support/ticketsSitzungstoken

Neues Ticket

Body: { subject, category, message } (category optional).

POST/api/v1/support/tickets/:id/messagesSitzungstoken

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.

POST/api/v1/user/push-devicesSitzungstoken

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).

DELETE/api/v1/user/push-devicesSitzungstoken

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

GET/api/public/v1/destinationsAPI-Schlüssel

Reiseziele auflisten

Vollständiger Katalog in einer partnerorientierten Form (nicht der UI-Form des Storefronts).

200 OK
{
  "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": [...] } ]
}
GET/api/public/v1/destinations/:codeAPI-Schlüssel

Reiseziel-Detail

Ein Land nach ISO-Code (z. B. /api/public/v1/destinations/JP), gleiche Tarifform wie oben.

Bestellungen

POST/api/public/v1/ordersAPI-Schlüssel

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.

Request body
{ "planId": "cus...", "quantity": 1 }
201 Created
{
  "id": "...", "orderNumber": "VIO-API-...", "status": "COMPLETED", "amountUsd": 4.25,
  "esims": [
    { "id": "...", "iccid": "...", "activationCode": "...",
      "qrCodeUrl": "https://...", "smdpAddress": "...", "status": "PENDING" }
  ]
}
Fehlerfälle: 402 INSUFFICIENT_BALANCE (zuerst aufladen), 404 PLAN_NOT_FOUND, oder 502 FULFILLMENT_FAILED (belastet, aber der Anbieter konnte die eSIM nicht ausstellen — die Bestell-ID ist enthalten, der Support wird automatisch benachrichtigt; pollen Sie GET /orders/:id, statt erneut zu belasten).
GET/api/public/v1/ordersAPI-Schlüssel

Bestellungen auflisten

Optional ?limit= (Standard 25, max. 100). Zusammenfassende Form — für eSIM-Daten den Detail-Endpunkt nutzen.

GET/api/public/v1/orders/:idAPI-Schlüssel

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

GET/api/public/v1/walletAPI-Schlüssel

Wallet-Guthaben

Vor einer größeren Bestellcharge abfragen oder sich bei niedrigem Guthaben benachrichtigen lassen.

200 OK
{ "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").

Vio eSIM API-Referenz & Partner-API-Dokumentation