• 228 destinations
  • No KYC, ever
  • Bitcoin, Monero, USDT and 4 more

SDKs and samples

No SDK to install.
An HTTP client is enough.

The API is six endpoints of plain JSON, so we ship an OpenAPI description you can generate a typed client from, plus ready-to-paste samples in the languages we see most.

  • OpenAPI 3.1, YAML
  • Six languages
  • Kept in sync with the reference

OpenAPI description

The full API is described in OpenAPI 3.1. Point any generator at it to get a typed client with request validation, or import it in your API tool of choice.

Download openapi.yaml Also served at https://smsmeteor.com/docs/openapi.yaml. Versioned with the API; the info.version field is the reference.
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 and Insomnia

Both tools import OpenAPI directly: Import, Link, paste the URL above. Create an environment with key set to your test key and every request is ready to run without sending anything.

Samples

Every sample sends one message with an idempotency key and prints the id, status and price. Replace the key, keep the header.

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 verification

The signature scheme is HMAC-SHA256 over timestamp.body. Verification code in Node, Python and PHP is on the webhooks page; the same twelve lines port to any language with an HMAC primitive.

Retry policy we recommend

Community libraries

We do not publish official SDKs; clients generated from the OpenAPI description stay current automatically. If you publish a wrapper, tell us and we will link it here with your name.