Product lookup
/api/public/v1/products
Batch resolution of products by barcode or SKU, returning the calling customer's net price and live stock. Two endpoints, one response shape.
Common to both
| Method | POST |
| Auth | X-API-Key header — required |
| Customer | X-Customer-No header — required for an integrator token, ignored for a customer token |
| Batch limit | 100 keys per call |
| Content type | application/json |
Both are POST despite being reads, because a batch of a hundred keys does not belong in a query
string.
POST /api/public/v1/products/by-ean
Look up by European Article Number. Each must be a valid 8- or 13-digit EAN.
{
"eans": ["9312345678907", "9312345678914"]
}
POST /api/public/v1/products/by-sku
Look up by SKU.
{
"skus": ["SHIRT-BLK-M", "SHIRT-BLK-L"]
}
Response
200 OK. One entry per requested key, in the same order, wrapped in the public envelope.
{
"data": [
{
"key": "9312345678907",
"found": true,
"value": {
"currency": "AUD",
"ean": "9312345678907",
"sku": "SHIRT-BLK-M",
"masterProductNo": "SHIRT",
"name": "Classic Shirt",
"size": "M",
"color": "Black",
"unitPrice": 24.50,
"stock": {
"onHand": 412,
"reserved": 37,
"byLocation": [
{ "locationCode": "SYD", "quantity": 260 },
{ "locationCode": "MEL", "quantity": 152 }
],
"incoming": [
{ "locationCode": "SYD", "quantity": 500, "expectedDate": "2026-09-14" }
]
}
}
},
{
"key": "9312345678914",
"found": false,
"value": null
}
]
}
Fields
| Field | Type | Notes |
|---|---|---|
key |
string | The EAN or SKU you asked for |
found |
boolean | Whether it resolved |
value |
object · null | Null when found is false |
value.currency |
string | ISO 4217, from the site's configured currency |
value.ean |
string · null | Null when the product has no EAN assigned |
value.sku |
string | |
value.masterProductNo |
string | Groups every size and colour variant |
value.name |
string · null | |
value.size |
string · null | Null when not applicable |
value.color |
string · null | Null when not applicable |
value.unitPrice |
decimal · null | Net, quantity 1, promotions excluded. Null when no price is determinable for this customer |
value.stock.onHand |
integer | Total across all locations |
value.stock.reserved |
integer | Held against existing orders |
value.stock.byLocation[] |
array | locationCode, quantity |
value.stock.incoming[] |
array | locationCode, quantity, expectedDate (date only) |
Three things to get right
An unknown key is not an error. It comes back with found: false and the call still returns
200. A batch of a hundred where four are unknown is a normal result.
unitPrice is not the price the customer pays. It is the net unit price at quantity one with
promotions excluded. Quantity breaks, promotions, freight, surcharges and tax are all applied at
checkout and are not reflected here.
Stock is a snapshot, not a reservation. Nothing is held. A quantity read here can be gone by the time an order is placed.
Errors
| Status | When |
|---|---|
400 |
X-Customer-No missing on an integrator token · empty key list · more than 100 keys |
401 |
X-API-Key missing, invalid, revoked or expired |
404 |
The customer named in X-Customer-No does not exist |
429 |
The token's rate limit for the current window is exhausted |
Errors use the public problem shape and are not wrapped in data.
Example
curl -X POST https://{host}/api/public/v1/products/by-sku \
-H "X-API-Key: {key}" \
-H "X-Customer-No: C00123" \
-H "Content-Type: application/json" \
-d '{"skus":["SHIRT-BLK-M"]}'