Développeurs2026-11Aperçu

API NinjaBuy Business

Importez des produits de Taobao, Weidian et 1688, gardez leur prix et leur stock synchronisés, et suivez chaque commande du vendeur en Chine, via le contrôle dans notre entrepôt, jusqu’à la porte de votre client. JSON sur HTTPS, un compte, un solde.

URL de base

Chaque route de ce site se trouve sous une même URL de base. L’app Shopify et tout ce que vous construisez appellent les mêmes routes : ce que fait l’app, votre code peut le faire aussi.

https://www.ninjabuy.com/api/v1

Vous préférez demander à un assistant IA ? Le même compte fonctionne via MCP sur https://www.ninjabuy.com/mcp : Assistants IA (MCP).

Catalogue
Commandes
Compte
Votre premier appel
curl "https://www.ninjabuy.com/api/v1/balance" \
  -H "Authorization: Bearer $NINJABUY_API_KEY" \
  -H "NinjaBuy-Version: 2026-11"

Authentification

Envoyez une clé API comme jeton bearer à chaque requête. Les clés commencent par nb_. Pendant la préversion, notre équipe les émet : une fois votre compte Business configuré, nous envoyons chaque clé une seule fois, par le canal de votre choix, avec les scopes demandés. Demandez-nous d’en révoquer une et elle cesse de fonctionner dès la requête suivante.

Gardez les clés sur votre serveur. Une clé dans un navigateur, une app ou un dépôt public peut être lue par n’importe qui, et elle peut dépenser votre solde.

Une app qui agit pour d’autres vendeurs NinjaBuy utilise plutôt OAuth 2.1 : enregistrement dynamique du client, flux authorization code avec PKCE (S256), et l’écran d’approbation du vendeur lui-même. Son jeton d’accès va dans le même en-tête et fonctionne sur les mêmes routes. Les jetons d’accès durent une heure ; les jetons de rafraîchissement les renouvellent pendant sept jours. Les assistants IA se connectent de la même façon (MCP).

products:readscope
Lire les imports, produits, variantes et règles de synchronisation.
products:writescope
Importer, modifier, envoyer et supprimer des produits ; modifier les règles de synchronisation.
inventory:readscope
Lire les niveaux de stock.
orders:readscope
Lire les commandes, commandes d’exécution et envois.
orders:writescope
Créer, mettre en attente, débloquer et annuler des commandes. Dépense votre solde.
balance:readscope
Lire le solde et ses transactions.
webhooks:writescope
Gérer les endpoints de webhook.

Un appel hors des scopes d’une clé répond 403 insufficient-scope et indique le scope requis.

En-tête
Authorization: Bearer nb_7Qk2...vX9e
Response 401
HTTP/2 401

{
  "type": "https://www.ninjabuy.com/api/v1/problems/unauthorized",
  "title": "Unauthorized",
  "status": 401,
  "detail": "The API key is missing, wrong, expired or revoked.",
  "request_id": "req_7Hq2Lw9c"
}

Versions

Le chemin porte la version majeure, /v1. À l’intérieur, des versions datées changent les champs et le comportement. Fixez celle sur laquelle vous avez construit avec l’en-tête NinjaBuy-Version ; chaque réponse indique la version utilisée dans le même en-tête.

2026-11 est la version actuelle, en préversion : les noms et les champs peuvent encore changer avant qu’elle soit déclarée stable. Chaque changement figure dans le journal des modifications, et nous prévenons par e-mail chaque détenteur de clé avant tout changement susceptible de le casser.

Dans une version, nous ne faisons qu’ajouter : nouvelles routes, nouveaux paramètres facultatifs, nouveaux champs dans les réponses et nouveaux types d’événements. Construisez votre client pour ignorer les champs qu’il ne connaît pas.

Fixer une version
GET /api/v1/orders
NinjaBuy-Version: 2026-11

HTTP/2 200
NinjaBuy-Version: 2026-11

Requêtes et réponses

  • Envoyez du JSON avec Content-Type: application/json ; les réponses sont du JSON en UTF-8. Les erreurs sont en application/problem+json.
  • Un montant est un objet avec une chaîne décimale et une devise : { "amount": "264.20", "currency": "CNY" }. Ce que NinjaBuy facture est en CN¥ ; vos prix de vente sont dans la devise de votre boutique.
  • Les identifiants sont des chaînes avec un préfixe qui indique leur type (prd_, ord_, shp_). Traitez-les comme opaques.
  • Les dates sont en ISO 8601, en UTC. Les pays sont des codes ISO à deux lettres.
  • Chaque réponse porte un en-tête X-Request-Id, et chaque erreur porte le même identifiant en request_id. Citez-le quand vous nous écrivez.
Montants, identifiants et dates
{
  "id": "ord_3n7q",
  "created_at": "2026-11-01T09:14:02Z",
  "total": { "amount": "264.20", "currency": "CNY" },
  "suggested_price": { "amount": "49.99", "currency": "USD" }
}

Pagination

Les listes renvoient les plus récents d’abord, sous forme de data, has_more et cursor. Renvoyez ce curseur pour la page suivante tant que has_more vaut true. Un curseur ne fonctionne qu’avec les filtres d’où il vient.

