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.
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 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 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 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.
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 #
| 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.
| 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
| 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
curl -s "https://simsms.com/api/v1/balance" \
-H "Authorization: Bearer $SIMSMS_KEY"
Réponse
{
"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
| 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
| 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
curl -s "https://simsms.com/api/v1/pricing?service=telegram&country=england" \
-H "Authorization: Bearer $SIMSMS_KEY"
Réponse
{
"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
| Paramètre | Description | |
|---|---|---|
service |
requis | Code de service, par exemple telegram. |
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
curl -s "https://simsms.com/api/v1/pricing?service=telegram" \
-H "Authorization: Bearer $SIMSMS_KEY"
Réponse
{
"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.
#!/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.
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.
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.