Clés Bearer
Envoyez Authorization: Bearer smp_live_… ou X-Api-Key. La clé complète n’est affichée qu’une fois et seule son empreinte est conservée. Jusqu’à 20 clés actives par compte, date d’expiration facultative et rotation en un clic.
Fonctionnement d’une intégration
L’API reproduit ce que fait le tableau de bord, dans le même ordre. Rien n’est débité tant que vous ne créez pas une commande, et chaque écriture est idempotente.
Dans votre tableau de bord, choisissez les autorisations dont la clé a besoin et, si vous le souhaitez, les IP autorisées à l’utiliser. La clé complète n’est affichée qu’une fois.
GET /v1/catalog/services renvoie chaque service publié avec le prix déjà exprimé dans la devise et le niveau de votre compte.
POST /v1/orders/preview valide le lien et la quantité et renvoie le montant exact, sans rien créer.
POST /v1/orders avec un Idempotency-Key. Le portefeuille est débité et la commande est routée vers le fournisseur de meilleure qualité mesurée.
Enregistrez un point de terminaison https et recevez des événements signés pour les changements de statut, les livraisons partielles, les fins, les remboursements et les recharges.
curl -X POST https://YOUR-DOMAIN/v1/orders \
-H "Authorization: Bearer smp_live_xxxxxxxxxx_..." \
-H "Idempotency-Key: 2b7c1d9e-order-1001" \
-H "Content-Type: application/json" \
-d '{"service":"<service_id>","link":"https://instagram.com/p/abc","quantity":1000}'Remplacez YOUR-DOMAIN par le domaine de cette boutique, la clé par la vôtre et <service_id> par un identifiant du catalogue.
Authentification et limites
Une clé est un identifiant côté serveur. Elle ne va jamais dans un navigateur, ne porte que les permissions que vous accordez, et vous pouvez la révoquer ou la remplacer à tout moment sans toucher à vos autres clés.
Envoyez Authorization: Bearer smp_live_… ou X-Api-Key. La clé complète n’est affichée qu’une fois et seule son empreinte est conservée. Jusqu’à 20 clés actives par compte, date d’expiration facultative et rotation en un clic.
Vous pouvez associer une clé à jusqu’à 20 adresses IP. Les requêtes venant d’une autre adresse sont refusées avec 403 FORBIDDEN.
Chaque clé hérite de la limite de requêtes par minute de votre niveau client. Chaque réponse porte RateLimit-Limit, RateLimit-Remaining et RateLimit-Reset ; au-delà de la limite, vous recevez 429 avec Retry-After.
Limite en vigueur pour le niveau Revendeur1 200 requêtes par minute
Chaque clé ne porte que les autorisations que vous accordez. Un appel hors de ses autorisations est refusé avec 403 FORBIDDEN.
| Autorisation | Ce qu’il fait |
|---|---|
catalog:read | Lister les services et les prix |
orders:read | Lire les commandes |
orders:write | Créer des commandes, recharger et annuler |
wallet:read | Lire les soldes |
assets:read | Lister vos annonces et offres |
assets:write | Créer et modifier des annonces, la vérification et la disponibilité |
transactions:write | Enregistrer les étapes de remise des transactions |
Idempotence
POST /v1/orders et POST /v1/orders/batch exigent un en-tête Idempotency-Key de 8 à 120 caractères. Répéter un appel avec la même clé renvoie la même commande sans débiter à nouveau. Réutiliser une clé avec un corps différent est refusé avec 409 IDEMPOTENCY_KEY_REUSE. Dans un lot, chaque élément est identifié par la clé du lot et son index.
HTTP/1.1 409 Conflict
X-Request-Id: req_<hex>
{
"error": {
"code": "IDEMPOTENCY_KEY_REUSE",
"message": "..."
},
"request_id": "req_<hex>"
}Points de terminaison
Tous les chemins sont sous /v1 sur le domaine de cette boutique. Les montants sont toujours des chaînes décimales avec une devise ISO 4217, jamais des nombres flottants. Les schémas complets de requête et de réponse sont dans le fichier OpenAPI.
| Méthode | Chemin | Autorisation | Ce qu’il fait |
|---|---|---|---|
| GET | /v1/catalog/platforms | catalog:read | Plateformes qui ont actuellement des services publiés |
| GET | /v1/catalog/services | catalog:read | Services avec le prix dans votre devise et votre niveau ; filtre par plateforme |
| GET | /v1/catalog/services/{id} | catalog:read | Un service avec son schéma de champs |
| Méthode | Chemin | Autorisation | Ce qu’il fait |
|---|---|---|---|
| POST | /v1/orders/preview | orders:write | Valider et chiffrer sans créer ni débiter |
| POST | /v1/ordersIdempotency-Key obligatoire | orders:write | Créer une commande : débite le portefeuille et route vers le meilleur fournisseur |
| GET | /v1/orders | orders:read | Lister les commandes, des plus récentes aux plus anciennes, avec pagination par curseur |
| POST | /v1/orders/batchIdempotency-Key obligatoire | orders:write | Jusqu’à 100 commandes en un appel, chacune avec son propre résultat |
| GET | /v1/orders/{id} | orders:read | Récupérer une commande par identifiant |
| POST | /v1/orders/{id}/refill | orders:write | Demander une recharge dans la période de garantie |
| POST | /v1/orders/{id}/cancel | orders:write | Demander l’annulation ; remboursée dès que le fournisseur confirme |
| Méthode | Chemin | Autorisation | Ce qu’il fait |
|---|---|---|---|
| GET | /v1/wallet/balance | wallet:read | Soldes par devise : disponible, argent, bonus et réservé |
| Méthode | Chemin | Autorisation | Ce qu’il fait |
|---|---|---|---|
| POST | /v1/assets | assets:write | Créer un brouillon d’annonce ; publiée après vérification et modération |
| GET | /v1/assets | assets:read | Vos annonces |
| PATCH | /v1/assets/{id} | assets:write | Modifier une annonce (corps complet ; If-Match pour le verrouillage optimiste) |
| POST | /v1/assets/batch | assets:write | Importer jusqu’à 1 000 annonces, identifiées par external_ref |
| POST | /v1/assets/{id}/verify | assets:write | Démarrer (method) ou vérifier (verification_id) une vérification de propriété |
| POST | /v1/assets/{id}/availability | assets:write | Masquer ou afficher une annonce (pas pendant une négociation) |
| Méthode | Chemin | Autorisation | Ce qu’il fait |
|---|---|---|---|
| GET | /v1/offers | assets:read | Offres reçues sur vos annonces |
| Méthode | Chemin | Autorisation | Ce qu’il fait |
|---|---|---|---|
| POST | /v1/transactions/{id}/handoff | transactions:write | Marquer une étape de procédure, ajouter un élément sécurisé ou terminer la remise |
HTTP/1.1 201 Created
X-Request-Id: req_<hex>
X-Api-Version: 2026-09-23
RateLimit-Limit: <limit> RateLimit-Remaining: <n> RateLimit-Reset: <seconds>
{
"id": "SMP-7K2Q9XHT",
"status": "routing",
"service": "<service_id>",
"link": "https://instagram.com/p/abc",
"quantity": 1000,
"charge": "<decimal>",
"refunded": "0",
"currency": "USD",
"start_count": null,
"remains": null,
"delivered": null,
"refill_until": null,
"created_at": "2026-09-23T12:00:00.000Z",
"updated_at": "2026-09-23T12:00:00.000Z"
}Webhooks
Enregistrez un point de terminaison https sur un domaine public et choisissez les événements souhaités. Chaque envoi est signé avec le secret de votre point de terminaison, affiché une seule fois à sa création.
POST /webhooks/orders HTTP/1.1
Content-Type: application/json
Webhook-Id: <event id>
Webhook-Timestamp: 1790000000
Webhook-Signature: t=1790000000,v1=<hex HMAC-SHA256(secret, "1790000000.<body>")>
{ "id": "<event id>", "type": "order.partial", "created_at": "2026-09-23T12:05:00.000Z",
"data": { "orderId": "SMP-7K2Q9XHT", ... } }import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyWebhook(secret, headers, rawBody) {
const t = headers['webhook-timestamp'];
const v1 = (headers['webhook-signature'] ?? '')
.split(',').find((p) => p.startsWith('v1='))?.slice(3) ?? '';
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300; // 5 minutes
return fresh && expected.length === v1.length
&& timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}Les événements sont écrits dans une file d’attente, dans la même transaction de base de données que le changement qui les a provoqués, donc rien n’est perdu si un envoi échoue. Les envois échoués sont retentés après 1 min, 5 min, 30 min, 2 h, 6 h, 12 h et 24 h avant d’être marqués comme définitivement en échec.
order.createdorder.status_changedorder.partialorder.completedorder.refundedorder.refill_updateddeposit.confirmedoffer.createdoffer.updatedreservation.createdtransaction.updatedpayout.updatedlisting.updateddispute.updatedCompatibilité
POST /api/v2 implémente le contrat commun « SMM API v2 » : envoyez la clé et l’action en champs de formulaire ou en JSON. Mêmes clés, autorisations et limites que /v1 ; seul le format change, et les erreurs sont renvoyées sous la forme { "error": "message" }.
Les panneaux n’envoient pas de clé d’idempotence : elle est donc dérivée du contenu de la commande et de la minute en cours ; la fenêtre de doublons couvre le reste.
curl -X POST https://YOUR-DOMAIN/api/v2 \
-d key=smp_live_xxxxxxxxxx_... \
-d action=add \
-d service=<service_id> \
-d link=https://instagram.com/p/abc \
-d quantity=1000
{ "order": "SMP-7K2Q9XHT" }Erreurs
Chaque réponse non 2xx a le même corps. Intégrez-vous sur le code, pas sur le message : les messages peuvent changer, pas les codes. Le request_id est aussi envoyé dans l’en-tête X-Request-Id.
HTTP/1.1 400 Bad Request
X-Request-Id: req_<hex>
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request.",
"details": {
"fields": [{ "path": "quantity", "message": "..." }]
}
},
"request_id": "req_<hex>"
}| Code | HTTP | Signification |
|---|---|---|
VALIDATION_ERROR | 400 | Corps ou en-têtes invalides ; details.fields liste chaque chemin et problème |
UNAUTHORIZED | 401 | Clé absente, invalide, révoquée ou expirée |
INSUFFICIENT_FUNDS | 402 | Solde du portefeuille insuffisant pour le devis |
FORBIDDEN | 403 | La clé n’a pas l’autorisation, IP non autorisée, sous-utilisateur sans permission ou compte suspendu |
NOT_FOUND | 404 | Commande, service ou annonce inexistant pour ce compte |
CONFLICT | 409 | Conflit d’état, comme la limite de clés actives |
INVALID_TRANSITION | 409 | La commande ou la transaction ne peut pas passer à cet état |
DUPLICATE_ORDER | 409 | Même service, lien et quantité dans la fenêtre de doublons |
IDEMPOTENCY_KEY_REUSE | 409 | Idempotency-Key déjà utilisée avec un corps différent |
ALREADY_RESERVED | 409 | L’actif est réservé par un autre acheteur |
POLICY_BLOCKED | 422 | Service ou pays bloqué par la politique de la plateforme |
MARGIN_GUARD | 422 | Aucun fournisseur ne peut traiter cette commande au prix publié |
UNPROCESSABLE | 422 | La requête est valide mais ne peut pas être exécutée |
RATE_LIMITED | 429 | Limite par clé atteinte ; attendez les secondes indiquées dans Retry-After |
INTERNAL | 500 | Erreur inattendue ; contactez l’assistance avec le request_id |
PROVIDER_ERROR | 502 | Échec du fournisseur ; la commande est retentée ou remboursée |
NO_ROUTE | 503 | Aucune route fournisseur disponible pour le moment ; réessayez plus tard |
NOT_CONFIGURED | 503 | Fonctionnalité non configurée sur cette boutique |
Qui peut l’utiliser
Les clés API et les points de terminaison de webhook sont créés par le titulaire du compte sur l’offre Revendeur. Les commandes passées avec une clé sont débitées du portefeuille du compte et apparaissent dans le même tableau de bord que les commandes manuelles. Les sous-utilisateurs ne peuvent pas créer de clés.
Que vous exploitiez un panneau qui a besoin d’un fournisseur fiable, un outil d’agence qui passe des commandes pour des clients, ou un inventaire vendeur qui doit rester synchronisé avec la marketplace, l’intégration suit le même schéma : une clé restreinte, des écritures idempotentes, et des événements que vous vérifiez avant de leur faire confiance.
Chaque point de terminaison se trouve sous /v1 sur le domaine de la boutique avec laquelle vous intégrez. Les réponses sont en JSON, les montants sont des chaînes décimales associées à une devise ISO 4217, et les horodatages sont au format ISO 8601. Chaque réponse porte un en-tête X-Api-Version avec la date du contrat avec lequel vous communiquez, et un X-Request-Id que vous pouvez citer à l’assistance. Les erreurs ont toujours le même corps : un objet d’erreur avec un code stable, un message lisible et des détails facultatifs, ainsi que le request_id.
Le fichier OpenAPI 3.1 décrit chaque chemin, chaque schéma et chaque code d’erreur. Importez-le dans votre client HTTP ou votre générateur et vous obtenez des requêtes typées pour le catalogue, les commandes, le portefeuille, les annonces, les offres et les remises de transactions.
Une clé est créée par le titulaire du compte sur l’offre Revendeur et n’est affichée qu’une fois ; seule une empreinte est conservée. Lors de la création, vous choisissez ses autorisations, une liste blanche d’IP facultative (jusqu’à 20 adresses) et une expiration facultative. La rotation crée une nouvelle clé avec les mêmes autorisations et révoque l’ancienne, ce qui permet de renouveler les identifiants sans interruption. Les commandes passées avec une clé sont débitées du portefeuille du compte et apparaissent dans le même tableau de bord que les commandes manuelles, avec leur source marquée comme API.
Chaque clé hérite de la limite de requêtes par minute du niveau de client du compte. Les en-têtes RateLimit-Limit, RateLimit-Remaining et RateLimit-Reset indiquent où vous en êtes ; au-delà de la limite, l’API renvoie 429 avec un en-tête Retry-After, et la bonne réaction est d’attendre exactement ce délai.
La création de commande est le seul appel qui déplace de l’argent, elle est donc protégée deux fois. D’abord, l’en-tête Idempotency-Key est obligatoire : répéter une requête avec la même clé renvoie la commande d’origine sans second débit, et réutiliser la clé avec un corps différent est refusé avec 409 IDEMPOTENCY_KEY_REUSE. Ensuite, une fenêtre de doublons détecte le même service, le même lien et la même quantité renvoyés dans un court intervalle sans correspondance de clé, et renvoie 409 DUPLICATE_ORDER.
Les lots acceptent jusqu’à 100 commandes par appel. Chaque élément est validé et débité séparément, identifié par la clé du lot et son index, et la réponse liste un résultat par élément, si bien qu’une ligne défectueuse ne bloque jamais les autres. Utilisez d’abord POST /v1/orders/preview lorsque vous voulez le montant exact et le résultat de validation sans rien créer.
Chaque changement d’état est écrit dans une file d’attente, dans la même transaction de base de données que le changement lui-même, et un distributeur le livre à votre point de terminaison https avec trois en-têtes : Webhook-Id, Webhook-Timestamp et Webhook-Signature. La signature est un HMAC-SHA256 de l’horodatage, d’un point et du corps brut, calculé avec le secret du point de terminaison affiché une seule fois à la création. Vérifiez-la en temps constant, rejetez les horodatages de plus de cinq minutes et dédoublonnez par Webhook-Id, car un événement réessayé porte le même identifiant.
Les envois qui ne reçoivent pas de 2xx sont réessayés après 1 minute, 5 minutes, 30 minutes, 2 heures, 6 heures, 12 heures et 24 heures avant d’être marqués comme définitivement en échec. Répondez vite et traitez de façon asynchrone ; un gestionnaire lent est la cause la plus fréquente de traitement en double.
Si votre panneau parle déjà le format répandu « SMM API v2 », vous pouvez ajouter cette boutique comme fournisseur en collant l’URL /api/v2 et votre clé. Les actions services, add, status, balance, refill, refill_status et cancel sont prises en charge, les prix reviennent dans la devise et le niveau de votre compte, et les erreurs utilisent la forme plate { "error": "message" } attendue par ces panneaux. L’idempotence est dérivée du contenu de la commande et de la minute en cours, si bien que les doubles envois accidentels dans la même minute sont fusionnés.
L’offre Revendeur. Les clés API et les points de terminaison de webhook sont créés par le titulaire du compte ; les sous-utilisateurs ne peuvent pas les créer. Les clés sont des identifiants côté serveur et ne doivent jamais être intégrées dans un navigateur ou une application mobile.
Envoyez la clé dans Authorization: Bearer smp_live_… ou dans un en-tête X-Api-Key. La clé doit porter l’autorisation requise par le point de terminaison, par exemple orders:write pour créer une commande ou catalog:read pour lister les services.
Renvoyez-la avec la même Idempotency-Key. Vous recevez la commande d’origine et rien n’est débité deux fois. Si vous envoyez un corps différent avec la même clé, l’API répond 409 IDEMPOTENCY_KEY_REUSE.
Calculez HMAC-SHA256 avec le secret de votre point de terminaison sur la chaîne formée par Webhook-Timestamp, un point et le corps brut, puis comparez-le en temps constant à la valeur v1 de Webhook-Signature. Rejetez les horodatages de plus de 5 minutes et dédoublonnez par Webhook-Id.
Chaque clé hérite de la limite de requêtes par minute de votre niveau de client, indiquée sur cette page. Les en-têtes RateLimit-* signalent la fenêtre en cours, et une réponse 429 contient Retry-After en secondes.
Oui. GET /v1/catalog/services renvoie le prix déjà converti dans la devise de votre compte avec votre remise de niveau, et POST /v1/orders/preview renvoie le montant exact, y compris les remises au volume et les codes promo, avant que vous ne vous engagiez.
Oui. Avec l’autorisation assets:write, vous pouvez créer et modifier des annonces, en importer jusqu’à 1 000 d’un coup, lancer une vérification de propriété et changer la disponibilité ; assets:read liste vos annonces et vos offres, et transactions:write enregistre les étapes de remise d’une transaction.
Avec l’offre Revendeur, créez une clé, téléchargez le fichier OpenAPI et envoyez votre première commande depuis votre propre système.
Nous ne vendons jamais d’avis ni de notes. Certaines plateformes restreignent dans leurs conditions les services d’engagement ou les transferts de comptes ; vous êtes responsable des règles de chaque plateforme que vous utilisez.