NinjaBuy Business API
Basis-URL
Elke route op deze site valt onder één basis-URL. De Shopify-app en alles wat jij bouwt, roepen dezelfde routes aan, dus wat de app doet, kan jouw code ook.
https://www.ninjabuy.com/api/v1
Liever een AI-assistent vragen? Hetzelfde account werkt via MCP op https://www.ninjabuy.com/mcp: AI-assistenten (MCP).
- ImportsEen link erin, de volledige verkoopkosten eruit.
- ProductenWat je verkoopt, en waar het staat.
- VariantenElke optie, gekoppeld aan de SKU van de verkoper.
- VoorraadniveausWat je nu kunt verkopen.
- SyncregelsWat er gebeurt als een verkoper een prijs verandert.
- BestellingenEen verkoop die we kopen, controleren en verzenden.
- FulfillmentordersDe regels die in één pakket vertrekken.
- ZendingenPakketten onderweg, met tracking.
- SaldoHet geld waaruit bestellingen worden betaald.
- Webhook-endpointsWaar we events naartoe sturen.
curl "https://www.ninjabuy.com/api/v1/balance" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11"Authenticatie
Stuur bij elk verzoek een API-sleutel als bearer token. Sleutels beginnen met nb_. Tijdens de preview geeft ons team ze uit: zodra je Business-account is ingericht, sturen we elke sleutel één keer via een kanaal dat jij kiest, met de scopes die je hebt gevraagd. Vraag ons er een in te trekken en hij werkt vanaf het volgende verzoek niet meer.
Bewaar sleutels op je server. Een sleutel in een browser, een app of een openbare repository kan iedereen lezen, en daarmee kan je saldo worden uitgegeven.
Een app die namens andere NinjaBuy-verkopers handelt, gebruikt OAuth 2.1: dynamische clientregistratie, de authorization code flow met PKCE (S256), en het eigen goedkeuringsscherm van de verkoper. Het access token gaat in dezelfde header en werkt op dezelfde routes. Access tokens gelden een uur; refresh tokens verlengen ze zeven dagen lang. AI-assistenten verbinden op dezelfde manier (MCP).
products:readscope- Imports, producten, varianten en syncregels lezen.
products:writescope- Producten importeren, bewerken, doorsturen en verwijderen; syncregels wijzigen.
inventory:readscope- Voorraadniveaus lezen.
orders:readscope- Bestellingen, fulfillmentorders en zendingen lezen.
orders:writescope- Bestellingen aanmaken, vasthouden, vrijgeven en annuleren. Gebruikt je saldo.
balance:readscope- Het saldo en de transacties lezen.
webhooks:writescope- Webhook-endpoints beheren.
Een aanroep buiten de scopes van een sleutel antwoordt met 403 insufficient-scope en noemt de scope die nodig is.
Authorization: Bearer nb_7Qk2...vX9eHTTP/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"
}Versiebeheer
Het pad bevat de hoofdversie, /v1. Daarbinnen veranderen gedateerde versies velden en gedrag. Leg de versie vast waarop je hebt gebouwd met de NinjaBuy-Version-header; elk antwoord noemt in dezelfde header de versie die het gebruikte.
2026-11 is de huidige versie, en het is een preview: namen en velden kunnen nog veranderen voordat hij als stabiel geldt. Elke wijziging staat in de changelog, en we mailen elke sleutelhouder vóór een wijziging die iets kan breken.
Binnen een versie voegen we alleen toe: nieuwe routes, nieuwe optionele parameters, nieuwe velden in antwoorden en nieuwe eventtypes. Bouw je client zo dat hij velden negeert die hij niet kent.
GET /api/v1/orders
NinjaBuy-Version: 2026-11
HTTP/2 200
NinjaBuy-Version: 2026-11Verzoeken en antwoorden
- Stuur JSON met
Content-Type: application/json; antwoorden zijn JSON in UTF-8. Fouten zijnapplication/problem+json. - Geld is een object met een decimale string en een valuta:
{ "amount": "264.20", "currency": "CNY" }. Wat NinjaBuy rekent, is in CN¥; je verkoopprijzen zijn in de valuta van je winkel. - Id's zijn strings met een prefix dat de soort noemt (
prd_,ord_,shp_). Behandel ze als ondoorzichtig. - Tijden zijn ISO 8601 in UTC. Landen zijn ISO-codes van twee letters.
- Elk antwoord bevat een
X-Request-Id-header, en elke fout bevat dezelfde id alsrequest_id. Vermeld die als je ons schrijft.
{
"id": "ord_3n7q",
"created_at": "2026-11-01T09:14:02Z",
"total": { "amount": "264.20", "currency": "CNY" },
"suggested_price": { "amount": "49.99", "currency": "USD" }
}Paginering
Lijsten antwoorden met nieuwste eerst, als data, has_more en cursor. Stuur die cursor terug voor de volgende pagina zolang has_more true is. Een cursor werkt alleen met de filters waar hij vandaan kwam.
limitinteger- 1 tot 100. 25 als je het weglaat.
cursorstring- De cursor van de vorige pagina. Laat weg voor de eerste 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"HTTP/2 200 OK
{
"data": [
{ "id": "ord_3n7q", "status": "checked" },
{ "id": "ord_3n6z", "status": "shipped" }
],
"has_more": true,
"cursor": "c_1q4ea"
}Rate limits
Limieten gelden per account, gedeeld door alle sleutels, OAuth-tokens en de MCP-verbinding. Elk antwoord laat in de IETF-headers RateLimit-Policy en RateLimit zien waar je staat; een weigering is 429 rate-limited met Retry-After in seconden.
| Venster | Wat telt |
|---|---|
| "create-links";q=30;w=60 | Aanroepen die een listing van de marktplaats lezen: een import aanmaken of verversen, een product doorsturen. 30 per minuut, gedeeld met de links-API en MCP. |
| "default";q=120;w=60 | Alle andere aanroepen. 120 per minuut. |
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"
}Idempotentie
Stuur bij elke POST een Idempotency-Key (1 tot 255 afdrukbare ASCII-tekens; een UUID is ideaal), en een herhaling na een time-out kan geen tweede bestelling plaatsen. 24 uur lang geeft dezelfde sleutel, op dezelfde route met dezelfde body, het eerste antwoord byte voor byte opnieuw, met Idempotent-Replayed: true, zonder opnieuw uit te voeren of mee te tellen voor een limiet.
- Dezelfde sleutel met een andere body of route:
422 idempotency-key-reused. - Het eerste verzoek loopt nog:
409 idempotency-key-in-progress, metRetry-After. - Een weigering door de rate limit is geen antwoord: de sleutel blijft vrij, dus opnieuw proberen na
Retry-Aftervoert het verzoek uit.
Bestellingen dragen ook je eigen external_id: een tweede bestelling met dezelfde wordt geweigerd met 409 duplicate-order, met welke sleutel ook verstuurd.
POST /api/v1/orders
Idempotency-Key: 4f0c2b4e-9d1a-4e0f-b0a8-5d1d3c7e2f61
HTTP/2 201
Idempotent-Replayed: true
X-Request-Id: req_7Hq2Lw9cFouten
Fouten zijn problem JSON (RFC 9457): type is een stabiele URL om op te vertakken, title geeft de naam, detail legt dit geval uit in woorden die je kunt tonen, en request_id vindt het in onze logs. Een body die de validatie niet doorstaat, voegt errors toe, elk met een JSON-pointer naar het veld.
| Status | Type | Wanneer |
|---|---|---|
| 400 | bad-json | De body is geen JSON. |
| 400 | bad-body | Een veld ontbreekt of klopt niet; errors[] wijst het aan. |
| 400 | bad-idempotency-key | De Idempotency-Key is leeg, te lang of geen afdrukbare ASCII. |
| 401 | unauthorized | De sleutel of het token ontbreekt, klopt niet, is verlopen of ingetrokken. |
| 403 | insufficient-scope | De sleutel mist de scope die de route nodig heeft. |
| 404 | not-found | Dit object bestaat niet op dit account. Id's van een ander account geven hetzelfde antwoord. |
| 405 | method-not-allowed | De route bestaat, maar niet met deze methode; Allow noemt de methodes die hij accepteert. |
| 409 | duplicate-order | Er bestaat een bestelling met deze external_id; order noemt hem. |
| 409 | idempotency-key-in-progress | Het eerste verzoek met deze sleutel loopt nog. |
| 409 | invalid-state | Het object kan dat nu niet, bijvoorbeeld een verzonden bestelling annuleren. |
| 415 | unsupported-media-type | De body is geen application/json. |
| 422 | idempotency-key-reused | De sleutel is gebruikt voor een ander verzoek. |
| 422 | unprocessable | Geldige JSON waar we niets mee kunnen: een onleesbare link, een uitverkochte variant. detail zegt welke. |
| 429 | rate-limited | Te veel aanroepen in het venster. Wacht Retry-After seconden. |
| 500 | internal-error | Onze fout. Probeer opnieuw met dezelfde Idempotency-Key. |
| 503 | service-unavailable | We konden de sleutel nu niet controleren of een winkel niet bereiken. Probeer opnieuw na Retry-After. |
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."
}
]
}