Skip to main content

Products

GET /products

Returns the full product catalogue available to the authenticated customer. Each element of the response array is one product (one SKU) with its nested images, accessories, substitutions, composition, and prices.

Authentication

Required. Bearer token from /auth/token.

Request

No query parameters, path parameters, or request body. The response is scoped to your customer record automatically.

Example

GET /products HTTP/1.1
Host: api.kiss.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json

Response

200 OK with a JSON array. Each element conforms to the Product model. Nested arrays use:

Example response

[
{
"SKU": "DRAC001",
"Name": "Dracula Adult Costume",
"Description": "Black cape, red lining, plastic fangs.",
"WebsiteDescription": "Sink your teeth into Halloween with this classic vampire look.",
"ProductCategoryCode": "HALLOWEEN-ADULT",
"WashingInstructions": "Hand wash cold, do not bleach.",
"Gender": "Male",
"Audience": "Adult",
"MainColour": "Black",
"Barcode": "5012345678901",
"Photo": "https://cdn.kiss.example.com/img/DRAC001.jpg",
"Theme": "Halloween",
"PackagedLength_in_cm": 30.00,
"PackagedWidth_in_cm": 25.00,
"PackagedHeight_in_cm": 5.00,
"PackagedWeight_in_g": 450.00,
"CartonLength_in_cm": 60.00,
"CartonWidth_in_cm": 50.00,
"CartonHeight_in_cm": 40.00,
"CartonWeight_in_g": 5400.00,
"CartonQty": 12,
"AmazonASIN": "B0ABCDE123",
"CountryOfOrigin": "CN",
"Status": "ACTIVE",
"StyleCode": "STY-DRAC",
"CartonBarcode": "15012345678908",
"HSCode": "6114.30",
"WhatsIncluded": "Cape, fangs, medallion.",
"ProductCompositionText": "100% polyester outer.",
"ProductImages": [
{ "ImageID": "IMG001", "FileName": "DRAC001_front.jpg", "IsPrimaryImage": true },
{ "ImageID": "IMG002", "FileName": "DRAC001_back.jpg", "IsPrimaryImage": false }
],
"ProductAccessories": [ { "AccessorySKU": "FANG001" } ],
"ProductSubstitutions": [ { "SubstituteSKU": "DRAC002" } ],
"ProductComposition": [
{ "MaterialCode": "POLY", "MaterialDescription": "Polyester", "CompositionPercentage": 100.00 }
],
"ProductPrices": [
{
"PriceListCode": "EUR-WHOLESALE",
"PriceListName": "EUR Wholesale 2026",
"CurrencyCode": "EUR",
"SKU": "DRAC001",
"PriceExclVAT": 19.9500,
"MOQ": 12,
"OrderMultiple": 12
}
]
}
]

Filtering behaviour

Server-side filters are applied automatically; you cannot turn them off:

  • Obsolete products are excluded. Products whose Status is the literal string OBSOLETE are not returned.
  • Price-list scoping. Only products that exist in your assigned price list are returned. SKUs you cannot buy are never returned.
  • Nested ProductPrices is filtered. Each product's ProductPrices array contains only entries from your assigned price list — you will not see other customers' prices.
  • Discounts pre-applied. Where a price-list entry permits a customer discount and your account has a discount percentage, the figure in PriceExclVAT is the net price you pay, rounded to four decimal places.

Pagination

This endpoint does not paginate. The entire eligible catalogue is returned in a single response. For large catalogues this can be several megabytes — see Performance tips.

Status codes

StatusCause
200Success.
401Missing, malformed, or expired bearer token.
404Your customer record could not be found. Body: { "error": "Customer not found." }
429Rate limited — see Rate limits.
500Unexpected server error.

Performance tips

  • Use a streaming JSON parser if your catalogue is large. The response is one large JSON array, so a streaming parser uses less memory than reading the whole body into RAM.
  • Cache responses. The catalogue changes slowly. Most customers refresh once a day; refreshing every few minutes is rarely necessary and counts against your rate limit.
  • Reconcile by SKU. This is the stable identifier. Use it as the primary key when joining to your local product table.
  • Watch the schema. If your client cares about the exact shape of the response, poll /products/schema on startup and compare it to a cached copy. Note that the schema reports field names in camelCase even though the data responses use PascalCase.