SimSms

1 选择服务 1,296 有货服务

选择服务

2 选择国家 145 国家

选择国家

3 网络与价格

选择服务和国家——顺序不限。价格和网络信息会显示在这里。

开发者

API 文档

在您自己的代码中读取余额,以及任意国家、任意服务的实时价格。一个持有者密钥,JSON over HTTPS,无需安装 SDK。

基础地址

https://simsms.com/api/v1
创建密钥

快速入门 #

全部采用 HTTPS 上的 JSON,用您自己创建的一个密钥完成鉴权。无需安装 SDK,无需签署合同,无需申请沙盒—一个密钥加 curl 即可。

  1. 1 创建密钥 打开账户菜单,选择 API 密钥,再选择创建密钥。密钥只显示一次:我们只保存其指纹,之后无法再次查看。
  2. 2 发送 Bearer 令牌 每个请求都携带 Authorization 请求头。没有其他接入方式—密钥不能出现在查询字符串中,不用 cookie,也不用 session。
  3. 3 读取响应 每个响应都是包含 ok 字段的 JSON 对象。当 ok 为 false 时,error 字段会用一个稳定、可供程序读取的字符串说明原因。

鉴权 #

每个账户只有一个密钥。除了下方的请求头方式外,其他发送方式均不支持—密钥若出现在查询字符串中,会被记录进服务器日志、浏览器历史和 referrer 请求头,因此会被直接拒绝,而不是悄悄接受。

request
Authorization: Bearer sk_your_key_here

密钥可用于消费 如今它能读取余额,将来订购号码功能上线后,用的也是同一个密钥。请像对待密码一样对待它:不要放进源代码仓库,不要出现在截图里,要替换而不是分享。替换密钥会立即关闭旧密钥。

约定 #

约定
基础地址 https://simsms.com/api/v1
传输方式 仅支持 HTTPS。普通 HTTP 会被重定向,且重定向请求不会携带您的请求头。
格式 输入输出均为 JSON。每个响应都是对象,绝不是裸数组。
成功 HTTP 200,返回 "ok": true。
失败 4xx 或 5xx 状态码,返回 "ok": false,以及一个稳定的 "error" 字符串。
金额 金额以美元数字表示,绝不是字符串,也绝不是美分。0.84 表示 84 美分。
未知字段 任何响应都可能新增字段。遇到不认识的字段请忽略,而不是报错。

错误 #

用于程序判断分支的是 error 字符串。旁边的说明句是写给您看的,不是给代码用的—说明句可能会改写,但字符串不会。

错误
HTTP 错误 何时
401 missing_key 没有 Authorization 请求头,或者它不是 Bearer 令牌。
401 bad_key 密钥未知,或者已被关闭或替换。
400 unknown_service 没有该代码对应的服务。代码来自目录,而不是显示名称。
404 no_stock 该服务与国家的组合目前没有库存号码。这是实时数据—库存可能会恢复。
404 unknown_country 该产品没有该代码对应的国家。代理和租用目录各自有自己的国家列表—不带国家参数调用该接口即可获取。
400 unknown_tech 该国家没有这一代网络。只有美国同时提供 4g 和 5g。
429 rate_limited 请求过于频繁。Retry-After 请求头会说明需要等待多少秒。

速率限制 #

每分钟 600 次请求,按账户而非按地址计数。密钥本应运行在服务器上—单一地址—因此按地址限制会误伤正常使用,还会让被盗的密钥在别处畅通无阻。超过限制会返回 429,并附带以秒为单位的 Retry-After 请求头。

接口 #

账户与目录的读取接口。每个路由都列出其全部参数、返回的全部字段,以及可能返回的全部错误——没有未文档化的行为。

查询余额 #

GET /api/v1/balance

账户当前持有的金额,以及按目录中当前最低价格能买到多少条验证码。

返回字段

查询余额 — 返回字段
字段 类型 说明
ok boolean 在 200 响应中始终为 true。
balance number 可用余额(美元),精确到美分。
currency string 始终是 "USD",让您不必自行假设币种。
codes_at_cheapest integer 按目录最低价格计算,余额能买到多少条验证码。这只是粗略参考,不是报价—目录为空时为 null。
cheapest_code number 该最低价格,方便您用其他数值自行计算这个参考值。

请求

request
curl -s "https://simsms.com/api/v1/balance" \
  -H "Authorization: Bearer $SIMSMS_KEY"

响应

200 OK
{
  "ok": true,
  "balance": 42.5,
  "currency": "USD",
  "codes_at_cheapest": 425,
  "cheapest_code": 0.1
}

可能返回 missing_key bad_key rate_limited

单个国家的服务价格 #

GET /api/v1/pricing?service={service}&country={country}

