← Back to kew.ie

Public catalogue API

The machine-readable interface to KEW’s published catalogue. Intended for agents and integrators; the same public data the KEW catalogue renders.

Read-only OpenAPI contract · Product sitemap · Agent discovery notes

You can search products and prepare a list for a quote without an account or a paid integration. This does not create a quotation or submit an enquiry. The customer completes the quote basket in their browser, or contacts KEW.

No authentication. No rate-limit headers are published yet — treat the service as politely rate-limited and do not poll aggressively.

Base URL: https://kew-erp-api-dxxg3763qa-ew.a.run.app


What is visible, and what is not

A product appears here only when KEW has explicitly published it. Publication is a deliberate staff decision recorded against the SKU; it is not inferred from stock levels, from legacy import flags, or from the product simply existing.

Consequences worth understanding before you build against this:

  • Absence is not evidence KEW cannot supply the line. An unpublished SKU may still be stocked. Ask for a quote rather than concluding it is unavailable.
  • The catalogue can be empty. It legitimately returns total: 0 when nothing has been published yet. That is not an outage.

The following are never returned by any public endpoint, by policy: cost, sell price, supplier identity, exact stock quantities, and warehouse bin locations.


GET /catalog/search

Search or browse published products.

Parameters

Name Type Default Notes
q string, ≤ 120 chars "" Free text. Empty browses everything published. Separate words may match across SKU, name, description, brand, manufacturer, MPN, GTIN, category and public search keywords. Quote a phrase to require it together.
category_code string, ≤ 64 chars — Restrict to one category. Codes come from GET /catalog/categories.
brand string, ≤ 64 chars — Restrict to one published brand using a normalized exact match (trimmed, collapsed whitespace, case-insensitive). This is not a free-text description search; a product that merely mentions the brand in its copy is excluded.
selling_unit Published selling unit; preserve it exactly when preparing a quote-basket line. Do not infer pack, reel or metre conversions.
stock_status in_stock | low_stock | order_in — Restrict to a coarse public stock band. Applied before total, limit and offset; products whose publication omits stock_status remain excluded from this filtered view.
sort name | sku | code sku
limit integer, 1–100 10
offset integer, ≥ 0 0

For example, 3 core finds a published product labelled 3-core because both words match; "3 core" requires that exact phrase. With very few exact results, multiword searches also try a conservative spelling match on public product text. Category and stock filters still apply, and the endpoint never searches unpublished products or staff-only supplier, cost, or location fields. Queries with more than 12 separate words return 422.

Response

{
  "total": 0,
  "limit": 10,
  "offset": 0,
  "items": []
}

total is the full count matching the query, not the page size — use it to paginate with offset.

Each entry in items carries the public-safe field set. Search omits unset fields; detail and category responses may return optional fields as null. Treat every field except sku as optional and handle both missing and null values:

Field Notes
sku KEW’s product code. Always present. Stable identifier.
name, description Human-readable copy.
brand, manufacturer, model, mpn, gtin Product identity for cross-referencing.
image_url, datasheet_url May be absolute or site-relative. Resolve relative values against https://kew.ie/, not the API server.
category, category_code Human-readable name and the code for filtering.
technical_description, bullet_features, layperson_description
selling_unit Published selling unit; preserve it exactly when preparing a quote-basket line. Do not infer pack, reel or metre conversions.
stock_status in_stock | low_stock | order_in. See below.

model is an optional field in the response schema but is not currently selectable through the standard publication workflow. Do not rely on it being populated; use a verified mpn and the published description when identifying a product.

Stock bands

Availability is a band, never a count:

Value Meaning
in_stock More than 5 units on hand
low_stock 1–5 units on hand
order_in None on hand; KEW orders it in

The band reflects the last stocktake for that line, not a real-time reservation. It is not a guarantee of allocation — confirm on a quote.

Examples

Search for a product (read-only):

curl --get 'https://kew-erp-api-dxxg3763qa-ew.a.run.app/catalog/search' \
  --data-urlencode 'q=LED high bay' \
  --data-urlencode 'stock_status=in_stock' \
  --data-urlencode 'limit=10'

Look up a specific SKU:

curl --get 'https://kew-erp-api-dxxg3763qa-ew.a.run.app/catalog/product' \
  --data-urlencode 'sku=UFO200W'

