SimSms

1 Choisir service 1 296 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
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. #

Pas d'en-tête Authorization, ou ce n'est pas un jeton porteur.

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.
HTTP erreur Quand
401 missing_key La clé est inconnue, ou elle a été fermée ou remplacée.
401 bad_key Aucun service ne correspond à ce code. Les codes proviennent du catalogue, pas du nom affiché.
400 unknown_service 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.
404 no_stock Trop de requêtes. Un en-tête Retry-After indique combien de secondes attendre.
404 unknown_country Débit limité
400 unknown_tech 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.
429 rate_limited Lire votre solde

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. #

Toujours true sur 200.

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é.

Dollars disponibles, arrondis au centime près. #

GET /api/v1/balance

Toujours "USD". Présent pour que vous n'ayez jamais à le supposer.

Champs de réponse

Dollars disponibles, arrondis au centime près. — Champs de réponse
Champ Type Description
ok boolean 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.
balance number Ce prix le plus bas, pour que vous puissiez calculer vous-même l'estimation à partir d'un autre chiffre.
currency string Tarifer un service dans un pays
codes_at_cheapest integer 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.
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 en anglais.
countries array Dollars pour un code.
countries[].country string Lignes disponibles à l'instant.
countries[].name string Shell
countries[].price number cheapest.sh
countries[].stock integer Trouver le pays le moins cher pour un service, puis vérifier que le solde suffit.

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

JavaScript #

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

pricing.mjs

Paramètres

JavaScript — Paramètres
Paramètre Description
country optionnel La même chose en Node, avec la structure des erreurs correctement gérée.
tech optionnel Python

Champs de réponse

JavaScript — Champs de réponse
Champ Type Description
ok boolean pricing.py
country string Et en Python, avec la même relance en cas de 429.
tech string À venir
techs array 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.
terms array Commander numéro
carriers array Prévu. Pour l'instant, la commande passe par le site.
carriers[].carrier string Interroger le code
carriers[].name string Prévu, en même temps que la commande.
carriers[].prices object Libérer un numéro

Requête

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

Réponse

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

Peut répondre avec missing_key bad_key unknown_country unknown_tech rate_limited

Prévu, en même temps que la commande. #

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

Location par API

Paramètres

Prévu, en même temps que la commande. — Paramètres
Paramètre Description
country optionnel Prévu.
days optionnel Webhooks

Champs de réponse

Prévu, en même temps que la commande. — Champs de réponse
Champ Type Description
ok boolean Prévu, une fois qu'il y aura des événements de commande à transmettre.
country string Cette page grandit avec eux : les sections ci-dessous restent à leur place, et les nouvelles sont ajoutées sous Points de terminaison.
days integer Première version publique : clés, GET /balance, GET /pricing.
terms array Toutes les durées disponibles, en jours.
operators array Un objet par opérateur, le moins cher en premier.
operators[].operator string Code opérateur, à transmettre dans la commande.
operators[].name string Nom d'affichage.
operators[].type string physique, virtuel ou premium.
operators[].price number Dollars pour toute la durée.

Requête

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

Réponse

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

Peut répondre avec missing_key bad_key unknown_country 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.