Skip to content
On this page

API для интеграции каталога товаров ритейл партнера

Цели

  • Возможность таргетирования на товары, бренды и категории товаров;
  • Возможность при запуске рекламных кампаний учитывать правила, предъявляемые к рекламе на товарах брендов-конкурентов.
  • Учет информации об остатках товаров на складах.

Реализация

Прежде чем начать

Вам должен быть известен API URL инстанса рекламной платформы. Попросите команду рекламной платформы выдать его вам.

Внимание

Если предполагается заливать только изменненые продукты (подразумевается как основной подход), то первый раз необходимо будет залить полный слепок текущего каталога и потом уже добавлять итеративно только измененные продукты.

Загрузка информации о товарах осуществляется через HTTP запросы к трем конечным точкам:

  • /api/v1/store - для загрузки данных о складах.
  • /api/v1/product - для загрузки данных о товарах.
  • /api/v1/remains/bystore - для загрузки информации об остатках на складах.

Авторизация запросов

API защищено API Key Authentication. Каждый запрос должен содержать специальный API Key в заголовке Authorization. Пример: Authorization: Bearer <api key>. API KEY будет предоставлен на этапе интеграции с API.

Добавление складов

С помощью PUT запроса на конечную точку /api/v1/store создаются новые склады и обновляются старые. В теле запроса ожидается массив с объектами, описывающими склад. Система позволяет добавить информацию для одного склада или загрузить все склады одним запросом.

Формат описания склада

ПараметрТипОписаниеОбязательное
idStringНазвание или порядковый номерДа
regionsString[]Субъекты РФ, обслуживаемые складом.regions или cities должно быть непустое
citiesString[]Названия городов, обслуживаемых складом.regions или cities должно быть непустое
json
[
  {
    "id": "store_1",
    "regions": ["Region"],
    "cities": ["City 1", "City 2", "City 3"]
  }
]
json
[
  {
    "errors": [
      {
        "fieldName": "cities/regions",
        "message": {
          "ru": "пустое значение",
          "en": "blank value"
        },
        "errorCode": 400
      }
    ],
    "requestJson": {
      "id": "store_1",
      "cities": [],
      "regions": []
    }
  },
  {
    "errors": [
      {
        "fieldName": "id",
        "message": {
          "ru": "Поле обязательно",
          "en": "Field is required"
        },
        "errorCode": 400
      }
    ],
    "requestJson": {
      "id": null,
      "cities": [],
      "regions": ["Region"]
    }
  }
]
json
{
  "metadata": {
    "description": "Request's body schema describing the creation or updating of a product store."
  },
  "elements": {
    "properties": {
      "id": {
        "type": "string"
      },
      "regions": {
        "elements": {
          "type": "string"
        }
      },
      "cities": {
        "elements": {
          "type": "string"
        }
      }
    }
  }
}

Ответ

Тело ответа будет пустым, если запрос выполнился успешно; в противном случае в теле ответа будет указана произошедшая ошибка.

Возможные статусы ответа:

  • 200 - Все данные были успешно загружены
  • 400 - Валидационные ошибки
  • 401 - Неавторизованный (API KEY невалиден или он отсутствует)
  • 500 - Внутренняя серверная ошибка

Добавление товаров

С помощью PUT запроса на эндпоинт /api/v1/product создаются новые товары в каталоге и обновляются старые. В теле запроса ожидается массив с объектами, описывающими товар. Система позволяет добавить информацию для одного товара или загрузить весь каталог одним запросом.

Формат описания товара