limitinteger
1 à 100. 25 si omis.
cursorstring
Le curseur de la page précédente. Omettez-le pour la première page.
curl "https://www.ninjabuy.com/api/v1/orders?limit=25&cursor=c_2v9kq" \
  -H "Authorization: Bearer $NINJABUY_API_KEY" \
  -H "NinjaBuy-Version: 2026-11"
Response 200
HTTP/2 200 OK

{
  "data": [
    { "id": "ord_3n7q", "status": "checked" },
    { "id": "ord_3n6z", "status": "shipped" }
  ],
  "has_more": true,
  "cursor": "c_1q4ea"
}

Limites de débit

Les limites sont par compte, partagées par toutes ses clés, ses jetons OAuth et sa connexion MCP. Chaque réponse indique où vous en êtes dans les en-têtes IETF RateLimit-Policy et RateLimit ; un refus est un 429 rate-limited avec Retry-After en secondes.

FenêtreCe qui compte
"create-links";q=30;w=60Appels qui lisent une annonce sur la marketplace : créer ou rafraîchir un import, envoyer un produit. 30 par minute, partagés avec l’API des liens et MCP.
"default";q=120;w=60Tous les autres appels. 120 par minute.
Réponse 429
HTTP/2 429
Content-Type: application/problem+json
Retry-After: 12
RateLimit-Policy: "create-links";q=30;w=60
RateLimit: "create-links";r=0;t=12

{
  "type": "https://www.ninjabuy.com/api/v1/problems/rate-limited",
  "title": "Too many requests",
  "status": 429,
  "detail": "Try again in 12 seconds.",
  "request_id": "req_7Hq2Lw9c"
}

Idempotence

Envoyez une Idempotency-Key (1 à 255 caractères ASCII imprimables ; un UUID est idéal) sur tout POST, et une nouvelle tentative après un délai dépassé ne peut pas créer une deuxième commande. Pendant 24 heures, la même clé, sur la même route avec le même corps, renvoie la première réponse à l’octet près, avec Idempotent-Replayed: true, sans rien exécuter ni compter dans une limite.

  • La même clé avec un corps ou une route différente : 422 idempotency-key-reused.
  • La première requête est encore en cours : 409 idempotency-key-in-progress, avec Retry-After.
  • Un refus pour limite de débit n’est pas une réponse : la clé reste libre, donc réessayer après Retry-After exécute la requête.

Les commandes portent aussi votre propre external_id : une deuxième commande avec le même est refusée avec 409 duplicate-order, quelle que soit la clé utilisée.

Une requête réessayée
POST /api/v1/orders
Idempotency-Key: 4f0c2b4e-9d1a-4e0f-b0a8-5d1d3c7e2f61

HTTP/2 201
Idempotent-Replayed: true
X-Request-Id: req_7Hq2Lw9c

Erreurs

Les erreurs sont au format problem JSON (RFC 9457) : type est une URL stable sur laquelle brancher, title la nomme, detail explique ce cas en mots affichables, et request_id la retrouve dans nos journaux. Un corps qui échoue à la validation ajoute errors, chacun avec un pointer JSON vers le champ.

StatutTypeQuand
400bad-jsonLe corps n’est pas du JSON.
400bad-bodyUn champ manque ou est incorrect ; errors[] l’indique.
400bad-idempotency-keyL’Idempotency-Key est vide, trop longue ou pas en ASCII imprimable.
401unauthorizedLa clé ou le jeton est absent, incorrect, expiré ou révoqué.
403insufficient-scopeLa clé n’a pas le scope requis par la route.
404not-foundAucun objet de ce type sur ce compte. Les identifiants d’un autre compte donnent la même réponse.
405method-not-allowedLa route existe, mais pas avec cette méthode ; Allow liste celles qu’elle accepte.
409duplicate-orderUne commande avec cet external_id existe ; order l’indique.
409idempotency-key-in-progressLa première requête avec cette clé est encore en cours.
409invalid-stateL’objet ne peut pas faire cela maintenant, par exemple annuler une commande expédiée.
415unsupported-media-typeLe corps n’est pas en application/json.
422idempotency-key-reusedLa clé a servi pour une autre requête.
422unprocessableDu JSON valide que nous ne pouvons pas traiter : un lien illisible, une variante épuisée. detail indique lequel.
429rate-limitedTrop d’appels dans la fenêtre. Attendez Retry-After secondes.
500internal-errorNotre erreur. Réessayez avec la même Idempotency-Key.
503service-unavailableNous n’avons pas pu vérifier la clé ou joindre une boutique pour le moment. Réessayez après Retry-After.
Response 400
HTTP/2 400

{
  "type": "https://www.ninjabuy.com/api/v1/problems/bad-body",
  "title": "Invalid request body",
  "status": 400,
  "detail": "1 field is invalid.",
  "request_id": "req_7Hq2Lw9c",
  "errors": [
    {
      "pointer": "/ship_to/country",
      "detail": "Must be a two-letter country code."
    }
  ]
}