Build customer-facing links and resolve media safely:

const productPage = new URL('/p', 'https://kew.ie');
productPage.searchParams.set('sku', product.sku);
const imageUrl = product.image_url
  ? new URL(product.image_url, 'https://kew.ie/').href
  : undefined;

Keep the SKU exactly as returned, including punctuation and slashes. Do not construct a different SKU from the manufacturer part number. Check the product description and ask KEW about pack sizes or ordering units if they are unclear.


GET /catalog/categories

Published categories with product counts. Only categories containing at least one published product appear.

{ "total": 0, "items": [] }

Each item has code, name and product_count. Use code with the category_code parameter on search.


GET /catalog/p/{sku} and GET /catalog/product?sku=...

Detail for a single published SKU. Returns the same public-safe field set as a search result.

Use the query-parameter form for SKUs containing / — several KEW codes do (for example PFE/10/100), and percent-encoding them into the path is fragile across clients.

Returns 404 when the SKU is unknown or not published. The two are deliberately indistinguishable: whether an unpublished SKU exists is not public information.


GET /catalog/c/{category_code}

Published products in one category. Supports limit and offset with the same bounds as search.


POST /catalog/quote-requests

Quote lines submit SKU, quantity and an optional note. Do not add a client-supplied selling_unit field to this request: unknown fields are rejected. The server reads the current ERP unit for each published product and snapshots it into the saved enquiry, staff context and email when that unit is selected for public publication. Missing or unselected units remain missing; no pack, reel or metre conversion is inferred.

This is the existing browser quote-basket submission endpoint. It requires Cloudflare Turnstile verification and is not an unattended agent tool. Publishing these documents does not remove that requirement or grant write access.

An agent should prepare a list containing the exact SKU, product link, requested quantity and any customer notes, then hand it to the customer. The customer can open the catalogue, add the products to their quote basket and submit it, or contact KEW. Opening a product link does not automatically add the item to a basket or submit it.

The browser endpoint validates published SKUs, records the enquiry and attempts to send an acknowledgement email. Its response distinguishes email_status: "sent" from "failed". A saved request with a failed email is still saved: do not blindly resubmit and create duplicates. The customer should retain the request reference and contact KEW if confirmation is unclear.

Every quote request is reviewed by a person before a price is issued. Expect a human-in-the-loop reply, not an instant automated price.


Errors

Status Meaning
404 Unknown or unpublished SKU/category — or the public catalogue is disabled.
422 Invalid parameters, or a quote request naming a SKU that is not published.
429 Request frequency exceeded a service limit. Honour Retry-After when present and back off.
5xx Temporary service failure. Retry reads with bounded backoff; never treat an error as an empty catalogue.

The catalogue sits behind a feature flag and is fail-closed: when disabled, catalogue routes return 404. If all reads return 404, the catalogue may be disabled; check the base URL and contact KEW rather than concluding every product is unavailable.


Guidance for agents

  • Do not infer a price from any field. There is none, by design.
  • Prefer this API over scraping HTML. It is stable and returns the same data the pages render.
  • Do not treat absence as unavailability — see the visibility note above.
  • Paginate with total and offset. Do not assume limit bounds the result set; it bounds the page.
  • Use sort=sku for a full crawl. Request at most 100 items per page, deduplicate by SKU and advance the offset by the page size. The catalogue can change during pagination; refresh later if the total changes. Stop and investigate repeated empty pages before reaching the reported total.
  • Be a considerate crawler. Fetch sequentially, cache successful reads and use bounded retries with backoff. Do not repeatedly crawl the entire catalogue for a single customer enquiry.
  • Separate facts from suggestions. Do not invent specifications, compatibility, certifications, pack units, delivery promises or prices when fields are missing.
  • Keep the customer in control. Ask them to confirm the item list and quantities. A prepared list is not a submitted enquiry, a priced quote, an order or a stock reservation.
  • Protect contact details. Do not place names, email addresses, phone numbers or account details in public URLs or search queries.

Product pages render a selected layperson_description as the lead and a distinct description as longer selection guidance, including in server-rendered HTML. Without selected short copy, the description remains the lead and the empty or duplicate second paragraph is hidden. Public-field selection remains authoritative. Release the API renderer before the updated landing template; the renderer also accepts the previous template.