ПараметрТипОписаниеОбязательное
skuIdStringУникальный идентификатор продуктаДа
skuNameStringИмя продуктаДа
descriptionStringОписание продуктаНет
manufacturerStringПроизводитель продуктаНет
manufacturerCountryStringСтрана производителяНет
brandStringБренд продуктаНет
categoriesString[]Категории продукта (должно совпадать с тем, что присылается в рекламном запросе)Нет
imgUrlStringURL картинкиНет
urlStringURL продуктаНет
outdatedBoolЕсли продукт устаревший (не существует)Нет
extJSONДополнительная информация о продуктеНет
json
[
  {
    "skuId": "unique_sku_id",
    "skuName": "некий продукт",
    "description": "Описание продукта.",
    "manufacturer": "Производитель",
    "manufacturerCountry": "Россия",
    "brand": "Бренд",
    "categories": ["category_1", "category_2"],
    "imgUrl": "https://domain.com/unique_sku_id/640/480",
    "url": "https://domain.com/unique_sku_id",
    "outdated": false,
    "ext": {
      "param1": "параметр 1",
      "param2": "параметр 2"
    }
  }
]
json
{
  "errors": [
    {
      "errors": [
        {
          "fieldName": "skuId",
          "message": {
            "ru": "Поле обязательно",
            "en": "Field is required"
          },
          "errorCode": 400.0
        },
        {
          "fieldName": "skuName",
          "message": {
            "ru": "Поле обязательно",
            "en": "Field is required"
          },
          "errorCode": 400.0
        }
      ],
      "requestJson": {
        "description": "Texas background",
        "manufacturer": "Electronics",
        "manufacturerCountry": "Ethiopia",
        "brand": "Internal Implementation Administrator",
        "categories": ["Manager"],
        "imgUrl": "http://placeimg.com/640/480",
        "url": "http://nickolas.info",
        "outdated": false,
        "ext": {
          "param1": "Table Wooden Dalasi Senior enable",
          "param2": "application District Liechtenstein bottom-line ADP"
        }
      }
    }
  ]
}
json
{
  "metadata": {
    "description": "Schema of the Request for Create or Update Products"
  },
  "elements": {
    "properties": {
      "skuId": {
        "type": "string"
      },
      "skuName": {
        "type": "string"
      }
    },
    "optionalProperties": {
      "description": {
        "type": "string"
      },
      "manufacturer": {
        "type": "string"
      },
      "manufacturerCountry": {
        "type": "string"
      },
      "brand": {
        "type": "string"
      },
      "categories": {
        "elements": {
          "type": "string"
        }
      },
      "imgUrl": {
        "type": "string"
      },
      "url": {
        "type": "string"
      },
      "outdated": {
        "type": "boolean"
      },
      "ext": {
        "optionalProperties": {
          "format": {
            "type": "string"
          },
          "activeIngredients": {
            "type": "string"
          },
          "composition": {
            "type": "string"
          },
          "pharmGroup": {
            "type": "string"
          },
          "indications": {
            "type": "string"
          },
          "contraindications": {
            "type": "string"
          },
          "prescription": {
            "type": "boolean"
          },
          "imgSmallUrl": {
            "type": "string"
          }
        }
      }
    }
  }
}

Ответ

Тело ответа будет пустым, если запрос выполнился успешно, в противном случае в теле ответа будет указана произошедшая ошибка.

Возможные статусы ответа:

  • 200 - Все данные были успешно загружены
  • 400 - Валидационные ошибки
  • 401 - Неавторизованный (API KEY невалиден или он отсутствует)
  • 500 - Внутренняя серверная ошибка

Добавление товарных остатков

С помощью PUT запроса на эндпоинт /api/v1/remains/bystore добавляется информация об остатках товаров на тех или иных складах. В теле запроса ожидается массив с объектами, содержащими склад и список доступных товаров в нем. Товары, отсутствующие в этом списке считаются отсутствующими в данном складе.

Формат описания остатков

ПараметрТипОписаниеОбязательное
storeIdStringИдентификатор складаДа
productsString[]Массив уникальных идентификаторов продуктовДа
json
[
  {
    "storeId": "xI1d",
    "products": ["d3456070-dd44-46cd-a558-d0d249777c98", "d3456070-dd44-46cd-a558-d0d249777c99"]
  }
]
json
{
  "results": [
    {
      "code": "PRODUCTS_NOT_FOUND",
      "details": "The list of products which do not exists in the Product Catalog",
      "products": ["d3456070-dd44-46cd-a558-d0d249777c98"]
    },
    {
      "code": "STORES_NOT_FOUND",
      "details": "The list of stores which do not exists in the Product Catalog",
      "stores": ["xI1d"]
    }
  ]
}
json
{
  "metadata": {
    "description": "The schema of the Request for Update Remains of Products"
  },
  "elements": {
    "properties": {
      "storeId": {
        "type": "string"
      },
      "products": {
        "elements": {
          "type": "string"
        }
      }
    }
  }
}

