Getting started
Quickstart
Five calls against your sandbox: send products, update stock, receive a simulated order and acknowledge it. Allow ten minutes.
Before you start
- A partner key (
npv_live_…). If you don't have one, create a developer account: it takes two minutes. You can also create the sandbox there with one click and skip step 1. curl, or any HTTP client. Samples in JavaScript, Python and PHP follow in syncing the catalogue.
The sandbox is a hidden shop that customers never see. Use it exactly like a real shop.
Terminal
export NUNUA_PARTNER_KEY=npv_live_...
Run it
quickstart.sh
# 1. Make your sandbox (partner key). The test key is shown once, so save it.
curl -s -X POST https://nunuapro.app/api/pos-partner/v1/sandbox \
-H "Authorization: Bearer $NUNUA_PARTNER_KEY"
export NUNUA_KEY=npk_test_... # the api_key from the response
BASE=https://nunuapro.app/api/pos/v1
# 2. Send two products.
curl -s -X POST $BASE/products/batch -H "Authorization: Bearer $NUNUA_KEY" -H "Content-Type: application/json" -d '{
"products": [
{"external_id": "SKU-1", "name": "SUKARI KILOMBERO 1KG", "barcode": "6001068705504", "price": 3500, "stock_qty": 40},
{"external_id": "SKU-2", "name": "COLGATE TOTAL 100G", "price": 4200, "stock_qty": 12}
]
}'
# 3. A sale happened in the shop: update stock and price.
curl -s -X PATCH $BASE/inventory -H "Authorization: Bearer $NUNUA_KEY" -H "Content-Type: application/json" -d '{
"items": [{"external_id": "SKU-1", "stock_qty": 39, "updated_at": "2026-11-03T10:15:00+03:00"}]
}'
# 4. Pretend a customer ordered, then read the change feed.
curl -s -X POST $BASE/sandbox/orders -H "Authorization: Bearer $NUNUA_KEY"
curl -s "$BASE/events?after=0" -H "Authorization: Bearer $NUNUA_KEY"
# 5. Record the sale in your POS, then acknowledge (send new stock quantities BEFORE this).
curl -s -X POST $BASE/orders/123/ack -H "Authorization: Bearer $NUNUA_KEY" -H "Content-Type: application/json" \
-d '{"status": "accepted", "pos_ref": "SALE-8841"}'What each step did
- Made your sandbox
POST /pos-partner/v1/sandboxcreates your test shop and returns itsnpk_test_…key once. Call it again with{"rotate": true}for a new key. - Sent two products
POST /pos/v1/products/batchupserts up to 200 products and answers200with a result for each. One bad row never fails the batch. - Updated stock
PATCH /pos/v1/inventoryis the call you'll make most: price, stock or availability for up to 500 products or variations. - Simulated an order
POST /pos/v1/sandbox/orderspretends a customer placed and confirmed an order (pass{"type":"delivery"}, or leave it as the default pickup).GET /pos/v1/eventsis where your POS sees it. - Acknowledged it
POST /pos/v1/orders/{id}/acktells us you recorded the sale. Then tryPOST /pos/v1/sandbox/orders/{id}/cancelto see the cancellation your POS must also handle.
Reading a batch result
Every product you send gets its own result. It tells you everything you need.
Response
{
"results": [
{ "external_id": "SKU-1", "status": "created", "product_id": 48213,
"listed": false, "catalog": "linked", "errors": [] },
{ "external_id": "SKU-2", "status": "rejected",
"errors": ["The price field must not be greater than 100000000."] }
]
}
| Field | Means |
|---|---|
status | created, updated, stale (older than what we hold, so ignored), archived or rejected. |
listed | Whether customers can see it yet. New imports start hidden until the owner approves them. |
catalog | linked (matched our shared catalogue by barcode), suggested (a likely match the owner confirms) or none. |
renamed_to | Present when another product already had this name: we kept both, naming this one "Name (SKU)". |
warnings, errors | Human-readable reasons. Log rejected rows and fix the cause in your data. |
Next: link a real shop with a code, then load its whole catalogue with a snapshot.