• 覆盖 228 个目的地
  • 始终无需 KYC
  • 支持 Bitcoin、Monero、USDT 等 7 种币种

SDK 与示例

无需安装 SDK。
一个 HTTP 客户端就够了。

API 仅包含六个使用普通 JSON 的端点,因此我们提供可生成类型化客户端的 OpenAPI 描述,以及常用语言中可直接粘贴使用的示例。

  • OpenAPI 3.1,YAML
  • 六种语言
  • 与参考文档保持同步

OpenAPI 描述

完整 API 使用 OpenAPI 3.1 描述。将任意生成器指向该文件,即可获得带请求验证的类型化客户端;您也可以将它导入常用的 API 工具。

下载 openapi.yaml 也可通过 https://smsmeteor.com/docs/openapi.yaml 获取。版本随 API 更新,以 info.version 字段为准。
npx openapi-typescript https://smsmeteor.com/docs/openapi.yaml -o smsmeteor.d.ts
# then use it with openapi-fetch
import createClient from "openapi-fetch";
import type { paths } from "./smsmeteor";
const api = createClient<paths>({ baseUrl: "https://api.smsmeteor.com/v1",
  headers: { Authorization: `Bearer ${process.env.SMSMETEOR_KEY}` } });
const { data } = await api.POST("/messages", { body: { to: "+14155550142", text: "Hi" } });
# openapi-python-client
pipx run openapi-python-client generate --url https://smsmeteor.com/docs/openapi.yaml

from smsmeteor_client import Client
from smsmeteor_client.api.messages import create_message
client = Client(base_url="https://api.smsmeteor.com/v1", headers={"Authorization": f"Bearer {KEY}"})
msg = create_message.sync(client=client, body={"to": "+14155550142", "text": "Hi"})
# openapi-generator
openapi-generator-cli generate \
  -i https://smsmeteor.com/docs/openapi.yaml \
  -g java --library okhttp-gson \
  -o smsmeteor-java

Postman 与 Insomnia

这两个工具都能直接导入 OpenAPI:依次选择 Import、Link,然后粘贴上面的 URL。创建一个环境,并将 key 设置为测试密钥,即可运行所有请求而不实际发送任何消息。

示例

每个示例都会使用幂等键发送一条消息,并输出 id、状态和价格。请替换密钥,并保留该标头。

POST /v1/messages
curl https://api.smsmeteor.com/v1/messages \
  -H "Authorization: Bearer $SMSMETEOR_KEY" \
  -H "Idempotency-Key: demo-001" \
  -d to="+14155550142" -d from="METEOR" \
  -d text="Your code is 493 201"
import os, requests

def send(to: str, text: str, key: str) -> dict:
    r = requests.post(
        "https://api.smsmeteor.com/v1/messages",
        headers={"Authorization": f"Bearer {os.environ['SMSMETEOR_KEY']}", "Idempotency-Key": key},
        json={"to": to, "from": "METEOR", "text": text},
        timeout=10,
    )
    r.raise_for_status()
    return r.json()

msg = send("+14155550142", "Your code is 493 201", "demo-001")
print(msg["id"], msg["status"], msg["price"])
export async function send(to, text, key) {
  const r = await fetch("https://api.smsmeteor.com/v1/messages", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SMSMETEOR_KEY}`,
      "Idempotency-Key": key,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ to, from: "METEOR", text }),
  });
  if (!r.ok) throw new Error((await r.json()).error.code);
  return r.json();
}

const msg = await send("+14155550142", "Your code is 493 201", "demo-001");
console.log(msg.id, msg.status, msg.price);
function send(string $to, string $text, string $key): array {
    $ch = curl_init('https://api.smsmeteor.com/v1/messages');
    curl_setopt_array($ch, [
        CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10,
        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('SMSMETEOR_KEY'),
            'Idempotency-Key: ' . $key, 'Content-Type: application/json'],
        CURLOPT_POSTFIELDS => json_encode(['to' => $to, 'from' => 'METEOR', 'text' => $text]),
    ]);
    $res = json_decode((string) curl_exec($ch), true);
    if (curl_getinfo($ch, CURLINFO_RESPONSE_CODE) >= 400) throw new RuntimeException($res['error']['code']);
    return $res;
}

$msg = send('+14155550142', 'Your code is 493 201', 'demo-001');
echo $msg['id'], ' ', $msg['status'], ' ', $msg['price'];
func send(to, text, key string) (map[string]any, error) {
    body, _ := json.Marshal(map[string]string{"to": to, "from": "METEOR", "text": text})
    req, _ := http.NewRequest("POST", "https://api.smsmeteor.com/v1/messages", bytes.NewReader(body))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("SMSMETEOR_KEY"))
    req.Header.Set("Idempotency-Key", key)
    req.Header.Set("Content-Type", "application/json")
    res, err := http.DefaultClient.Do(req)
    if err != nil { return nil, err }
    defer res.Body.Close()
    var out map[string]any
    return out, json.NewDecoder(res.Body).Decode(&out)
}
require "net/http"; require "json"

def send_sms(to, text, key)
  uri = URI("https://api.smsmeteor.com/v1/messages")
  req = Net::HTTP::Post.new(uri, "Authorization" => "Bearer #{ENV['SMSMETEOR_KEY']}",
    "Idempotency-Key" => key, "Content-Type" => "application/json")
  req.body = { to: to, from: "METEOR", text: text }.to_json
  res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
  JSON.parse(res.body)
end

msg = send_sms("+14155550142", "Your code is 493 201", "demo-001")
puts [msg["id"], msg["status"], msg["price"]].join(" ")

Webhook 验证

签名方案是对 timestamp.body 计算 HMAC-SHA256。Node、Python 和 PHP 的验证代码位于 Webhook 页面;只要语言支持 HMAC 原语,这十二行代码都可以移植。

我们推荐的重试策略

社区库

我们不发布官方 SDK;从 OpenAPI 描述生成的客户端会自动保持最新。如果您发布了封装库,请告诉我们,我们会在此附上您的姓名和链接。