针对单一组合的实时价格与实时库存。两个数字都会变动—价格取决于该国家承载该服务的最低价网络,库存则是网络实时上报的数值。

参数

单个国家的服务价格 — 参数
参数 说明
service 必填 服务代码,例如 telegram。小写,来自目录。
country 可选 国家代码,例如 england。不填则一次获取所有国家—见下文。

返回字段

单个国家的服务价格 — 返回字段
字段 类型 说明
ok boolean 在 200 响应中始终为 true。
service string 您所请求的服务代码,原样返回。
country string 您所请求的国家代码,原样返回。
price number 以最低价网络计算,一条验证码的美元价格。
stock integer 当前上报的可用号码数量。这是实时数据,会变动。

请求

request
curl -s "https://simsms.com/api/v1/pricing?service=telegram&country=england" \
  -H "Authorization: Bearer $SIMSMS_KEY"

响应

200 OK
{
  "ok": true,
  "service": "telegram",
  "country": "england",
  "price": 0.84,
  "stock": 61213
}

可能返回 missing_key bad_key unknown_service no_stock rate_limited

所有国家的服务价格 #

GET /api/v1/pricing?service={service}

不带国家参数,即可获取承载该服务的所有国家。排序是本站自定的:先看实际到码率,再在其中比价—而不是单纯按原始价格排序,那样会把一个两美分却没人能收到验证码的号码排在最前面。

参数

所有国家的服务价格 — 参数
参数 说明
service 必填 服务代码,例如 telegram。

返回字段

所有国家的服务价格 — 返回字段
字段 类型 说明
ok boolean 在 200 响应中始终为 true。
service string 您所请求的服务代码。
name string 显示名称,例如「Telegram」。
countries array 每个国家对应一个对象,顺序如上文所述。
countries[].country string 国家代码,用于回传至配对调用。
countries[].name string 英文名称。
countries[].price number 一条验证码的美元价格。
countries[].stock integer 当前可用线路数量。

请求

request
curl -s "https://simsms.com/api/v1/pricing?service=telegram" \
  -H "Authorization: Bearer $SIMSMS_KEY"

响应

200 OK
{
  "ok": true,
  "service": "telegram",
  "name": "Telegram",
  "countries": [
    { "country": "england", "name": "United Kingdom", "price": 0.84, "stock": 61213 },
    { "country": "poland",  "name": "Poland",         "price": 0.91, "stock": 22140 }
  ]
}

可能返回 missing_key bad_key unknown_service rate_limited

移动代理定价 #

GET /api/v1/proxy-pricing?country={country}&tech={tech}

不指定国家时,返回我们部署调制解调器的四个国家,附运营商数量和起价;指定国家后,返回该国全部运营商及各租期价格。租期以天为单位:1、7、30、365。

参数

移动代理定价 — 参数
参数 说明
country 可选 国家代码,例如 us;留空则返回国家列表。
tech 可选 网络代次,4g 或 5g。仅美国同时销售两种,其他国家将忽略此字段,只返回单一套餐。

返回字段

移动代理定价 — 返回字段
字段 类型 说明
ok boolean 200 响应中恒为 true。
country string 您所查询的国家。
tech string 应用默认值后实际计价的网络代次。
techs array 该国在售的全部网络代次。
terms array 在售租期,单位为天。
carriers array 每个运营商对应一个对象。
carriers[].carrier string 运营商代码,用于下单。
carriers[].name string 显示名称,例如「T-Mobile」。
carriers[].prices object 各租期的美元价格,以天数为键。

请求

request
curl -s "https://simsms.com/api/v1/proxy-pricing?country=us" \
  -H "Authorization: Bearer $SIMSMS_KEY"

响应

200 OK
{
  "ok": true,
  "country": "us",
  "tech": "4g",
  "techs": ["4g", "5g"],
  "terms": [1, 7, 30, 365],
  "carriers": [
    { "carrier": "us-t-mobile", "name": "T-Mobile", "prices": { "1": 8.67, "7": 52, "30": 130, "365": 1300 } },
    { "carrier": "us-verizon",  "name": "Verizon",  "prices": { "1": 8.67, "7": 52, "30": 130, "365": 1300 } }
  ]
}

可能返回 missing_key bad_key unknown_country unknown_tech rate_limited

租用号码定价 #

GET /api/v1/rental-pricing?country={country}&days={days}

不指定国家时,返回全部可租用号码的国家及起价;指定国家后,返回该国全部运营商及您所选租期的价格。

参数

租用号码定价 — 参数
参数 说明
country 可选 国家代码,例如 fr;留空则返回国家列表。
days 可选 租期天数:7、14 或 30;其他数值将回退为最短租期。

返回字段

