nz-price-hub

nz-price-hub

Public price API for three New Zealand supermarket chains. Base URL: https://hub.w1.nz.

Responses are gzip-compressed, including when Accept-Encoding is omitted. Send curl --compressed so curl decompresses the body. Browsers do this when they advertise gzip. Send Accept-Encoding: identity only when you need the raw uncompressed bytes.

Chains: paknsave, newworld, woolworths.

Departments: produce (fresh fruit and vegetables) and meat (fresh meat and seafood).

Dates are New Zealand calendar dates, YYYY-MM-DD. Omit date to use the latest day loaded on the server.

A light per-IP limit applies: about 10 requests per second, with a burst of 40. HTTP 429 responses include Retry-After.

Find the nearest store

GET /v1/stores/nearest?lat={lat}&lng={lng}&limit=3

limit defaults to 3. Optional chain keeps one banner. Results are sorted nearest first and include distance_km. Stores with no coordinates are omitted.

curl --compressed "https://hub.w1.nz/v1/stores/nearest?lat=-36.748&lng=174.748&limit=3"

Filter the national store list:

curl --compressed "https://hub.w1.nz/v1/stores?region=Auckland&chain=woolworths&q=Browns%20Bay"
curl --compressed "https://hub.w1.nz/v1/stores?lat=-36.748&lng=174.748&limit=5"

lat and lng together sort by haversine distance and add distance_km. Stores with no coordinates are left out of that list. q matches name, suburb, address, region, or store id.

Prices at a store

GET /v1/prices?chain=&store=&date=&department=&q=&limit=&offset=

store is a store id or a case-insensitive name fragment. limit defaults to 50 and is capped. offset pages through the match set.

curl --compressed "https://hub.w1.nz/v1/prices?chain=woolworths&store=Browns%20Bay&department=produce&q=banana"

Each price object includes chain, store_id, store_name, date, department, product_id, name, price (NZD shelf price), unit_price, unit, size, promo, was_price, and url when the scrape captured them.

Search

GET /v1/search?q=&chain=&store=&lat=&lng=&date=&limit=

q is required and matches the product name. When lat and lng are set, the search uses the nearest store of each chain that has prices for that day (or only chain when that is set) instead of every store in the country. An explicit store selects that store.

curl --compressed "https://hub.w1.nz/v1/search?q=broccoli&lat=-36.748&lng=174.748"

Compare

GET /v1/compare?q=banana&lat=-36.748&lng=174.748

or name the stores yourself:

GET /v1/compare?q=banana&stores=paknsave:STOREID,newworld:STOREID,woolworths:STOREID

stores values are chain:store_id pairs separated by commas. With lat and lng, each chain uses the nearest store that has prices for that day. The reply is one cheapest product per chain, sorted by unit price when that field is present, otherwise by shelf price.

curl --compressed "https://hub.w1.nz/v1/compare?q=banana&lat=-36.748&lng=174.748"

Other reads

curl --compressed "https://hub.w1.nz/v1/dates"
curl --compressed "https://hub.w1.nz/v1/runs"
curl --compressed "https://hub.w1.nz/healthz"
curl --compressed "https://hub.w1.nz/docs"

/v1/dates lists days that have a snapshot. /v1/runs is the latest scrape log. Each row's status is ok, imported, blocked, skipped, skipped-blocked, or error. /healthz is a liveness check. /docs is the HTML reference. This document is also at /SKILL.md as markdown.

Install this skill

Save the raw markdown to each of these paths:

mkdir -p ~/.codex/skills/nz-price-hub ~/.claude/skills/nz-price-hub .agents/skills/nz-price-hub
curl --compressed -fsSL -o ~/.codex/skills/nz-price-hub/SKILL.md https://hub.w1.nz/SKILL.md
cp ~/.codex/skills/nz-price-hub/SKILL.md ~/.claude/skills/nz-price-hub/SKILL.md
cp ~/.codex/skills/nz-price-hub/SKILL.md .agents/skills/nz-price-hub/SKILL.md

Prices are online shelf prices from the public catalogues, not a checkout quote. The hub does not sign in, add to a cart, or place orders.