Pobieranie katalogu
OpenApp pobiera katalog produktów z endpointu udostępnionego przez merchanta i skonfigurowanego w panelu merchanta. Pierwsze pobranie importuje pełny katalog; kolejne pobrania są przyrostowe i zwracają tylko produkty zmienione od ostatniej synchronizacji.
Po początkowej pełnej synchronizacji OpenApp może również przeprowadzać pełne odświeżenie w godzinach niskiego ruchu, aby uzupełnić ewentualne luki powstałe w synchronizacjach przyrostowych.
Żądanie
OpenApp wykonuje żądanie HTTP GET do skonfigurowanego endpointu:
GET <catalogue-url>?checkpoint=<checkpoint>&limit=<limit>
| Parametr | Opis |
|---|---|
checkpoint | Nieprzejrzysty string (patrz niżej) kodujący pozycję w katalogu, od której należy kontynuować. Nieobecny przy pełnej synchronizacji - w takim przypadku należy zwrócić wszystkie produkty. |
limit | Maksymalna liczba produktów, którą OpenApp chce otrzymać na jednej stronie. |
Format checkpointu
Checkpoint to string zakodowany w Base64 zawierający epoch milisekundy updatedAt oraz id ostatniego produktu zwróconego na poprzedniej stronie, oddzielone dwukropkiem:
Base64("<updatedAt epoch millis>:<last product id>")
Każdy produkt musi zawierać wartość updatedAt, ponieważ OpenApp używa jej do tworzenia i dekodowania checkpointów.
Produkty muszą być zwracane w rosnącej kolejności (updatedAt, id). Merchant musi zwrócić wszystkie produkty, których updatedAt jest ściśle większe niż zakodowany znacznik czasu, oraz wszystkie produkty, których updatedAt jest równe zakodowanemu znacznikowi czasu i których id jest leksykograficznie większe niż zakodowane id (w celu obsługi remisów). To porządkowanie zapewnia przesuwanie checkpointu z każdą stroną.
Na przykład, jeśli ostatni produkt na poprzedniej stronie miał updatedAt = 2026-06-09T11:48:12.000Z i id = id123 (epoch millis 1781005692000):
MTc4MTAwNTY5MjAwMDppZDEyMw==
Zatem jeśli skonfigurowano adres https://shop.example.com/api/openapp/catalogue, żądanie wykonane przez OpenApp dla drugiej strony będzie wyglądać następująco:
GET https://shop.example.com/api/openapp/catalogue?checkpoint=MTc4MTAwNTY5MjAwMDppZDEyMw%3D%3D&limit=500
Odpowiedź
W odpowiedzi merchant zwraca stronę produktów wraz z nextCheckpoint kodującym pozycję ostatniego produktu na stronie. Merchant musi uwzględnić nextCheckpoint, gdy products jest niepuste. OpenApp wysyła kolejne żądania stron, dopóki nie otrzyma strony z pustą tablicą products - wtedy ostatni otrzymany nextCheckpoint jest zapisywany jako checkpoint dla następnej synchronizacji przyrostowej.
Produkty są zwracane w rosnącej kolejności (updatedAt, id). W poniższym przykładzie wycofany produkt był ostatnio aktualizowany najwcześniej i dlatego pojawia się pierwszy; dwa aktywne produkty następują w kolejności chronologicznej.
- Odpowiedź
- Schemat
{
"currency": "PLN",
"products": [
{
"id": "id125",
"updatedAt": "2026-06-07T16:30:00.000Z",
"name": "Discontinued product",
"status": "DELISTED",
"variants": [
{
"id": "id125",
"unitPrice": 4500,
"stock": {
"isAvailable": false
}
}
]
},
{
"id": "id124",
"updatedAt": "2026-06-08T09:15:00.000Z",
"name": "Superb product 2",
"categories": [
"Home",
"Kitchen",
"Cookware"
],
"images": [
"http://cdn.merchant.com/static/products/id124/1"
],
"url": "https://shop.example.com/products/id124",
"status": "ACTIVE",
"variants": [
{
"id": "id124",
"ean": "5901234123464",
"unitPrice": 6000,
"stock": {
"isAvailable": true,
"availableQuantity": 3
},
"measurement": {
"type": "VOLUME",
"quantityValue": 500,
"quantityUnit": "ML"
}
}
]
},
{
"id": "id123",
"updatedAt": "2026-06-09T11:48:12.000Z",
"name": "Superb product",
"description": "A superb product that makes everyday cooking easier.",
"brandName": "SuperBrand",
"categories": [
"Home",
"Kitchen",
"Cookware"
],
"images": [
"http://cdn.merchant.com/static/products/id123/1",
"http://cdn.merchant.com/static/products/id123/2"
],
"url": "https://shop.example.com/products/id123",
"status": "ACTIVE",
"variants": [
{
"id": "id123-red",
"name": "Red",
"ean": "5901234123457",
"unitPrice": 6000,
"originalUnitPrice": 7000,
"stock": {
"isAvailable": true,
"availableQuantity": 5
},
"measurement": {
"type": "WEIGHT",
"quantityValue": 0.3,
"quantityUnit": "KG",
"referenceValue": 100,
"referenceUnit": "G"
}
},
{
"id": "id123-blue",
"name": "Blue",
"ean": "5901234123471",
"unitPrice": 7000,
"stock": {
"isAvailable": true
},
"measurement": {
"type": "WEIGHT",
"quantityValue": 0.3,
"quantityUnit": "KG",
"referenceValue": 100,
"referenceUnit": "G"
}
}
]
}
],
"nextCheckpoint": "MTc4MTAwNTY5MjAwMDppZDEyMw=="
}
currencystringWymaganeThe currency of all prices in this response.
productstablica typu CatalogueProductWymaganePokaż parametry podrzędneUkryj parametry podrzędne11
idstringWymaganeThe unique ID of the product. Groups its variants. Any change to a variant must bump this product's updatedAt.
maxLength: 36
updatedAtstringWymaganeThe moment the product or any of its variants was last changed in the merchant system.
format: date-time
namestringWymaganeThe product name.
maxLength: 255
descriptionstringOpcjonalneThe product description. Plain text, no HTML.
maxLength: 5000
descriptionHtmlstringOpcjonalneThe product description as HTML. Provide description, descriptionHtml, or both.
brandNamestringOpcjonalneThe brand of the product. Optional, but strongly recommended - significantly improves recommendation quality.
maxLength: 255
categoriestablica typu stringOpcjonalneThe category path of the product from the most generic to the most specific category, i.e. ["Home", "Kitchen", "Cookware"].
imagestablica typu stringOpcjonalneThe URLs of the product images. Optional, but strongly recommended - significantly improves recommendation quality. Variants may override with their own images.
urlstringOpcjonalneThe URL of the product page in the webshop.
statusenumOpcjonalneThe listing status of the product. DELISTED informs OpenApp the product was permanently removed from the catalogue. Defaults to ACTIVE.
Możliwe wartości: ACTIVEDELISTED
variantstablica typu CatalogueVariantWymaganeThe sellable variants of this product. Every product has at least one variant. For products without real variants (a single SKU), provide exactly one variant - its id may be the same as the product id. Prices, stock, measurement and barcode live on variants.
minItems: 1
Pokaż parametry podrzędneUkryj parametry podrzędne8
idstringWymaganeThe unique ID of the variant. This is the product ID used in basket retrieval, order placement, the recommendations order feed, the wishlist feed and recommendation responses. Must be consistent across all APIs.
maxLength: 36
namestringOpcjonalneThe variant name, e.g. 'Red / M'. When absent, the product name applies.
maxLength: 255
eanstringOpcjonalneThe ean (or other barcode) of the variant. Optional, but strongly recommended - significantly improves recommendation quality.
maxLength: 36
unitPriceintegerWymaganeThe current price of a single item. Price is expressed as the number (integer) of 1/100s of the price.
minimum: 0
originalUnitPriceintegerOpcjonalneThe original (before discount) price of a single item. Price is expressed as the number (integer) of 1/100s of the price. Omit when the variant is not discounted.
minimum: 0
stockobiektWymaganeThe stock status of the variant.
Pokaż parametry podrzędneUkryj parametry podrzędne2
isAvailablebooleanWymaganeWhether the variant is available for purchase.
availableQuantityintegerOpcjonalneThe number of items available in stock. Omit when inventory is not tracked - isAvailable: true with no availableQuantity means available with untracked inventory.
minimum: 0
measurementjeden z: WeightMeasurement, VolumeMeasurementOpcjonalneThe net content of a single item. Used for unit pricing display and replenishment predictions.
Pokaż parametry podrzędneUkryj parametry podrzędne2
WeightMeasurementobiektPokaż parametry podrzędneUkryj parametry podrzędne5
typeliterał "WEIGHT"WymaganeIdentifies this as a weight measurement.
Wartość: WEIGHT
quantityValuenumberWymaganeThe net weight amount.
exclusiveMinimum: 0
quantityUnitenumWymaganeThe unit of quantityValue.
Możliwe wartości: GKGMG
referenceValuenumberOpcjonalneReference amount for unit pricing display, e.g. 100 (with referenceUnit G) to show a price-per-100g label. Required when referenceUnit is set.
exclusiveMinimum: 0
referenceUnitenumOpcjonalneUnit of the reference amount. Required when referenceValue is set.
Możliwe wartości: GKGMG
VolumeMeasurementobiektPokaż parametry podrzędneUkryj parametry podrzędne5
typeliterał "VOLUME"WymaganeIdentifies this as a volume measurement.
Wartość: VOLUME
quantityValuenumberWymaganeThe net volume amount.
exclusiveMinimum: 0
quantityUnitenumWymaganeThe unit of quantityValue.
Możliwe wartości: MLCLLM3
referenceValuenumberOpcjonalneReference amount for unit pricing display, e.g. 100 (with referenceUnit ML) to show a price-per-100ml label. Required when referenceUnit is set.
exclusiveMinimum: 0
referenceUnitenumOpcjonalneUnit of the reference amount. Required when referenceValue is set.
Możliwe wartości: MLCLLM3
imagestablica typu stringOpcjonalneVariant-specific image URLs. When absent, the product images apply.
nextCheckpointstring lub nullOpcjonalneAn opaque Base64-encoded string encoding the position of the last product in this page (updatedAt epoch millis + id). OpenApp sends this value as the checkpoint parameter of the next request. Must be present whenever products is non-empty. Omit or set to null only on the final empty-products page that signals end of sync.
maxLength: 255
Surowy schemat JSON
{
"description": "A page of the merchant product catalogue returned on catalogue polling",
"additionalProperties": false,
"type": "object",
"properties": {
"currency": {
"description": "The currency of all prices in this response.",
"type": "string",
"title": "currency"
},
"products": {
"type": "array",
"items": {
"$ref": "#/definitions/CatalogueProduct"
},
"title": "products"
},
"nextCheckpoint": {
"description": "An opaque Base64-encoded string encoding the position of the last product in this page (updatedAt epoch millis + id). OpenApp sends this value as the checkpoint parameter of the next request. Must be present whenever products is non-empty. Omit or set to null only on the final empty-products page that signals end of sync.",
"maxLength": 255,
"type": [
"string",
"null"
],
"title": "nextCheckpoint"
}
},
"required": [
"currency",
"products"
],
"definitions": {
"CatalogueProduct": {
"title": "CatalogueProduct",
"type": "object",
"properties": {
"id": {
"description": "The unique ID of the product. Groups its variants. Any change to a variant must bump this product's updatedAt.",
"maxLength": 36,
"type": "string",
"title": "id"
},
"updatedAt": {
"description": "The moment the product or any of its variants was last changed in the merchant system.",
"format": "date-time",
"type": "string",
"title": "updatedAt"
},
"name": {
"description": "The product name.",
"maxLength": 255,
"type": "string",
"title": "name"
},
"description": {
"description": "The product description. Plain text, no HTML.",
"maxLength": 5000,
"type": "string",
"title": "description"
},
"descriptionHtml": {
"description": "The product description as HTML. Provide description, descriptionHtml, or both.",
"type": "string",
"title": "descriptionHtml"
},
"brandName": {
"description": "The brand of the product. Optional, but strongly recommended - significantly improves recommendation quality.",
"maxLength": 255,
"type": "string",
"title": "brandName"
},
"categories": {
"description": "The category path of the product from the most generic to the most specific category, i.e. [\"Home\", \"Kitchen\", \"Cookware\"].",
"type": "array",
"items": {
"maxLength": 255,
"type": "string"
},
"title": "categories"
},
"images": {
"description": "The URLs of the product images. Optional, but strongly recommended - significantly improves recommendation quality. Variants may override with their own images.",
"type": "array",
"items": {
"type": "string"
},
"title": "images"
},
"url": {
"description": "The URL of the product page in the webshop.",
"type": "string",
"title": "url"
},
"status": {
"description": "The listing status of the product. DELISTED informs OpenApp the product was permanently removed from the catalogue. Defaults to ACTIVE.",
"enum": [
"ACTIVE",
"DELISTED"
],
"type": "string",
"title": "status"
},
"variants": {
"description": "The sellable variants of this product. Every product has at least one variant. For products without real variants (a single SKU), provide exactly one variant - its id may be the same as the product id. Prices, stock, measurement and barcode live on variants.",
"minItems": 1,
"type": "array",
"items": {
"$ref": "#/definitions/CatalogueVariant"
},
"title": "variants"
}
},
"required": [
"id",
"updatedAt",
"name",
"variants"
]
},
"CatalogueVariant": {
"title": "CatalogueVariant",
"type": "object",
"properties": {
"id": {
"description": "The unique ID of the variant. This is the product ID used in basket retrieval, order placement, the recommendations order feed, the wishlist feed and recommendation responses. Must be consistent across all APIs.",
"maxLength": 36,
"type": "string",
"title": "id"
},
"name": {
"description": "The variant name, e.g. 'Red / M'. When absent, the product name applies.",
"maxLength": 255,
"type": "string",
"title": "name"
},
"ean": {
"description": "The ean (or other barcode) of the variant. Optional, but strongly recommended - significantly improves recommendation quality.",
"maxLength": 36,
"type": "string",
"title": "ean"
},
"unitPrice": {
"description": "The current price of a single item. Price is expressed as the number (integer) of 1/100s of the price.",
"minimum": 0,
"type": "integer",
"title": "unitPrice"
},
"originalUnitPrice": {
"description": "The original (before discount) price of a single item. Price is expressed as the number (integer) of 1/100s of the price. Omit when the variant is not discounted.",
"minimum": 0,
"type": "integer",
"title": "originalUnitPrice"
},
"stock": {
"description": "The stock status of the variant.",
"$ref": "#/definitions/VariantStock",
"title": "stock"
},
"measurement": {
"description": "The net content of a single item. Used for unit pricing display and replenishment predictions.",
"oneOf": [
{
"$ref": "#/definitions/WeightMeasurement"
},
{
"$ref": "#/definitions/VolumeMeasurement"
}
],
"title": "measurement"
},
"images": {
"description": "Variant-specific image URLs. When absent, the product images apply.",
"type": "array",
"items": {
"type": "string"
},
"title": "images"
}
},
"required": [
"id",
"unitPrice",
"stock"
]
},
"VariantStock": {
"title": "VariantStock",
"type": "object",
"properties": {
"isAvailable": {
"description": "Whether the variant is available for purchase.",
"type": "boolean",
"title": "isAvailable"
},
"availableQuantity": {
"description": "The number of items available in stock. Omit when inventory is not tracked - isAvailable: true with no availableQuantity means available with untracked inventory.",
"minimum": 0,
"type": "integer",
"title": "availableQuantity"
}
},
"required": [
"isAvailable"
]
},
"WeightMeasurement": {
"title": "WeightMeasurement",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Identifies this as a weight measurement.",
"const": "WEIGHT",
"type": "string",
"title": "type"
},
"quantityValue": {
"description": "The net weight amount.",
"exclusiveMinimum": 0,
"type": "number",
"title": "quantityValue"
},
"quantityUnit": {
"description": "The unit of quantityValue.",
"enum": [
"G",
"KG",
"MG"
],
"type": "string",
"title": "quantityUnit"
},
"referenceValue": {
"description": "Reference amount for unit pricing display, e.g. 100 (with referenceUnit G) to show a price-per-100g label. Required when referenceUnit is set.",
"exclusiveMinimum": 0,
"type": "number",
"title": "referenceValue"
},
"referenceUnit": {
"description": "Unit of the reference amount. Required when referenceValue is set.",
"enum": [
"G",
"KG",
"MG"
],
"type": "string",
"title": "referenceUnit"
}
},
"required": [
"type",
"quantityValue",
"quantityUnit"
]
},
"VolumeMeasurement": {
"title": "VolumeMeasurement",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "Identifies this as a volume measurement.",
"const": "VOLUME",
"type": "string",
"title": "type"
},
"quantityValue": {
"description": "The net volume amount.",
"exclusiveMinimum": 0,
"type": "number",
"title": "quantityValue"
},
"quantityUnit": {
"description": "The unit of quantityValue.",
"enum": [
"ML",
"CL",
"L",
"M3"
],
"type": "string",
"title": "quantityUnit"
},
"referenceValue": {
"description": "Reference amount for unit pricing display, e.g. 100 (with referenceUnit ML) to show a price-per-100ml label. Required when referenceUnit is set.",
"exclusiveMinimum": 0,
"type": "number",
"title": "referenceValue"
},
"referenceUnit": {
"description": "Unit of the reference amount. Required when referenceValue is set.",
"enum": [
"ML",
"CL",
"L",
"M3"
],
"type": "string",
"title": "referenceUnit"
}
},
"required": [
"type",
"quantityValue",
"quantityUnit"
]
}
},
"$schema": "http://json-schema.org/draft-07/schema#"
}
Produkty i warianty
Każdy produkt zawiera co najmniej jeden wariant. Dla produktów z pojedynczym wariantem należy podać dokładnie jeden wariant - jego id może być takie samo jak id produktu. Ceny, stan magazynowy, jednostka miary i kod kreskowy są przypisane do wariantu, nie do produktu.
id wariantu to identyfikator używany we wszystkich pozostałych API: pobieraniu koszyka, składaniu zamówienia, feedzie zamówień rekomendacji, feedzie wishlisty i odpowiedziach rekomendacji.
Każda zmiana wariantu - cena, stan magazynowy, EAN - musi zaktualizować updatedAt produktu, ponieważ synchronizacja przyrostowa i checkpointy działają na poziomie produktu.
Stan magazynowy jest wyrażony jako { isAvailable, availableQuantity? }. availableQuantity jest obecne tylko wtedy, gdy merchant śledzi stany magazynowe. isAvailable: true bez availableQuantity oznacza, że wariant jest dostępny, ale stany nie są śledzone.
Pola ean wariantu, images produktu i brandName produktu są opcjonalne, ale ich uwzględnienie znacząco poprawia algorytm rekomendacji. Podanie tych pól jest zalecane.
Jeśli endpoint merchanta zwróci błąd lub przekroczy czas oczekiwania podczas zaplanowanego pobierania, OpenApp ponowi próbę przy następnym cyklu synchronizacji. Nie jest wymagane żadne działanie ze strony merchanta.
Produkty usunięte z systemu merchanta nie mogą pojawić się w odpowiedzi synchronizacji przyrostowej. Aby poinformować OpenApp o usunięciu, należy:
- Oznaczyć produkt jako
DELISTEDi nadal zwracać go w odpowiedziach przyrostowych tak długo, jak system merchanta przechowuje jego zapis, lub - Pozwolić OpenApp obsłużyć to automatycznie: podczas każdego okresowego pełnego odświeżenia wszystkie produkty wcześniej znane OpenApp, nieobecne w odpowiedzi merchanta, zostaną automatycznie wycofane.