租用号码定价 — 返回字段
字段 类型 说明
ok boolean 200 响应中恒为 true。
country string 您所查询的国家。
days integer 实际计价的租期。
terms array 在售全部租期,单位为天。
operators array 每个运营商对应一个对象,按价格从低到高排列。
operators[].operator string 运营商代码,用于下单。
operators[].name string 显示名称。
operators[].type string physical、virtual 或 premium。
operators[].price number 整个租期的美元总价。

请求

request
curl -s "https://simsms.com/api/v1/rental-pricing?country=fr&days=30" \
  -H "Authorization: Bearer $SIMSMS_KEY"

响应

200 OK
{
  "ok": true,
  "country": "fr",
  "days": 30,
  "terms": [7, 14, 30],
  "operators": [
    { "operator": "fr-lycamobile", "name": "Lycamobile", "type": "virtual",  "price": 14.32 },
    { "operator": "fr-orange",     "name": "Orange",     "type": "physical", "price": 20.76 }
  ]
}

可能返回 missing_key bad_key unknown_country rate_limited

完整示例 #

完整可运行的程序,而非单行代码片段——包括片段总会省略的两件事:处理错误格式,以及在 429 时退避重试。

Shell #

查找服务的最低价国家,并确认余额是否充足。

cheapest.sh
#!/usr/bin/env bash
set -euo pipefail
: "${SIMSMS_KEY:?export your key first}"
API="https://simsms.com/api/v1"

auth=(-H "Authorization: Bearer $SIMSMS_KEY")

# The catalogue is already ordered: the first country is the one to take.
best=$(curl -sf "${API}/pricing?service=telegram" "${auth[@]}" \
        | jq -r ".countries[0] | \"\(.country) \(.price)\"")
country=${best% *}
price=${best#* }

balance=$(curl -sf "${API}/balance" "${auth[@]}" | jq -r .balance)

# ⚠️ Compare as numbers, not as strings: "9.5" > "10" is true in a string sort.
if awk "BEGIN{exit !($balance >= $price)}"; then
  echo "ok: $country at \$$price, balance \$$balance"
else
  echo "top up first: need \$$price, have \$$balance" >&2
  exit 1
fi

JavaScript #

相同功能的 Node 版本,正确处理了错误结构。

pricing.mjs
const API = "https://simsms.com/api/v1";
const key = process.env.SIMSMS_KEY;

async function call(path) {
  const r = await fetch(API + path, {
    headers: { Authorization: `Bearer ${key}` },
  });
  const body = await r.json();
  // A non-2xx always carries { ok:false, error }. Branch on `error`, never on
  // the sentence — the string is stable, the wording is not.
  if (!r.ok || !body.ok) {
    if (body.error === "rate_limited") {
      const wait = Number(r.headers.get("Retry-After") || 60);
      await new Promise((s) => setTimeout(s, wait * 1000));
      return call(path);
    }
    throw new Error(body.error ?? `http_${r.status}`);
  }
  return body;
}

const { countries } = await call("/pricing?service=telegram");
const { balance }   = await call("/balance");

const best = countries[0];
console.log(`${best.name}: $${best.price} (${best.stock} in stock)`);
console.log(balance >= best.price ? "balance covers it" : "top up first");

Python #

以及 Python 版本,同样在 429 时重试。

pricing.py
import os, time, requests

API = "https://simsms.com/api/v1"
S = requests.Session()
S.headers["Authorization"] = f"Bearer {os.environ['SIMSMS_KEY']}"

def call(path):
    r = S.get(API + path, timeout=20)
    body = r.json()
    if not r.ok or not body.get("ok"):
        if body.get("error") == "rate_limited":
            time.sleep(int(r.headers.get("Retry-After", 60)))
            return call(path)
        raise RuntimeError(body.get("error", f"http_{r.status_code}"))
    return body

countries = call("/pricing?service=telegram")["countries"]
balance   = call("/balance")["balance"]

best = countries[0]
print(f"{best['name']}: ${best['price']} ({best['stock']} in stock)")
print("balance covers it" if balance >= best["price"] else "top up first")

路线图 #

API 目前覆盖账户与目录查询。下单接口即将上线,将使用相同的基础地址和密钥——您现在构建的代码无需重写。

下单购买号码 计划中 计划中。目前下单仍通过网站完成。
轮询验证码 计划中 计划中,与下单接口同期上线。
释放号码 计划中 计划中,与下单接口同期上线。
API 租用号码 计划中 计划中。
Webhooks 计划中 计划中,待有可推送的订单事件后上线。

本页面将随之扩充:以下各节保持不变,新增内容将加入「端点」部分下方。

更新日志 #

  • 首个公开版本:密钥、GET /balance、GET /pricing。