Sviluppatori2026-11Anteprima

API NinjaBuy Business

Importa prodotti da Taobao, Weidian e 1688, tieni prezzo e stock sincronizzati e segui ogni ordine dal venditore in Cina, attraverso il controllo nel nostro magazzino, fino alla porta del tuo cliente. JSON su HTTPS, un account, un saldo.

URL di base

Ogni route di questo sito vive sotto un unico URL di base. L’app Shopify e tutto ciò che costruisci chiamano le stesse route, quindi ciò che fa l’app può farlo anche il tuo codice.

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

Preferisci chiedere a un assistente IA? Lo stesso account funziona via MCP su https://www.ninjabuy.com/mcp: Assistenti IA (MCP).

Catalogo
Ordini
Account
La tua prima chiamata
curl "https://www.ninjabuy.com/api/v1/balance" \
  -H "Authorization: Bearer $NINJABUY_API_KEY" \
  -H "NinjaBuy-Version: 2026-11"

Autenticazione

Invia una chiave API come bearer token in ogni richiesta. Le chiavi iniziano con nb_. Durante l’anteprima le emette il nostro team: una volta configurato il tuo account Business, inviamo ogni chiave una sola volta, sul canale che scegli, con gli scope richiesti. Chiedici di revocarne una e smette di funzionare dalla richiesta successiva.

Tieni le chiavi sul tuo server. Una chiave in un browser, in un’app o in un repository pubblico può essere letta da chiunque e può spendere il tuo saldo.

Un’app che agisce per altri venditori NinjaBuy usa invece OAuth 2.1: registrazione dinamica del client, flusso authorization code con PKCE (S256) e la schermata di approvazione del venditore stesso. Il suo token di accesso va nella stessa intestazione e funziona sulle stesse route. I token di accesso durano un’ora; i token di aggiornamento li rinnovano per sette giorni. Gli assistenti IA si collegano allo stesso modo (MCP).

products:readscope
Leggi importazioni, prodotti, varianti e regole di sincronizzazione.
products:writescope
Importa, modifica, invia ed elimina prodotti; cambia le regole di sincronizzazione.
inventory:readscope
Leggi i livelli di stock.
orders:readscope
Leggi ordini, ordini di evasione e spedizioni.
orders:writescope
Crea, metti in attesa, sblocca e annulla ordini. Spende il tuo saldo.
balance:readscope
Leggi il saldo e le sue transazioni.
webhooks:writescope
Gestisci gli endpoint webhook.

Una chiamata fuori dagli scope di una chiave risponde 403 insufficient-scope e indica lo scope necessario.

Intestazione
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"
}

Versioni

Il percorso contiene la versione principale, /v1. Al suo interno, versioni datate cambiano campi e comportamento. Fissa quella su cui hai costruito con l’intestazione NinjaBuy-Version; ogni risposta indica la versione usata nella stessa intestazione.

2026-11 è la versione attuale ed è un’anteprima: nomi e campi possono ancora cambiare prima che sia dichiarata stabile. Ogni modifica è nel changelog e avvisiamo via email ogni titolare di chiave prima di una modifica che potrebbe creargli problemi.

All’interno di una versione aggiungiamo soltanto: nuove route, nuovi parametri facoltativi, nuovi campi nelle risposte e nuovi tipi di evento. Costruisci il tuo client in modo che ignori i campi che non conosce.

Fissa una versione
GET /api/v1/orders
NinjaBuy-Version: 2026-11

HTTP/2 200
NinjaBuy-Version: 2026-11

Richieste e risposte

  • Invia JSON con Content-Type: application/json; le risposte sono JSON in UTF-8. Gli errori sono application/problem+json.
  • Un importo è un oggetto con una stringa decimale e una valuta: { "amount": "264.20", "currency": "CNY" }. Ciò che NinjaBuy addebita è in CN¥; i tuoi prezzi di vendita sono nella valuta del tuo negozio.
  • Gli ID sono stringhe con un prefisso che ne indica il tipo (prd_, ord_, shp_). Trattali come opachi.
  • Le date sono ISO 8601 in UTC. I paesi sono codici ISO a due lettere.
  • Ogni risposta ha un’intestazione X-Request-Id e ogni errore riporta lo stesso ID come request_id. Citalo quando ci scrivi.
