Vio eSIM API 参考文档
同一后端提供两套 REST 接口:驱动网页版与我们 iOS/Android 应用的面向客户 API,以及一套单独的、通过 API 密钥认证的合作伙伴 API,用于以编程方式转售 Vio eSIM。
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
两次调用即可浏览目录并购买 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 | 状态冲突(例如删除余额不为零的账户) |
| 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 | 可选 · 两字母代码,如 zh |
{ "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 代码获取某一国家的完整详情(描述、套餐),如 /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 详情(二维码、激活码)并按 id 匹配。
我的 eSIM
调用方拥有的每个 eSIM:iccid、activationCode、qrCodeUrl、smdpAddress、status、dataUsage/totalVolume(MB)、activatedAt、expiresAt。这些数据驱动"我的 eSIM"界面和二维码显示。
钱包历史
/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 代码获取单个国家(如 /api/public/v1/destinations/JP),套餐格式与上文相同。
订单
创建订单
从调用方钱包余额中扣款购买套餐,并同步开通 eSIM — 响应中已包含可直接交给最终客户的二维码/激活数据。正常情况下无需轮询。
{ "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 的二维码/激活数据及实时用量(dataUsageMb / totalVolumeMb) — 轮询此接口可向客户展示其剩余流量。
钱包
钱包余额
批量下单前请先查询,或在余额过低时设置提醒。
{ "balanceUsd": 128.40, "currency": "USD" }尚未实现的功能
以确保此处不会将未实现的功能误认为已可用。
推送通知发送
令牌注册功能可用;实际发送推送还需要 APNs/FCM 凭据。
合作伙伴专属定价
合作伙伴 API 目前收取与商城相同的零售价。批发/协商定价需要修改数据结构并做出业务决策。
刷新令牌
会话是长期有效(30 天)的单一令牌,而非短期访问令牌 + 刷新令牌的组合。目前已足够;日后若需更严格的安全策略可重新评估。
原生 Stripe 支付界面
Stripe 集成目前使用托管 Checkout(跳转/内嵌网页)。原生的银行卡输入界面需改用 PaymentIntents 及 Stripe SDK。
面向合作伙伴的 Webhook
合作伙伴目前必须轮询 GET /orders/:id 获取状态;尚未提供出站 Webhook(例如"eSIM 已激活")。
