Authentication
Every request to /v1/products must include your API key. Two methods are accepted —
use whichever suits your client:
1. Query parameter
GET https://api.mdrlighting.co.nz/v1/products?key=YOUR_API_KEY
2. Bearer token header
GET https://api.mdrlighting.co.nz/v1/products
Authorization: Bearer YOUR_API_KEY
Keys are issued to you directly. A key may be disabled or expire; in either case requests
return 401. Keep your key secret — it identifies your account and controls what you can see.
GET /v1/products
Returns the products visible to your key, each with current available stock grouped into the stock labels configured for your account.
Which products appear
Your feed contains the products in the categories enabled for your account that are also published on the MDR website. If a product is unpublished it will not appear, even if it is in one of your categories. Some entries are packages / kits assembled from several components — for those, the quantity shown is how many complete packages can currently be made from component stock.
Response fields
| Field | Type | Description |
|---|---|---|
id | integer | Stable product identifier. |
name | string | Product name. |
sku | string · nullable | Product SKU / internal reference. |
last_updated | string | UTC timestamp the product was last modified. |
website_url | string · nullable · optional | Link to this product’s page on the MDR website, ready to use in your own listings. null if it has no public page. Only present if enabled for your key. |
portal_categories | array · optional | The product’s B2B / portal categories from the MDR website, each as "Parent > Name", e.g. ["Lighting > Moving Heads"]. An empty array means the product isn’t filed under any portal category. Only present if enabled for your key. |
sales_price | number · optional | Recommended retail (list) unit price. Only present if pricing is enabled for your key. |
compare_price | number · nullable · optional | The “was” / strike-through comparison price, for showing a saving against sales_price. null when the product has no comparison price. Only present if enabled for your key. |
has_compare_price | boolean · optional | Convenience flag — true when compare_price is set, so you can branch without null-checking. Accompanies compare_price. |
your_price | number · optional | Your account’s unit buy price for this product (qty 1), under your assigned pricelist. Only present if a pricelist is assigned to your key. |
stock | object | Available quantity by label, e.g. { "Available Immediately": 12 }. Quantities are free to sell — stock already reserved against confirmed orders is excluded, so what you see is what can actually be ordered. |
availability | array | The same quantities broken out per label, each with a delivery lead time: { "label", "qty", "lead_time" }. lead_time is a short text such as "5-7 days"; an empty value means the item is available now. |
incoming | array · optional | Stock on a scheduled inbound delivery that has not yet arrived: { "quantity", "expected_date", "label" }, where expected_date is the delivery’s scheduled arrival date. Only present if incoming stock is enabled for your key; an empty array means none due in. |
Example response
{
"count": 1,
"products": [
{
"id": 1423,
"name": "Chauvet Maverick MK3 Spot",
"sku": "CHV-MK3-SPOT",
"last_updated": "2026-06-05 21:14:02",
"website_url": "https://www.mdrlighting.co.nz/shop/chauvet-maverick-mk3-spot-1423",
"portal_categories": [
"Lighting > Moving Heads",
"Brands > Chauvet"
],
"sales_price": 4299.00,
"compare_price": 4799.00,
"has_compare_price": true,
"your_price": 3869.10,
"stock": {
"Available Immediately": 7,
"Secondary Warehouse Availability": 3
},
"availability": [
{
"label": "Available Immediately",
"qty": 7,
"lead_time": "0 days"
},
{
"label": "Secondary Warehouse Availability",
"qty": 3,
"lead_time": "5-7 days"
}
],
"incoming": [
{
"quantity": 20,
"expected_date": "2026-06-15",
"label": "Available Immediately"
}
]
}
]
}
Availability & lead times
The stock object and the availability array describe the
same quantities — stock is the simple { label: qty }
form, while availability adds a lead_time per label. The lead time is a short
text such as "5-7 days"; an empty value means the item is available now and ready to ship
(a non-empty value typically indicates stock held at a location with that delivery lead time, for
example an overseas partner warehouse). Use whichever form suits your integration.
These quantities are available (free-to-sell) stock, not raw shelf count: anything already reserved against a confirmed order has been deducted. This means the number you see is what you can actually order today, so you will not be offered stock that is already committed elsewhere.
Stock labels currently in use:
| Stock label | Typical lead time |
|---|---|
| Available Immediately | 0 days |
| Secondary Warehouse Availability | 5-7 days |
Incoming stock
If incoming stock is enabled for your key, each product includes an incoming array of
inbound deliveries that are scheduled but not yet received. Each entry has a quantity, an
expected_date (YYYY-MM-DD) — the delivery’s scheduled arrival date
— and a label indicating the destination. A product with nothing due in returns
"incoming": []. Use this to show customers when out-of-stock items are due back in.
Only live, scheduled deliveries are listed. If a delivery is cancelled it disappears from
incoming, and if the arrival date is re-planned the new date is reflected here — so
the dates track the current delivery schedule rather than the date originally ordered.
GET /v1/status no auth
Lightweight health check for monitoring. No API key required.
{
"api": "MDR Inventory API",
"status": "ok",
"timestamp": "2026-06-06T14:21:09+12:00"
}
The timestamp is New Zealand time.
Error codes
| Status | Meaning | Body |
|---|---|---|
401 | Missing, invalid, disabled, or expired API key. | { "error": "Invalid or expired API key" } |
429 | Rate limit exceeded. Retry after the indicated number of seconds. | { "error": "Rate limit exceeded", "retry_after_seconds": 30 } |
500 | Unexpected server error while fulfilling the request. | { "error": "Internal server error" } |
Rate limits
Each key has a per-minute limit, a short burst allowance, and a daily cap. Typical limits are around
5 requests/minute, a burst of 3, and
200 per day (your key may differ). When you exceed a limit you receive
429 with retry_after_seconds indicating how long to wait before retrying.
Build a small backoff into your client to handle this gracefully.