Importi, ID e date
{
  "id": "ord_3n7q",
  "created_at": "2026-11-01T09:14:02Z",
  "total": { "amount": "264.20", "currency": "CNY" },
  "suggested_price": { "amount": "49.99", "currency": "USD" }
}

Paginazione

Gli elenchi restituiscono i più recenti per primi, come data, has_more e cursor. Rimanda quel cursore per la pagina successiva finché has_more è true. Un cursore funziona solo con i filtri da cui proviene.

limitinteger
Da 1 a 100. 25 se omesso.
cursorstring
Il cursore della pagina precedente. Omettilo per la prima pagina.
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"
}

Limiti di frequenza

I limiti sono per account, condivisi da tutte le sue chiavi, i token OAuth e il collegamento MCP. Ogni risposta indica a che punto sei nelle intestazioni IETF RateLimit-Policy e RateLimit; un rifiuto è 429 rate-limited con Retry-After in secondi.

FinestraCosa conta
"create-links";q=30;w=60Chiamate che leggono un’inserzione dal marketplace: creare o aggiornare un’importazione, inviare un prodotto. 30 al minuto, condivise con l’API dei link e MCP.
"default";q=120;w=60Tutte le altre chiamate. 120 al minuto.
Risposta 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"
}

Idempotenza

Invia una Idempotency-Key (da 1 a 255 caratteri ASCII stampabili; un UUID è l’ideale) in ogni POST, e un nuovo tentativo dopo un timeout non può creare un secondo ordine. Per 24 ore la stessa chiave, sulla stessa route con lo stesso corpo, restituisce di nuovo la prima risposta byte per byte, con Idempotent-Replayed: true, senza rieseguire nulla né contare per un limite.

  • La stessa chiave con un corpo o una route diversi: 422 idempotency-key-reused.
  • La prima richiesta è ancora in corso: 409 idempotency-key-in-progress, con Retry-After.
  • Un rifiuto per limite di frequenza non è una risposta: la chiave resta libera, quindi riprovare dopo Retry-After esegue la richiesta.

Gli ordini portano anche un tuo external_id: un secondo ordine con lo stesso viene rifiutato con 409 duplicate-order, qualunque sia la chiave usata.

Una richiesta ripetuta
POST /api/v1/orders
Idempotency-Key: 4f0c2b4e-9d1a-4e0f-b0a8-5d1d3c7e2f61

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

Errori

Gli errori sono problem JSON (RFC 9457): type è un URL stabile su cui ramificare, title lo nomina, detail spiega questo caso con parole che puoi mostrare e request_id lo ritrova nei nostri log. Un corpo che non supera la validazione aggiunge errors, ognuno con un pointer JSON al campo.

StatoTipoQuando
400bad-jsonIl corpo non è JSON.
400bad-bodyUn campo manca o è errato; errors[] lo indica.
400bad-idempotency-keyLa Idempotency-Key è vuota, troppo lunga o non è ASCII stampabile.
401unauthorizedLa chiave o il token manca, è errato, scaduto o revocato.
403insufficient-scopeAlla chiave manca lo scope richiesto dalla route.
404not-foundNessun oggetto simile su questo account. Gli ID di un altro account danno la stessa risposta.
405method-not-allowedLa route esiste, ma non con questo metodo; Allow elenca quelli accettati.
409duplicate-orderEsiste un ordine con questo external_id; order lo indica.
409idempotency-key-in-progressLa prima richiesta con questa chiave è ancora in corso.
409invalid-stateL’oggetto non può farlo ora, per esempio annullare un ordine spedito.
415unsupported-media-typeIl corpo non è application/json.
422idempotency-key-reusedLa chiave è stata usata per una richiesta diversa.
422unprocessableJSON valido su cui non possiamo agire: un link non letto, una variante esaurita. detail indica quale.
429rate-limitedTroppe chiamate nella finestra. Attendi Retry-After secondi.
500internal-errorColpa nostra. Riprova con la stessa Idempotency-Key.
503service-unavailableAl momento non siamo riusciti a verificare la chiave o a raggiungere un negozio. Riprova dopo 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."
    }
  ]
}