SimSms

1 Choisir service 1 290 services en stock

Choisir un service

2 Choisir pays 145 pays

Choisir un pays

3 Réseau et prix

Choisissez un service et un pays — dans l'ordre de votre choix. Le prix et le réseau s'affichent ici.

Développeurs

Documentation API

Consultez votre solde et le prix en direct de n'importe quel service dans n'importe quel pays depuis votre propre code. Une clé Bearer, JSON sur HTTPS, aucun SDK à installer.

URL de base

https://simsms.com/api/v1
Créer une clé

Prise en main #

Tout se fait en JSON sur HTTPS, authentifié avec une seule clé que vous créez vous-même. Pas de SDK à installer, pas de contrat à signer, pas de bac à sable à demander — une clé et curl suffisent.

  1. 1 Créer une clé Ouvrez le menu du compte, puis Clé d'API, puis Créer une clé. Elle s'affiche une seule fois : nous ne conservons que son empreinte, donc elle ne peut plus être retrouvée ensuite.
  2. 2 Envoyer un jeton porteur Chaque requête porte un en-tête Authorization. Il n'y a pas d'autre point d'entrée — pas de clé dans la chaîne de requête, pas de cookie, pas de session.
  3. 3 Lire la réponse Chaque réponse est un objet JSON comportant un champ ok. Quand ok vaut false, un champ error indique la raison dans une chaîne stable, lisible par une machine.

Authentification #

Une seule clé par compte. L'envoyer autrement que par l'en-tête ci-dessous n'est pas pris en charge — une clé dans une chaîne de requête finit dans les journaux serveur, l'historique du navigateur et les en-têtes referrer, elle est donc refusée plutôt qu'acceptée silencieusement.

request
Authorization: Bearer sk_your_key_here

Une clé peut dépenser Elle lit le solde aujourd'hui, et c'est la même clé qui commandera des numéros quand la commande existera. Traitez-la comme un mot de passe : hors du contrôle de version, hors des captures d'écran, remplacée plutôt que partagée. Remplacer une clé ferme l'ancienne immédiatement.

Conventions #

Conventions
URL de base https://simsms.com/api/v1
Transport HTTPS uniquement. Le HTTP simple est redirigé, et la redirection ne transporte pas votre en-tête.
Format Du JSON en entrée, du JSON en sortie. Chaque réponse est un objet, jamais un simple tableau.
Succès HTTP 200 avec "ok": true.
Échec Un code 4xx ou 5xx avec "ok": false et une chaîne "error" stable.
Somme Des nombres en dollars US, jamais des chaînes, jamais des cents. 0.84 signifie 84 cents.
Champs inconnus De nouveaux champs peuvent être ajoutés à n'importe quelle réponse. Ignorez ce que vous ne connaissez pas plutôt que d'échouer dessus.

Erreurs #

La chaîne error est l'élément sur lequel s'appuyer dans le code. La phrase à côté est pour vous, pas pour votre code — elle peut être reformulée ; la chaîne, non.

Erreurs
HTTP erreur Quand
401 missing_key Pas d'en-tête Authorization, ou ce n'est pas un jeton porteur.
401 bad_key La clé est inconnue, ou elle a été fermée ou remplacée.
400 unknown_service Aucun service ne correspond à ce code. Les codes proviennent du catalogue, pas du nom affiché.
404 no_stock Cette paire service/pays n'a aucun numéro en stock pour l'instant. C'est un chiffre en temps réel — il peut revenir.
429 rate_limited Trop de requêtes. Un en-tête Retry-After indique combien de secondes attendre.

Débit limité #

600 requêtes par minute, comptées par compte plutôt que par adresse. Une clé est censée tourner depuis un serveur — une seule adresse — donc une limite par adresse pénaliserait un usage normal et laisserait une clé volée tourner librement ailleurs. Au-delà de la limite, vous obtenez 429 et un en-tête Retry-After en secondes.

Points de terminaison #

Lectures du compte et du catalogue. Chaque route liste tous les paramètres qu'elle accepte, tous les champs qu'elle renvoie, et toutes les erreurs qu'elle peut renvoyer — aucun comportement non documenté.

Lire votre solde #

GET /api/v1/balance