Ответ

Тело ответа будет пустым, если запрос выполнился успешно, в противном случае в теле ответа будет указана произошедшая ошибка.

Возможные статусы ответа:

  • 200 - Все данные были успешно загружены
  • 400 - Валидационные ошибки
  • 401 - Неавторизованный (API KEY невалиден или он отсутствует)
  • 500 - Внутренняя серверная ошибка

Дополнительные параметры в рекламных запросах

  • brand - наименование бренда товарова, полученного в момент когда пользователь находится в карточке товара (web, iOS и Android приложения)
  • city - наименование города, который выбрал пользователь в приложении или определила само приложение по геопозиции пользователя.
  • region - наименование региона, который выбрал пользователь в приложении или определила само приложение по геопозиции пользователя.

Пример запроса Web SDK

Ниже приведен пример использования дополнительных параметров при создании запроса в Web SDK. Для более детального изучения Web SDK смотри документацию.

js
import webSDK from 'https://test-sdk.com/web-sdk.js';
    webSDK.init({
      uid: "User ID if logged",
      sessionId: "User Session ID",
      bannerURL: "https://test.url",
    });

webSDK.loadBanner('placement_id',
  {
    sizes: [{ w: 240, h: 300 }]
    refresh: 30,
    customParams: {
      "skuId": "LG00001",
      "skuName": "Leggo bricks (speed boat)",
      "category": "Kids",
      "brand": "Lego",
      "city": "City",
      "region": "Region"
    }
  }
);

Пример заапроса iOS SDK

Ниже приведен пример использования дополнительных параметров при создании запроса в iOS SDK. Для более детального изучения iOS SDK смотри документацию.

swift
class MyViewController: UIViewController {

    @IBOutlet weak var creativeView: CreativeView!

    private var creative: Creative!

    override func viewDidLoad() {
        super.viewDidLoad()

        . . .

        // Configure creative request query, here
        creativeView.query = CreativeQuery(
            placementId: "YOUR_PLACEMENT_ID",
            sizes: [SizeEntity(width: 260, height: 106)],
            floorPrice: 2.0,
            currency: "USD",
            customParams: [
                "skuId": "LG00001",
                "skuName": "Leggo bricks (speed boat)",
                "category": "Kids",
                "gdprConsent": "CPsmEWIPsmEWIABAMBFRACBsABEAAAAgEIYgACJAAYiAAA.QRXwAgAAgivA",
                "ccpa": "1YNN",
                "coppa": "1",
                "brand": "Lego",
                "city": "City",
                "region": "Region"
            ]
        )

        // Let's init creative controller
        self.creative = .init(creativeView: creativeView)

        // Finally, let's load creatives
        self.creative.load()
    }
}

Пример запроса Android SDK

Ниже приведен пример использования дополнительных параметров при создании запроса в Android SDK. Для более детального изучения Android SDK смотри документацию.

kotlin
class MyActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMyBinding
    private lateinit var creative: Creative

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMyBinding.inflate(layoutInflater)

        val creativeView = binding.creativeView

        // Configure creative request query, here
        creativeView.query = CreativeQuery(
            placementId = "YOUR_PLACEMENT_ID",
            sizes = listOf(Size(width = 260, height = 106)),
            floorPrice = 2.0,
            currency = "USD",
            customParams = mapOf(
                "skuId" to "LG00001",
                "skuName" to "Lego bricks (speed boat)",
                "category" to "Kids",
                "gdprConsent" to "CPsmEWIPsmEWIABAMBFRACBsABEAAAAgEIYgACJAAYiAAA.QRXwAgAAgivA",
                "ccpa" to "1YNN",
                "coppa" to "1",
                "brand" to "Lego",
                "city" to "City",
                "region" to "Region"
            ),
        )

        // Let's init creative controller
        creative = Creative(
            lifecycle = lifecycle,
            creativeView = creativeView
        )

        setContentView(binding.root)

        // Finally, let's load creatives
        creative.load()
}