Vio eSIM API リファレンス
同じバックエンド上の2つのREST表面:ウェブアプリとiOS/Androidアプリを支える顧客向けAPIと、Vio eSIMをプログラムで再販するための、APIキーで認証される別個のパートナーAPI。
https://vioesim.com/api/v1https://vioesim.com/api/public/v1モバイルアプリの認証
ウェブアプリとネイティブアプリは同一のセッションシステムを共有します — ネイティブアプリはCookieストアに頼らず、トークン自体を保持します。
登録またはログイン。 どちらのエンドポイントもユーザーオブジェクトとともにtokenフィールドを返します(ウェブアプリが代わりに使用するSet-Cookieヘッダーも含む)。tokenはKeychain(iOS)またはKeystoreに裏付けられたストア(Android)に保存してください。
毎回のリクエストで それを送り返します:
Authorization: Bearer <token>トークンの有効期限: 発行から30日間、または /api/v1/auth/logout が呼び出されるまで。リフレッシュトークンの手順はありません — 期限が近いトークンは、ユーザーに再度ログインしてもらうことで単純に置き換えられます。
パートナーAPIの認証
自社サイトやアプリを通じてVio eSIMを再販する外部企業向けです。パートナーは通常のVio eSIMアカウントです:以下からキーを生成してください ダッシュボード → APIキー (一度だけ表示されます — 保存してください、再表示はできません)。その後、毎回のリクエストで送信します:
Authorization: Bearer vio_live_sk_...
# or
X-API-Key: vio_live_sk_...新しいキーを生成すると、以前のキーは即座に無効になります。
クイックスタート — パートナーAPI
カタログを閲覧し、2回の呼び出しでeSIMを購入します:
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 }'エラーとレート制限
モバイル/ウェブAPIは { "error": "メッセージ" } を返します(現在はトルコ語のメッセージ)。パートナーAPIは code で分岐できるよう構造化された形式を返します:
{ "error": { "code": "INSUFFICIENT_BALANCE", "message": "Insufficient wallet balance." } }| ステータス | 意味 |
|---|---|
| 401 | トークンまたはAPIキーが欠落・無効・期限切れ |
| 402 | パートナーAPIのみ — ウォレット残高が不足 |
| 404 | リソースが見つからない、または呼び出し元の所有ではない |
| 409 | 競合状態(例:残高が0でないアカウントの削除) |
| 429 | レート制限に到達 — Retry-Afterヘッダー(秒)を参照 |
| 502 | 決済は完了したがeSIMのプロビジョニングに失敗 — 決済を再試行しないでください |
レート制限(パートナーAPI): 読み取りはキーごとに120リクエスト/分、POST /orders は30リクエスト/分。
モバイル / ウェブAPI
認証
登録
アカウントとアクティブなセッションを作成します。
{
"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": "..."
}ログイン
ボディ:{ email, password }。登録と同じレスポンス形式。認証情報が誤っている場合は401、アカウントが停止中の場合は403。
ログアウト
ボディなし。サーバー側でセッションを削除します — 盗まれたトークンが動作し続けないよう、単に「ローカルでトークンを忘れる」のではなく、実際のログアウト時にこれを呼び出してください。
現在のユーザー
ログアウト状態では { "user": null } を返します(エラーにはなりません) — アプリ起動時にログイン画面を表示するかどうかの判断に使用してください。
パスワードを忘れた場合
ボディ:{ email, locale }。アドレスが存在するかどうかに関わらず常に { success: true } を返し、アカウントの列挙に使われないようにしています。リセットリンク/トークン付きのメールを送信します(1時間有効)。
パスワードのリセット
ボディ:{ token, newPassword }。?token= を付けたGETでフォーム表示前に有効性を確認できます({ "valid": true|false })。
パスワードの変更
ボディ:{ currentPassword, newPassword }。アカウントにまだパスワードが設定されていない場合(例:ソーシャルログイン)を除き、currentPassword は必須です。
アカウント
プロフィールの更新
変更したいフィールドのみ送信してください。
| Field | Notes |
|---|---|
| firstName, lastName | 任意 · 文字列 |
| preferredCurrency | 任意 · USD、EUR、GBP、TRYのいずれか |
| locale | 任意 · 2文字コード、例:ja |
{ "success": true, "user": { ...same shape as /auth/me } }アバターの更新
ボディ:{ "avatarUrl": "data:image/..." } — base64のdata URI、最大約1.5MB。
APIキーの生成
このアカウントの新しいパートナーAPIキーを発行し、以前のキーを置き換えます。生の鍵はこのレスポンスで一度だけ表示されます — 以降はプレフィックスのみ取得可能です。
{
"success": true,
"key": "vio_live_sk_...",
"apiKeyPrefix": "vio_live_sk_ab12…9f8e",
"apiKeyGeneratedAt": "2026-08-22T17:00:00.781Z"
}アカウントの削除
App Store審査のために必須(アカウント作成機能があるアプリはアプリ内削除を提供する必要があります)。過去の注文が税務・会計記録として残るよう、行を完全に削除するのではなくアカウントを匿名化します(メールは撹拌されて再登録可能になり、名前/アバター/パスワードは消去されます)。ユーザーの全セッションと登録済みプッシュデバイスを破棄します。
カタログ
渡航先一覧の取得
有効なプランを持つ国と地域を、価格付き・UI用にフォーマットして返します(ストアフロント自体が呼び出しているものと同じです)。任意 ?filter=popular|regional|global|<検索テキスト>。
渡航先の詳細
ISOコードによる1つの国の完全な詳細(説明、プラン)、例:/api/v1/destinations/jp。
購入
チェックアウト
先にウォレットへ入金するのではなく、直接プランを購入します。
| Field | Notes |
|---|---|
| planId* | |
| quantity | 任意 · 1〜10、デフォルト1 |
| paymentMethod* | wallet | stripe | crypto |
| successUrl, cancelUrl | 任意 · stripe/cryptoのリダイレクト用。リダイレクトでアプリが再度開くよう、単なるウェブURLではなくユニバーサル/アプリリンクを使用してください。 |
{ "success": true, "orderId": "..." }{ "success": true, "orderId": "...", "url": "https://checkout.stripe.com/..." }Stripeによるウォレット入金
カードでウォレットに入金します — チェックアウトとは別のフローです。ボディ:{ amount(セント、最小200), currency, successUrl, cancelUrl }。{ sessionId, url } を返します。
暗号資産によるウォレット入金
ボディ:{ amount(小数文字列、最小$2), currency, url_return }。url を含むCryptomusのインボイスオブジェクトを返します。
注文一覧
呼び出し元の全注文を新しい順に返します。
注文の詳細
esimIds を含む単一の注文 — GET /api/v1/user/esims で完全なeSIM詳細(QR、アクティベーションコード)を取得し、idで照合してください。
マイeSIM
呼び出し元が所有する各eSIM:iccid、activationCode、qrCodeUrl、smdpAddress、status、dataUsage/totalVolume(MB)、activatedAt、expiresAt。「マイeSIM」画面とQR表示のデータ元です。
ウォレット履歴
/auth/me に表示されるウォレット残高の入金/出金/購入/返金履歴。
サポート
チケット一覧
呼び出し元のチケットとその完全なメッセージスレッドを新しい順に返します。
新規チケット
ボディ:{ subject, category, message }(category は任意)。
チケットへの返信
ボディ:{ message }。RESOLVED/CLOSEDのチケットに返信すると自動的に再オープンされます。
プッシュ通知デバイス
デバイストークンの登録のみ行います — 実際の送信にはAPNs/FCMの認証情報が必要です。下の注意書きを参照してください。
デバイスの登録
APNsまたはFCMトークンを取得した後に呼び出してください。ボディ:{ platform: "IOS"|"ANDROID", pushToken, appVersion }。トークンによってupsertされるため、アプリ起動のたびに再度呼び出しても問題なく、推奨されます(トークンはローテーションすることがあります)。
デバイス登録の解除
ボディ:{ pushToken }。共有/リセットされたデバイスが他のユーザーの通知を受け取り続けないよう、ログアウト時に呼び出してください。
パートナーAPI
以下はすべて、上記のAPIキーヘッダーが必要です — ここではセッションCookieは適用されません。
カタログ
渡航先一覧の取得
ストアフロントのUI形式ではなく、パートナー向けの形式での完全なカタログ。
{
"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": [...] } ]
}渡航先の詳細
ISOコードによる1つの国(例:/api/public/v1/destinations/JP)、上記と同じプラン形式。
注文
注文の作成
呼び出し元のウォレット残高からプランを購入し、eSIMを同期的にプロビジョニングします — レスポンスにはすでにエンドカスタマーに渡す準備が整ったQR/アクティベーションデータが含まれます。正常系ではポーリングは不要です。
{ "planId": "cus...", "quantity": 1 }{
"id": "...", "orderNumber": "VIO-API-...", "status": "COMPLETED", "amountUsd": 4.25,
"esims": [
{ "id": "...", "iccid": "...", "activationCode": "...",
"qrCodeUrl": "https://...", "smdpAddress": "...", "status": "PENDING" }
]
}注文一覧
任意 ?limit=(デフォルト25、最大100)。要約形式です — eSIMデータには詳細エンドポイントを使用してください。
注文の詳細
各eSIMのQR/アクティベーションデータとリアルタイム使用量(dataUsageMb / totalVolumeMb)を含む完全な注文詳細 — 残りデータ量を顧客に表示するためこれをポーリングしてください。
ウォレット
ウォレット残高
大量の注文をまとめて行う前に確認するか、残高が少なくなったときに自身に通知してください。
{ "balanceUsd": 128.40, "currency": "USD" }まだ構築されていないもの
ここに書かれていないものが動作すると誤解されないように。
プッシュ通知の送信
トークン登録は動作しますが、実際の送信にはAPNs/FCMの認証情報が必要です。
パートナー別の価格設定
パートナーAPIは現在ストアフロントと同じ小売価格を課金します。卸売/交渉価格にはスキーマ変更とビジネス上の意思決定が必要です。
リフレッシュトークン
セッションは、短命なアクセストークンとリフレッシュトークンのペアではなく、長命(30日)なフラットトークンです。当面は十分ですが、より厳格なセキュリティ体制が必要になれば後日見直します。
ネイティブStripe決済画面
Stripe連携はホスト型Checkout(リダイレクト/ウェブビュー)を使用しています。ネイティブのカード入力UIにはPaymentIntents+Stripe SDKを使用することになります。
パートナー向けWebhook
パートナーはステータス確認のため GET /orders/:id をポーリングする必要があります。まだ発信Webhook(例:「eSIMがアクティベートされました」)はありません。
