Documentation API
Accès programmatique aux numéros virtuels, commandes et solde du compte.
⟩ Authentification
Toutes les requêtes API nécessitent un Bearer token. Générez-en un depuis les Paramètres du compte dans le tableau de bord, puis incluez-le dans chaque requête :
Les requêtes sans token valide reçoivent une réponse 401 UNAUTHORIZED.
⟩ URL de base
Tous les chemins d'endpoints ci-dessous sont relatifs à :
⟩ Format de réponse
Chaque réponse renvoie du JSON avec une enveloppe cohérente. Toutes les réponses incluent un en-tête x-request-id pour le débogage.
{
"success": true,
"data": { ... }
} {
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human-readable message"
}
} /catalog/countries Renvoie la liste de tous les pays disponibles.
Paramètres
Aucun
Exemple de requête
curl -s https://api.smscode.gg/v1/catalog/countries \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/catalog/countries", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/catalog/countries",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Exemple de réponse
{
"success": true,
"data": [
{
"id": 6,
"code": "ID",
"name": "Indonesia",
"dial_code": "+62",
"emoji": "🇮🇩",
"active": true
}
]
} /catalog/services Renvoie la liste des services (plateformes) disponibles. Filtrage optionnel par pays.
Paramètres de requête
| Nom | Type | Requis | Description |
|---|---|---|---|
country_id | integer | Non | Filtrer les services disponibles pour ce pays |
Exemple de requête
curl -s "https://api.smscode.gg/v1/catalog/services?country_id=6" \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/catalog/services?country_id=6", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/catalog/services",
params={"country_id": 6},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Exemple de réponse
{
"success": true,
"data": [
{
"id": 3,
"code": "wa",
"name": "WhatsApp",
"active": true
}
]
} /catalog/products Renvoie une liste paginée des produits disponibles. Filtrage par pays et/ou plateforme.
Paramètres de requête
| Nom | Type | Requis | Description |
|---|---|---|---|
country_id | integer | Non | Filtrer par identifiant de pays |
platform_id | integer | Non | Filtrer par identifiant de plateforme/service |
sort | string | Non | Ordre de tri : price_asc (défaut), price_desc, available_asc, available_desc, name_asc, name_desc |
limit | integer | Non | Résultats par page (1-10 000, défaut 1 000) |
page | integer | Non | Numéro de page (min. 1, défaut 1) |
Exemple de requête
curl -s "https://api.smscode.gg/v1/catalog/products?country_id=6&platform_id=3&limit=10&page=1" \
-H "Authorization: Bearer YOUR_API_TOKEN" const params = new URLSearchParams({
country_id: "6", platform_id: "3", limit: "10", page: "1",
});
const res = await fetch(`https://api.smscode.gg/v1/catalog/products?${params}`, {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/catalog/products",
params={"country_id": 6, "platform_id": 3, "limit": 10, "page": 1},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Exemple de réponse
{
"success": true,
"data": [
{
"id": 142,
"name": "WhatsApp Indonesia",
"country_id": 6,
"platform_id": 3,
"available": 42,
"price": 15000,
"active": true
}
],
"meta": { "page": 1, "limit": 10, "count": 1 }
} /catalog/exchange-rate Renvoie le taux de change actuel pour une paire de devises. Utile pour la conversion des prix.
Paramètres de requête
| Nom | Type | Requis | Description |
|---|---|---|---|
pair | string | Non | Paire de devises (défaut : USD/IDR) |
Exemple de requête
curl -s "https://api.smscode.gg/v1/catalog/exchange-rate?pair=USD/IDR" \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/catalog/exchange-rate?pair=USD/IDR", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/catalog/exchange-rate",
params={"pair": "USD/IDR"},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Exemple de réponse
{
"success": true,
"data": {
"pair": "USD/IDR",
"base_currency": "USD",
"quote_currency": "IDR",
"rate": 16250
}
} /balance Renvoie le solde du compte de l'utilisateur authentifié en IDR.
Paramètres
Aucun
Exemple de requête
curl -s https://api.smscode.gg/v1/balance \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/balance", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/balance",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Exemple de réponse
{
"success": true,
"data": {
"currency": "IDR",
"balance": 500000
}
} /orders Renvoie la liste des commandes de l'utilisateur authentifié, triées par date décroissante. Filtrage par statut et pagination via offset.
Paramètres de requête
| Nom | Type | Requis | Description |
|---|---|---|---|
limit | integer | Non | Nombre max. de résultats (1-100, défaut 20) |
offset | integer | Non | Nombre de résultats à ignorer (défaut 0) |
status | string | Non | Filtrer par statut : ACTIVE, OTP_RECEIVED, COMPLETED, CANCELED, EXPIRED (insensible à la casse) |
Exemple de requête
curl -s "https://api.smscode.gg/v1/orders?limit=5&status=ACTIVE" \
-H "Authorization: Bearer YOUR_API_TOKEN" const params = new URLSearchParams({
limit: "5", status: "ACTIVE", offset: "0",
});
const res = await fetch(`https://api.smscode.gg/v1/orders?${params}`, {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/orders",
params={"limit": 5, "status": "ACTIVE", "offset": 0},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Exemple de réponse
{
"success": true,
"data": [
{
"id": 1001,
"status": "ACTIVE",
"created_at": "2026-02-25T10:00:00Z",
"product_id": 142,
"phone_number": "+6281234567890",
"amount": 15000,
"otp_code": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:20:00Z",
"canceled_at": null,
"failed_reason": null
}
]
} /orders/{id} Renvoie une commande par son identifiant. Ne renvoie que les commandes de l'utilisateur authentifié.
Paramètres de chemin
| Nom | Type | Requis | Description |
|---|---|---|---|
id | integer | Oui | Identifiant de commande (paramètre de chemin) |
Exemple de requête
curl -s https://api.smscode.gg/v1/orders/1001 \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/orders/1001", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/orders/1001",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Exemple de réponse
{
"success": true,
"data": {
"id": 1001,
"status": "OTP_RECEIVED",
"created_at": "2026-02-25T10:00:00Z",
"product_id": 142,
"phone_number": "+6281234567890",
"amount": 15000,
"otp_code": "123456",
"otp_received_at": "2026-02-25T10:05:00Z",
"expires_at": "2026-02-25T10:20:00Z",
"canceled_at": null,
"failed_reason": null
}
} /orders/active Liste toutes les commandes actuellement actives (ACTIVE + OTP_RECEIVED). Utilisez cet endpoint pour surveiller les mises à jour de statut OTP.
Paramètres
Aucun
Exemple de requête
curl -s https://api.smscode.gg/v1/orders/active \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/orders/active", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/orders/active",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Exemple de réponse
{
"success": true,
"data": [
{
"id": 1001,
"status": "OTP_RECEIVED",
"otp_code": "123456",
"otp_message": "Your verification code is 123456",
"otp_received_at": "2026-02-25T10:05:00Z",
"expires_at": "2026-02-25T10:20:00Z",
"failed_reason": null
},
{
"id": 1002,
"status": "ACTIVE",
"otp_code": null,
"otp_message": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:50:00Z",
"failed_reason": null
}
]
} /orders/create Crée une nouvelle commande de numéro virtuel. Débite le solde automatiquement. Prend en charge un en-tête Idempotency-Key optionnel pour éviter les commandes en double lors des nouvelles tentatives réseau.
Corps de la requête
| Nom | Type | Requis | Description |
|---|---|---|---|
product_id | integer | Oui | Identifiant du produit à commander |
quantity | integer | Non | Quantité (1-100, défaut 1) |
Passez un en-tête Idempotency-Key (toute chaîne unique) pour réessayer les requêtes en toute sécurité sans créer de doublons.
Exemple de requête
curl -s -X POST https://api.smscode.gg/v1/orders/create \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-request-id-123" \
-d '{"product_id":142,"quantity":1}' const res = await fetch("https://api.smscode.gg/v1/orders/create", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json",
"Idempotency-Key": "unique-request-id-123",
},
body: JSON.stringify({ product_id: 142, quantity: 1 }),
});
const data = await res.json(); import requests
res = requests.post("https://api.smscode.gg/v1/orders/create",
json={"product_id": 142, "quantity": 1},
headers={
"Authorization": "Bearer YOUR_API_TOKEN",
"Idempotency-Key": "unique-request-id-123",
})
data = res.json() Exemple de réponse
{
"success": true,
"data": {
"orders": [
{
"id": 1002,
"status": "ACTIVE",
"phone_number": "+6281234567891",
"otp_code": null,
"otp_received_at": null,
"expires_at": "2026-02-25T10:50:00Z",
"failed_reason": null
}
],
"failed_count": 0
}
} /orders/cancel Annule une commande active. Le coût de la location est remboursé sur le solde de votre compte.
Corps de la requête
| Nom | Type | Requis | Description |
|---|---|---|---|
id | integer | Oui | Identifiant de la commande à annuler |
Exemple de requête
curl -s -X POST https://api.smscode.gg/v1/orders/cancel \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id":1001}' const res = await fetch("https://api.smscode.gg/v1/orders/cancel", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({ id: 1001 }),
});
const data = await res.json(); import requests
res = requests.post("https://api.smscode.gg/v1/orders/cancel",
json={"id": 1001},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Exemple de réponse
{
"success": true,
"data": {
"order_id": 1001,
"status": "CANCELED",
"refund_amount": 15000,
"new_balance": 515000
}
} /orders/finish Marque une commande comme terminée après réception de l'OTP. Cela libère le numéro immédiatement au lieu d'attendre l'expiration.
Corps de la requête
| Nom | Type | Requis | Description |
|---|---|---|---|
id | integer | Oui | Identifiant de la commande à finaliser |
Exemple de requête
curl -s -X POST https://api.smscode.gg/v1/orders/finish \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id":1001}' const res = await fetch("https://api.smscode.gg/v1/orders/finish", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({ id: 1001 }),
});
const data = await res.json(); import requests
res = requests.post("https://api.smscode.gg/v1/orders/finish",
json={"id": 1001},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Exemple de réponse
{
"success": true,
"data": {
"order_id": 1001,
"status": "COMPLETED"
}
} /orders/resend Demande à la plateforme de renvoyer le SMS au numéro loué. Toutes les plateformes ne prennent pas en charge le renvoi — vérifiez le champ resent dans la réponse.
Corps de la requête
| Nom | Type | Requis | Description |
|---|---|---|---|
id | integer | Oui | Identifiant de la commande pour le renvoi SMS |
Exemple de requête
curl -s -X POST https://api.smscode.gg/v1/orders/resend \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id":1001}' const res = await fetch("https://api.smscode.gg/v1/orders/resend", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({ id: 1001 }),
});
const data = await res.json(); import requests
res = requests.post("https://api.smscode.gg/v1/orders/resend",
json={"id": 1001},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Exemple de réponse
{
"success": true,
"data": {
"order_id": 1001,
"status": "ACTIVE",
"resent": true
}
} /webhook Renvoie votre configuration actuelle de notifications webhook.
Paramètres
Aucun
Exemple de requête
curl -s https://api.smscode.gg/v1/webhook \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/webhook", {
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.get("https://api.smscode.gg/v1/webhook",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Exemple de réponse
{
"success": true,
"data": {
"webhook_url": "https://example.com/webhook",
"webhook_secret": "a1b2c3d4e5f6..."
}
} /webhook Met à jour votre URL webhook et/ou votre secret. Un secret est généré automatiquement lorsque vous définissez une URL pour la première fois. Envoyez une chaîne vide pour effacer. L'URL doit utiliser HTTPS.
Corps de la requête
| Nom | Type | Requis | Description |
|---|---|---|---|
webhook_url | string | Non | URL HTTPS pour recevoir les événements webhook (chaîne vide pour effacer) |
webhook_secret | string | Non | Secret partagé pour la signature HMAC-SHA256 (généré automatiquement s'il est omis lors de la première configuration) |
Au moins un champ est requis.
Exemple de requête
curl -s -X PATCH https://api.smscode.gg/v1/webhook \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"webhook_url":"https://example.com/webhook"}' const res = await fetch("https://api.smscode.gg/v1/webhook", {
method: "PATCH",
headers: {
Authorization: "Bearer YOUR_API_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({ webhook_url: "https://example.com/webhook" }),
});
const data = await res.json(); import requests
res = requests.patch("https://api.smscode.gg/v1/webhook",
json={"webhook_url": "https://example.com/webhook"},
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Exemple de réponse
{
"success": true,
"data": {
"webhook_url": "https://example.com/webhook",
"webhook_secret": "a1b2c3d4e5f6..."
}
} /webhook/test Envoie un événement test à votre URL webhook configurée. Renvoie le code de statut HTTP de votre serveur. Utile pour vérifier que votre endpoint fonctionne avant la mise en production.
Paramètres
Aucun
Exemple de requête
curl -s -X POST https://api.smscode.gg/v1/webhook/test \
-H "Authorization: Bearer YOUR_API_TOKEN" const res = await fetch("https://api.smscode.gg/v1/webhook/test", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json(); import requests
res = requests.post("https://api.smscode.gg/v1/webhook/test",
headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json() Exemple de réponse
{
"success": true,
"data": {
"status_code": 200
}
} ⟩ Notifications webhook
Configurez une URL webhook pour recevoir des notifications push en temps réel pour les événements de commande au lieu du polling. C'est l'approche recommandée pour les scripts de bot.
Événements
| Événement | Déclencheur |
|---|---|
order.otp_received | Code OTP livré au numéro loué |
order.completed | Commande marquée comme terminée (manuellement ou par expiration) |
order.expired | Commande expirée sans OTP (solde remboursé) |
order.canceled | Commande annulée par l'utilisateur (solde remboursé) |
Payload
{
"event": "order.otp_received",
"timestamp": "2026-02-25T12:00:00Z",
"data": {
"order_id": 1001,
"phone_number": "+628123456789",
"otp_code": "1234",
"otp_message": "Your verification code is 1234",
"product_id": 42,
"country": "Indonesia",
"platform": "WhatsApp"
}
} Vérification de la signature
Chaque requête webhook inclut un en-tête X-Webhook-Signature avec une signature HMAC-SHA256 du corps de la requête, utilisant votre webhook_secret comme clé :
Vérifiez cette signature côté serveur pour vous assurer que la requête est authentique. La livraison est de type « fire-and-forget » avec un délai d'expiration de 3 secondes et sans nouvelle tentative.
⟩ Limites de débit
Les requêtes API sont soumises à des limites de débit par groupe d'endpoints. Le dépassement de la limite renvoie un code 429 Too Many Requests avec un en-tête Retry-After indiquant le nombre de secondes à attendre.
| Groupe d'endpoints | Limite | Fenêtre |
|---|---|---|
| Catalogue (pays, services, produits, taux de change) | 1 200 requêtes | 60 secondes |
| Solde | 600 requêtes | 60 secondes |
| Lecture de commandes (liste, détail, actives) | 1 200 requêtes | 60 secondes |
| Création de commande | 1 200 requêtes | 60 secondes |
| Annulation de commande | 600 requêtes | 60 secondes |
| Actions sur les commandes (finaliser, renvoyer) | 600 requêtes | 60 secondes |
| Configuration webhook (lecture, mise à jour, test) | 120 requêtes | 60 secondes |
⟩ Codes d'erreur
Les réponses d'erreur incluent l'un de ces codes dans error.code :
| Code | HTTP | Description |
|---|---|---|
UNAUTHORIZED | 401 | Token API manquant ou invalide |
FORBIDDEN | 403 | Accès refusé |
NOT_FOUND | 404 | Ressource introuvable (commande, taux de change, etc.) |
CONFLICT | 409 | Requête en double ou conflit de ressource |
INSUFFICIENT_BALANCE | 409 | Solde insuffisant pour créer la commande |
VALIDATION_ERROR | 422 | Les paramètres de la requête n'ont pas passé la validation |
RATE_LIMIT_EXCEEDED | 429 | Trop de requêtes (vérifiez l'en-tête Retry-After) |
INTERNAL_ERROR | 500 | Erreur interne du serveur |
PROVIDER_ERROR | 422 | Le fournisseur SMS en amont a rejeté la requête |
CANCEL_TOO_EARLY | 409 | Commande trop récente pour être annulée — patientez 2 minutes |
SERVICE_UNAVAILABLE | 503 | Service temporairement indisponible (maintenance) |