Ce que le compte détient actuellement, et combien de codes cela permet d'acheter au prix le plus bas du catalogue en ce moment.

Champs de réponse

Lire votre solde — Champs de réponse
Champ Type Description
ok boolean Toujours true sur 200.
balance number Dollars disponibles, arrondis au centime près.
currency string Toujours "USD". Présent pour que vous n'ayez jamais à le supposer.
codes_at_cheapest integer Combien de codes le solde permet d'acheter au prix le plus bas du catalogue. Une estimation approximative, pas un devis — null si le catalogue est vide.
cheapest_code number Ce prix le plus bas, pour que vous puissiez calculer vous-même l'estimation à partir d'un autre chiffre.

Requête

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

Réponse

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

Peut répondre avec missing_key bad_key rate_limited

Tarifer un service dans un pays #

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

Le prix en temps réel et le stock en temps réel pour une paire donnée. Les deux chiffres évoluent — le prix suit le réseau le moins cher qui propose ce service dans ce pays, et le stock est ce que le réseau indique à l'instant.

Paramètres

Tarifer un service dans un pays — Paramètres
Paramètre Description
service requis Code de service, par exemple telegram. En minuscules, tiré du catalogue.
country optionnel Code pays, par exemple england. Omettez-le pour obtenir tous les pays à la fois — voir ci-dessous.

Champs de réponse

Tarifer un service dans un pays — Champs de réponse
Champ Type Description
ok boolean Toujours vrai en 200.
service string Le code de service que vous avez demandé, renvoyé tel quel.
country string Le code pays que vous avez demandé, renvoyé tel quel.
price number Dollars pour un code, au tarif du réseau le moins cher qui le propose.
stock integer Nombre de lignes disponibles à l'instant. C'est une valeur en temps réel, qui évolue.

Requête

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

Réponse

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

Peut répondre avec missing_key bad_key unknown_service no_stock rate_limited

Prix d'un service, tous pays confondus #

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

Omettez le pays et vous obtenez tous les pays qui proposent ce service. L'ordre est propre au site : ce qui délivre réellement en premier, puis le moins cher à ce niveau-là — pas le prix brut, qui mettrait en tête un numéro à deux centimes dont personne ne reçoit jamais de code.

Paramètres

Prix d'un service, tous pays confondus — Paramètres
Paramètre Description
service requis Code de service, par exemple telegram.

Champs de réponse

Prix d'un service, tous pays confondus — Champs de réponse
Champ Type Description
ok boolean Toujours vrai en 200.
service string Le code de service que vous avez demandé.
name string Son nom d'affichage, par exemple « Telegram ».
countries array Un objet par pays, dans l'ordre décrit ci-dessus.
countries[].country string Code pays, à réutiliser dans l'appel prenant la paire service/pays.
countries[].name string Son nom en anglais.
countries[].price number Dollars pour un code.
countries[].stock integer Lignes disponibles à l'instant.

Requête

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

Réponse

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 }
  ]
}

Peut répondre avec missing_key bad_key unknown_service rate_limited

Exemples #

Des programmes complets et exécutables plutôt que des fragments d'une ligne — avec les deux choses que les fragments oublient toujours : la gestion de la forme des erreurs, et le ralentissement en cas de 429.

Shell #

Trouver le pays le moins cher pour un service, puis vérifier que le solde suffit.

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 #

La même chose en Node, avec la structure des erreurs correctement gérée.

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 #

Et en Python, avec la même relance en cas de 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")

À venir #

Aujourd'hui, l'API couvre la lecture du compte et du catalogue. La surface de commande vient ensuite : elle logera sous la même adresse de base et prendra la même clé — rien de ce que vous construisez aujourd'hui n'aura besoin d'être réécrit.

Commander numéro Prévu Prévu. Pour l'instant, la commande passe par le site.
Interroger le code Prévu Prévu, en même temps que la commande.
Libérer un numéro Prévu Prévu, en même temps que la commande.
Location par API Prévu Prévu.
Webhooks Prévu Prévu, une fois qu'il y aura des événements de commande à transmettre.

Cette page grandit avec eux : les sections ci-dessous restent à leur place, et les nouvelles sont ajoutées sous Points de terminaison.

Historique #

  • Première version publique : clés, GET /balance, GET /pricing.