La vérification SMS manuelle — acheter un numéro, attendre le code, l’entrer dans une interface — fonctionne parfaitement pour les usages ponctuels. Mais dès qu’il s’agit d’automatisation — tests E2E, création de comptes en masse, pipelines CI/CD, monitoring de services — l’intervention manuelle devient un goulot d’étranglement. L’API SMSCode permet de gérer tout le cycle de vérification SMS de manière programmatique, depuis la sélection du numéro jusqu’à la récupération du code.
TL;DR — L’API REST SMSCode permet d’automatiser entièrement le cycle achat de numéro → réception du SMS → libération. Elle est compatible avec n’importe quel langage. Authentification par bearer token, 5 endpoints principaux. Les prix démarrent à 0,005 $ par numéro. Idéal pour les tests automatisés, la création de comptes de test, ou l’intégration de vérification SMS dans des workflows CI/CD. L’API est compatible avec le format SMS-Activate pour une migration facile.
Cas d’usage de l’API SMSCode
Avant de plonger dans la technique, voici les situations concrètes pour lesquelles l’API est utilisée :
Tests E2E et tests d’intégration. Playwright, Cypress, Selenium — les frameworks de test automatisé peuvent créer des comptes utilisateur et tester des flux d’inscription complets. L’API SMSCode fournit les numéros de téléphone et récupère les codes OTP programmatiquement, ce qui rend les tests d’inscription entièrement automatisables.
Pipelines CI/CD. Tester une intégration d’inscription SMS à chaque déploiement sans intervention humaine. L’API s’intègre dans n’importe quel script de pipeline (GitHub Actions, GitLab CI, Jenkins, Buildkite).
Création de comptes de test. Les équipes QA qui ont besoin de dizaines ou centaines de comptes de test sur une plateforme cible peuvent automatiser la création avec des numéros distincts pour chaque compte. Chaque numéro SMSCode est unique — aucun risque de collision.
Monitoring de services. Vérifier régulièrement qu’un flux d’inscription fonctionne correctement en production, sans créer de comptes manuellement. Un script peut s’exécuter toutes les heures et alerter si la vérification SMS échoue.
Applications et SaaS. Des développeurs intègrent l’API SMSCode dans leurs propres applications pour fournir des numéros virtuels à leurs utilisateurs finaux comme service.
Scraping et données. Accéder à des services qui nécessitent une vérification SMS pour récupérer des données publiques.
Obtenir ta clé API
- Crée un compte sur smscode.gg
- Va dans Paramètres → API dans ton tableau de bord
- Génère une clé API (bearer token) — elle apparaît une seule fois, copie-la immédiatement
- Ajoute des crédits — minimum 1 $ pour commencer à tester
Sécurité de la clé API :
- Traite-la comme un mot de passe — accès complet à ton solde et à tes commandes
- Ne la commit jamais dans un dépôt git (utilise
.gitignorepour les fichiers.env) - Utilise les variables d’environnement :
SMSCODE_API_KEY=ta_cledans.env - Régénère-la immédiatement si tu suspectes une compromission
Authentification
Toutes les requêtes utilisent un header Authorization avec un bearer token :
Authorization: Bearer ta_cle_api
Content-Type: application/json
L’API est disponible sur https://api.smscode.gg/v1/. Toutes les réponses sont en JSON avec la structure suivante :
// Succès
{ "success": true, "data": { ... } }
// Erreur
{ "success": false, "error": { "code": "CODE_ERREUR", "message": "Description" } }
Endpoints principaux
Vérifier le solde
GET /v1/balance
Réponse :
{
"success": true,
"data": {
"balance": 4.52,
"currency": "USD"
}
}
Vérifie ton solde avant chaque session d’automatisation pour éviter les interruptions en cours de processus.
Lister les services et pays disponibles
GET /v1/catalog
GET /v1/catalog?service=google
GET /v1/catalog?service=instagram&country=fr
Réponse :
{
"success": true,
"data": [
{
"service": "google",
"country": "in",
"country_name": "Inde",
"price": 0.01,
"available": 142
},
{
"service": "google",
"country": "fr",
"country_name": "France",
"price": 0.40,
"available": 23
}
]
}
Utilise le champ available pour filtrer les pays avec du stock disponible avant de commander. Un available: 0 signifie qu’il faut choisir un autre pays ou réessayer plus tard.
Acheter un numéro
POST /v1/orders
Corps de la requête :
{
"service": "google",
"country": "in"
}
Réponse :
{
"success": true,
"data": {
"order_id": "ord_abc123",
"number": "+919876543210",
"country": "in",
"service": "google",
"expires_at": "2026-03-16T10:20:00Z",
"status": "pending"
}
}
Le numéro est réservé exclusivement pour toi jusqu’à expires_at (généralement 15–20 minutes). Utilise le numéro dans ton flux d’automatisation immédiatement après la réception.
Récupérer le statut d’une commande (polling)
GET /v1/orders/{order_id}
Réponse (SMS reçu — statut completed) :
{
"success": true,
"data": {
"order_id": "ord_abc123",
"number": "+919876543210",
"status": "completed",
"sms_text": "Your Google verification code is 847291",
"code": "847291",
"received_at": "2026-03-16T10:15:30Z"
}
}
Réponse (en attente de SMS — statut pending) :
{
"success": true,
"data": {
"order_id": "ord_abc123",
"status": "pending",
"sms_text": null,
"code": null
}
}
Le champ code contient le code numérique extrait du SMS. Le champ sms_text contient le message complet — utile si le format du code varie selon les services.
Annuler une commande
DELETE /v1/orders/{order_id}
Annule une commande avant expiration. Le montant est remboursé automatiquement sur ton solde. Utilise cet endpoint dans ton gestionnaire d’erreurs ou timeout pour récupérer le crédit plutôt que d’attendre l’expiration automatique.
Exemples d’intégration
Python — Implémentation complète
import requests
import time
import os
API_KEY = os.environ.get("SMSCODE_API_KEY")
BASE_URL = "https://api.smscode.gg/v1"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
def verifier_solde():
"""Vérifie le solde disponible avant de commencer."""
response = requests.get(f"{BASE_URL}/balance", headers=headers)
data = response.json()
if not data["success"]:
raise Exception(f"Erreur solde : {data['error']['message']}")
return data["data"]["balance"]
def trouver_pays_disponible(service, pays_preferes=["in", "id", "ph"]):
"""Trouve le premier pays disponible parmi une liste de préférences."""
response = requests.get(
f"{BASE_URL}/catalog",
params={"service": service},
headers=headers
)
catalog = response.json()["data"]
catalog_map = {item["country"]: item for item in catalog}
for pays in pays_preferes:
if pays in catalog_map and catalog_map[pays]["available"] > 0:
return pays, catalog_map[pays]["price"]
raise Exception(f"Aucun pays disponible pour {service} parmi {pays_preferes}")
def acheter_numero(service, country):
"""Achète un numéro virtuel et retourne l'order_id et le numéro."""
response = requests.post(
f"{BASE_URL}/orders",
json={"service": service, "country": country},
headers=headers
)
data = response.json()
if not data["success"]:
raise Exception(f"Erreur achat numéro : {data['error']['message']}")
return data["data"]["order_id"], data["data"]["number"]
def attendre_sms(order_id, timeout=120, intervalle=5):
"""Attend le SMS avec polling configurable."""
start = time.time()
while time.time() - start < timeout:
response = requests.get(
f"{BASE_URL}/orders/{order_id}",
headers=headers
)
data = response.json()["data"]
if data["status"] == "completed" and data["code"]:
return data["code"], data["sms_text"]
if data["status"] in ["expired", "cancelled"]:
raise Exception(f"Commande terminée sans SMS : {data['status']}")
time.sleep(intervalle)
raise TimeoutError(f"SMS non reçu après {timeout}s")
def annuler_commande(order_id):
"""Annule une commande et récupère le remboursement."""
requests.delete(f"{BASE_URL}/orders/{order_id}", headers=headers)
# Utilisation avec gestion complète des erreurs
def obtenir_code_verification(service, pays_preferes=None):
"""Fonction principale : obtient un code de vérification SMS."""
if pays_preferes is None:
pays_preferes = ["in", "id", "ph"]
solde = verifier_solde()
print(f"Solde disponible : {solde:.3f} $")
pays, prix = trouver_pays_disponible(service, pays_preferes)
print(f"Pays sélectionné : {pays} ({prix:.3f} $)")
order_id, numero = acheter_numero(service, pays)
print(f"Numéro obtenu : {numero} (order: {order_id})")
try:
code, sms = attendre_sms(order_id)
print(f"Code reçu : {code}")
return numero, code
except TimeoutError:
print("Timeout — annulation de la commande (remboursement auto)")
annuler_commande(order_id)
raise
# Exemple d'utilisation
numero, code = obtenir_code_verification("google", pays_preferes=["in", "id", "kz"])
print(f"Numéro : {numero}, Code : {code}")
JavaScript (Node.js) — Avec async/await
const API_KEY = process.env.SMSCODE_API_KEY;
const BASE_URL = 'https://api.smscode.gg/v1';
const defaultHeaders = {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
};
async function apiRequest(method, endpoint, body = null, params = null) {
let url = `${BASE_URL}${endpoint}`;
if (params) {
url += '?' + new URLSearchParams(params).toString();
}
const options = { method, headers: defaultHeaders };
if (body) options.body = JSON.stringify(body);
const response = await fetch(url, options);
const data = await response.json();
if (!data.success) {
throw new Error(`API Error: ${data.error.code} — ${data.error.message}`);
}
return data.data;
}
async function acheterNumero(service, country) {
return apiRequest('POST', '/orders', { service, country });
}
async function attendreSms(orderId, timeoutMs = 120000, intervalMs = 5000) {
const start = Date.now();
while (Date.now() - start < timeoutMs) {
const order = await apiRequest('GET', `/orders/${orderId}`);
if (order.status === 'completed' && order.code) {
return { code: order.code, sms: order.sms_text };
}
if (['expired', 'cancelled'].includes(order.status)) {
throw new Error(`Order ended without SMS: ${order.status}`);
}
await new Promise(resolve => setTimeout(resolve, intervalMs));
}
throw new Error('Timeout — SMS not received');
}
async function annulerCommande(orderId) {
await apiRequest('DELETE', `/orders/${orderId}`);
}
// Fonction principale avec gestion des erreurs
async function obtenirCodeVerification(service, country = 'in') {
let orderId = null;
try {
const order = await acheterNumero(service, country);
orderId = order.order_id;
console.log(`Numéro obtenu : ${order.number} (${orderId})`);
const { code, sms } = await attendreSms(orderId);
console.log(`Code reçu : ${code}`);
console.log(`SMS complet : ${sms}`);
return { number: order.number, code };
} catch (error) {
if (orderId) {
console.log('Annulation de la commande...');
await annulerCommande(orderId).catch(() => {});
}
throw error;
}
}
// Utilisation
(async () => {
try {
const { number, code } = await obtenirCodeVerification('instagram', 'in');
console.log(`Prêt pour l'inscription avec ${number}, code : ${code}`);
} catch (error) {
console.error('Erreur :', error.message);
process.exit(1);
}
})();
PHP
<?php
$apiKey = getenv('SMSCODE_API_KEY');
$baseUrl = 'https://api.smscode.gg/v1';
function smscodeRequest($method, $endpoint, $data = null) {
global $apiKey, $baseUrl;
$ch = curl_init($baseUrl . $endpoint);
$headers = [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json'
];
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
} elseif ($method === 'DELETE') {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$decoded = json_decode($response, true);
if (!$decoded['success']) {
throw new Exception('API Error: ' . $decoded['error']['message']);
}
return $decoded['data'];
}
// Acheter un numéro
$order = smscodeRequest('POST', '/orders', [
'service' => 'google',
'country' => 'in'
]);
$orderId = $order['order_id'];
$numero = $order['number'];
echo "Numéro obtenu : $numero\n";
// Attendre le SMS avec polling
$timeout = 120;
$start = time();
$code = null;
while (time() - $start < $timeout) {
$orderStatus = smscodeRequest('GET', '/orders/' . $orderId);
if ($orderStatus['status'] === 'completed' && $orderStatus['code']) {
$code = $orderStatus['code'];
echo "Code reçu : $code\n";
break;
}
if (in_array($orderStatus['status'], ['expired', 'cancelled'])) {
die("Commande terminée sans SMS\n");
}
sleep(5);
}
if (!$code) {
echo "Timeout — annulation\n";
smscodeRequest('DELETE', '/orders/' . $orderId);
}
Intégration avec Playwright — Tests E2E complets
Un des cas d’usage les plus puissants de l’API SMSCode est l’intégration dans des tests E2E automatisés. Voici un exemple concret avec Playwright et TypeScript :
// tests/helpers/smscode.ts
const API_KEY = process.env.SMSCODE_API_KEY!;
const BASE_URL = 'https://api.smscode.gg/v1';
interface SmsCodeResult {
number: string;
code: string;
orderId: string;
}
export async function getVerificationNumber(
service: string,
country: string = 'in'
): Promise<SmsCodeResult> {
const orderResp = await fetch(`${BASE_URL}/orders`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ service, country })
});
const orderData = await orderResp.json();
if (!orderData.success) throw new Error(orderData.error.message);
const { order_id: orderId, number } = orderData.data;
// Polling jusqu'au code
for (let i = 0; i < 24; i++) {
await new Promise(r => setTimeout(r, 5000));
const statusResp = await fetch(`${BASE_URL}/orders/${orderId}`, {
headers: { 'Authorization': `Bearer ${API_KEY}` }
});
const statusData = await statusResp.json();
if (statusData.data.code) {
return { number, code: statusData.data.code, orderId };
}
}
// Annulation si timeout
await fetch(`${BASE_URL}/orders/${orderId}`, {
method: 'DELETE',
headers: { 'Authorization': `Bearer ${API_KEY}` }
});
throw new Error('SMS timeout après 120 secondes');
}
// tests/signup.spec.ts
import { test, expect } from '@playwright/test';
import { getVerificationNumber } from './helpers/smscode';
test('inscription complète avec vérification SMS', async ({ page }) => {
// Obtenir le numéro AVANT d'ouvrir le formulaire
const { number, code } = await getVerificationNumber('google', 'in');
await page.goto('https://accounts.google.com/signup');
// ... remplir le formulaire jusqu'à la demande de téléphone ...
await page.fill('#phoneNumberId', number.replace('+91', '')); // sans indicatif
await page.click('#next');
// Entrer le code reçu
await page.fill('#code', code);
await page.click('#next');
await expect(page.locator('.account-created')).toBeVisible({ timeout: 10000 });
});
Bonnes pratiques pour l’intégration API
Polling avec intervalle raisonnable. Évite de faire des requêtes toutes les secondes — ça consomme des ressources inutilement et peut déclencher des limites de débit. Un intervalle de 5 secondes est optimal. Pour des cas où la vitesse est critique, 3 secondes est le minimum raisonnable.
Toujours prévoir un timeout. Fixe un timeout maximum (120 secondes est raisonnable) et une logique d’annulation associée. Un SMS peut ne jamais arriver pour diverses raisons — prévois ce cas explicitement plutôt que de boucler indéfiniment.
Variables d’environnement obligatoires. Ne hard-code jamais ta clé API. Utilise process.env.SMSCODE_API_KEY (Node.js), os.environ.get("SMSCODE_API_KEY") (Python), ou getenv('SMSCODE_API_KEY') (PHP). Ajoute .env à ton .gitignore.
Gestion des erreurs par code. L’API retourne des codes d’erreur explicites dans error.code. Gère chaque code différemment plutôt que de tout traiter comme une erreur générique — NO_NUMBERS_AVAILABLE déclenche un retry sur un autre pays, INSUFFICIENT_BALANCE déclenche une alerte de rechargement.
Retry sur pays alternatifs. Si un pays retourne NO_NUMBERS_AVAILABLE, essaie immédiatement un pays alternatif plutôt que d’attendre. Définis une liste ordonnée de pays par préférence : ["in", "id", "ph", "kz"] pour les services peu sensibles au pays.
Annulation explicite en cas d’échec. Si ton process échoue avant de recevoir le SMS (exception non gérée, timeout, crash), annule la commande via DELETE /v1/orders/{id} pour récupérer le crédit. Implémente un finally ou un gestionnaire d’erreurs global pour cette annulation.
Vérification du solde en amont. Pour les workflows automatisés qui tournent en production, vérifie le solde au début de chaque session et configure une alerte si le solde passe sous un seuil minimum.
Codes d’erreur courants
| Code | Signification | Solution recommandée |
|---|---|---|
INSUFFICIENT_BALANCE | Solde insuffisant | Recharge le compte, configure une alerte de solde bas |
SERVICE_UNAVAILABLE | Service indisponible dans ce pays | Essaie un autre pays de ta liste de fallback |
NO_NUMBERS_AVAILABLE | Stock épuisé pour ce pays/service | Change de pays ou réessaie dans 5–10 minutes |
ORDER_NOT_FOUND | ID de commande invalide | Vérifie l’order_id — il peut avoir expiré |
ORDER_ALREADY_CANCELLED | Commande déjà annulée | Ne pas annuler deux fois, ignorer cette erreur |
INVALID_API_KEY | Clé API incorrecte ou expirée | Régénère la clé dans les paramètres du compte |
RATE_LIMIT_EXCEEDED | Trop de requêtes | Implémente un backoff exponentiel, réduis la fréquence |
Rate limits et scaling
L’API applique des limites de débit pour garantir la disponibilité du service pour tous les utilisateurs :
- 60 requêtes par minute par clé API (toutes routes confondues)
- 10 commandes actives simultanées par compte
Pour des workflows à très haut volume (automatisation à grande échelle, intégration dans un SaaS avec beaucoup d’utilisateurs), contacte le support SMSCode pour discuter de limites personnalisées adaptées à ton cas d’usage.
FAQ
L’API SMSCode est-elle compatible avec les intégrations SMS-Activate existantes ?
Oui. L’API SMSCode est compatible avec le format de l’API SMS-Activate, ce qui facilite la migration depuis ce service. Les codes de service et de pays peuvent différer légèrement — consulte la documentation API pour le mapping exact. La structure des requêtes et des réponses est similaire.
Comment gérer le cas où plusieurs tests s’exécutent en parallèle ?
Tu peux avoir jusqu’à 10 commandes actives simultanément par compte. Pour des suites de tests parallèles, assure-toi que chaque worker de test utilise sa propre instance de la fonction d’achat — chaque appel à POST /v1/orders crée une commande indépendante avec un numéro distinct. Les SMS sont correctement isolés par order_id.
L’API gère-t-elle automatiquement les remboursements ?
Oui. Si la commande expire sans SMS reçu (au bout de 15–20 minutes), le remboursement est automatique sans action de ta part. Si tu annules manuellement via DELETE /v1/orders/{id}, le remboursement est également immédiat. Tu n’as jamais à faire de demande de remboursement manuelle.
Y a-t-il un SDK officiel pour l’API SMSCode ?
Les exemples de code dans ce guide couvrent les cas d’usage les plus courants en Python, JavaScript/TypeScript et PHP. Des wrappers communautaires existent — consulte la documentation officielle sur smscode.gg pour les liens à jour. L’API étant REST standard avec JSON, elle s’intègre facilement dans n’importe quel environnement sans SDK dédié.
Comment tester l’API sans consommer de crédits réels ?
Il n’existe pas d’environnement sandbox — chaque commande consomme des crédits réels. Pour tester ton intégration à moindre coût, utilise des services avec des pays très économiques (Telegram + Kazakhstan à 0,005 $) et annule les commandes immédiatement si tu n’as pas besoin du code. Le coût de développement d’une intégration complète représente généralement moins d’1 $ en crédits de test.
Quelle est la différence entre l’API v1 et l’interface web ?
L’interface web et l’API v1 accèdent au même pool de numéros et aux mêmes prix — la différence est uniquement dans la façon d’interagir avec le service. L’interface web est conçue pour l’usage manuel visuel ; l’API est conçue pour l’automatisation programmatique. Un développeur peut utiliser les deux selon le contexte — l’API pour les tests automatisés, l’interface web pour les vérifications ponctuelles.