Product API

Product API для управления товарами в каталоге продавца с 23 методами для комплексного управления товарным ассортиментом.

Обзор

Product API обеспечивает полный жизненный цикл товаров от создания до архивирования. Включает управление атрибутами, изображениями, SKU, ценами, остатками и метаинформацией.

Основные возможности:

  • 📦 Архивирование и восстановление товаров
  • 📋 Получение списков товаров с фильтрацией
  • 🔧 Обновление атрибутов и характеристик
  • 📤 Импорт товаров по SKU
  • 🖼️ Управление изображениями
  • 📊 Мониторинг цен и остатков
  • ⭐ Анализ рейтингов и отзывов
  • 🔗 Связанные SKU и рекомендации

Доступные методы

Управление жизненным циклом товаров

archiveProducts(request) - Архивирование товаров

const result = await productApi.archiveProducts({
  product_id: [123456, 789012, 345678]
});

unarchiveProducts(request) - Разархивирование товаров

const result = await productApi.unarchiveProducts({
  product_id: [123456, 789012]
});

deleteProducts(request) - Удаление товаров

const result = await productApi.deleteProducts({
  offers: [
    { offer_id: "ITEM001" },
    { product_id: 123456 }
  ]
});

Получение информации о товарах

getProductsList(request) - Список товаров

const products = await productApi.getProductsList({
  filter: {
    offer_id: ["ITEM001", "ITEM002"],
    visibility: "VISIBLE"
  },
  limit: 100
});

getProductInfo(request) - Подробная информация о товаре

const info = await productApi.getProductInfo({
  sku: 987654321,
  offer_id: "ITEM001",
  product_id: 123456
});

getProductInfoListV3(request) - Расширенная информация V3

const infoList = await productApi.getProductInfoListV3({
  filter: {
    offer_id: ["ITEM001", "ITEM002"],
    product_id: [123456, 789012]
  },
  limit: 50
});

Импорт и управление товарами

importProductsBySku(request) - Импорт по SKU

const importResult = await productApi.importProductsBySku({
  items: [
    { sku: 987654321, offer_id: "ITEM001" },
    { sku: 123456789, offer_id: "ITEM002" }
  ]
});

importProducts(request) - Общий импорт товаров

const result = await productApi.importProducts({
  items: [
    {
      offer_id: "NEW_ITEM",
      barcode: "1234567890123",
      category_id: 15621,
      name: "Новый товар",
      price: "1500",
      old_price: "2000",
      currency_code: "RUB",
      attributes: [
        {
          complex_id: 0,
          id: 85,
          values: [{ dictionary_value_id: 971082156 }]
        }
      ]
    }
  ]
});

getImportProductsInfo(request) - Статус импорта

const status = await productApi.getImportProductsInfo({
  task_id: "task_123456"
});

Управление атрибутами и характеристиками

updateProductAttributes(request) - Обновление атрибутов

const result = await productApi.updateProductAttributes({
  items: [
    {
      offer_id: "ITEM001",
      attributes: [
        {
          complex_id: 0,
          id: 85,
          values: [{ dictionary_value_id: 971082156 }]
        }
      ]
    }
  ]
});

getProductAttributes(request) - Атрибуты товара

const attributes = await productApi.getProductAttributes({
  filter: {
    offer_id: ["ITEM001"],
    visibility: "VISIBLE"
  },
  limit: 100
});

getCertificationTypes(request) - Типы сертификации

const certTypes = await productApi.getCertificationTypes({
  category_id: 15621,
  type_id: 1
});

Управление изображениями

importProductPictures(request) - Импорт изображений

const result = await productApi.importProductPictures({
  product_id: 123456,
  images: [
    {
      file_name: "product1.jpg",
      url: "https://example.com/images/product1.jpg"
    },
    {
      file_name: "product2.jpg",
      url: "https://example.com/images/product2.jpg"
    }
  ]
});

getProductPictures(request) - Получение изображений

const pictures = await productApi.getProductPictures({
  product_id: [123456, 789012]
});

Цены и остатки

getProductStocks(request) - Остатки товаров

const stocks = await productApi.getProductStocks({
  filter: {
    offer_id: ["ITEM001", "ITEM002"],
    visibility: "VISIBLE"
  },
  limit: 100
});

getProductPrices(request) - Цены товаров

const prices = await productApi.getProductPrices({
  filter: {
    offer_id: ["ITEM001", "ITEM002"],
    visibility: "VISIBLE"
  },
  limit: 100
});

Рейтинги и аналитика

getProductRating(request) - Рейтинг товара

const rating = await productApi.getProductRating({
  products: [
    { offer_id: "ITEM001" },
    { sku: 987654321 }
  ]
});

getRelatedSKU(request) - Связанные SKU

const relatedSku = await productApi.getRelatedSKU({
  sku: [987654321, 123456789]
});

Дополнительная информация

getDiscountedProductInfo(request) - Информация об уценке

const discountedInfo = await productApi.getDiscountedProductInfo({
  discounted_skus: ["987654321", "123456789"]
});

getProductDescription(request) - Описание товара

const description = await productApi.getProductDescription({
  offer_id: "ITEM001",
  product_id: 123456
});

getProductSubscription(request) - Подписки на товар

const subscription = await productApi.getProductSubscription({
  offer_id: "ITEM001",
  sku: 987654321
});

getUploadQuota(request) - Квота загрузки

const quota = await productApi.getUploadQuota();

updateOfferID(request) - Обновление артикула

const result = await productApi.updateOfferID({
  update_offer_id: [
    {
      offer_id: "OLD_ITEM",
      new_offer_id: "NEW_ITEM"
    }
  ]
});

TypeScript интерфейсы

// Основные запросы
interface ProductArchiveRequest {
  product_id: number[];
}

interface ProductUnarchiveRequest {
  product_id: number[];
}

interface ProductListRequest {
  filter: {
    offer_id?: string[];
    product_id?: number[];
    visibility?: "VISIBLE" | "INVISIBLE" | "EMPTY_STOCK" | "NOT_MODERATED" | "MODERATED" | "DISABLED" | "STATE_FAILED_MODERATION" | "READY_TO_SUPPLY" | "VALIDATION_STATE_PENDING" | "VALIDATION_STATE_FAIL" | "VALIDATION_STATE_SUCCESS" | "TO_SUPPLY" | "IN_SALE" | "REMOVED_FROM_SALE" | "BANNED" | "OVERPRICED" | "CRITICALLY_OVERPRICED" | "EMPTY_BARCODE" | "BARCODE_EXISTS" | "QUARANTINE" | "ARCHIVED" | "OVERPRICED_WITH_STOCK" | "PARTIAL_APPROVED" | "IMAGE_ABSENT" | "MODERATION_BLOCK";
  };
  sort?: "created_at" | "updated_at" | "price" | "name";
  sort_dir?: "asc" | "desc";
  limit: number;
  last_id?: string;
}

interface ProductInfoRequest {
  sku?: number;
  offer_id?: string;
  product_id?: number;
}

interface ProductImportBySKURequest {
  items: Array<{
    sku: number;
    offer_id: string;
  }>;
}

interface ProductImportRequest {
  items: Array<{
    offer_id: string;
    barcode?: string;
    category_id?: number;
    name?: string;
    price?: string;
    old_price?: string;
    currency_code?: string;
    vat?: string;
    height?: number;
    depth?: number;
    width?: number;
    dimension_unit?: string;
    weight?: number;
    weight_unit?: string;
    images?: Array<{
      file_name: string;
      default?: boolean;
    }>;
    attributes: Array<{
      complex_id: number;
      id: number;
      values: Array<{
        dictionary_value_id?: number;
        value?: string;
      }>;
    }>;
  }>;
}

interface ProductAttributesUpdateRequest {
  items: Array<{
    offer_id: string;
    attributes: Array<{
      complex_id: number;
      id: number;
      values: Array<{
        dictionary_value_id?: number;
        value?: string;
      }>;
    }>;
  }>;
}

interface ProductPicturesImportRequest {
  product_id: number;
  images: Array<{
    file_name: string;
    url: string;
  }>;
}

interface ProductOfferIDUpdateRequest {
  update_offer_id: Array<{
    offer_id: string;
    new_offer_id: string;
  }>;
}

interface ProductDeleteRequest {
  offers: Array<{
    offer_id?: string;
    product_id?: number;
  }>;
}

// Ответы
interface ProductListResponse {
  items: Array<{
    product_id: number;
    offer_id: string;
    is_fbo_visible: boolean;
    is_fbs_visible: boolean;
    archived: boolean;
    is_discounted: boolean;
  }>;
  total: number;
  last_id: string;
}

interface ProductInfoResponse {
  product_id: number;
  offer_id: string;
  barcode: string;
  category_id: number;
  name: string;
  offer_ids: string[];
  price: string;
  old_price: string;
  premium_price: string;
  currency_code: string;
  marketing_price: string;
  min_ozon_price: string;
  min_price: string;
  sources: Array<{
    is_enabled: boolean;
    sku: number;
    source: string;
  }>;
  stocks: Array<{
    coming: number;
    present: number;
    reserved: number;
    type: string;
  }>;
  errors: string[];
  vat: string;
  visible: boolean;
  visibility_details: {
    has_price: boolean;
    has_stock: boolean;
    active_product: boolean;
  };
  price_index: string;
  images: Array<{
    file_name: string;
    default: boolean;
    index: number;
  }>;
  image360: string[];
  pdf_list: Array<{
    index: number;
    name: string;
    src_url: string;
  }>;
  attributes: Array<{
    attribute_id: number;
    complex_id: number;
    values: Array<{
      dictionary_value_id: number;
      value: string;
    }>;
  }>;
  complex_attributes: any[];
  color_image: string;
  last_id: string;
  weight: number;
  dimensions: {
    height: number;
    length: number;
    weight: number;
    width: number;
  };
  description_category_id: number;
  type_id: number;
  is_kgt: boolean;
  sku: number;
  rating: string;
  tax_rate: string;
  discounted_stocks: {
    coming: number;
    present: number;
    reserved: number;
  };
  is_prepayment: boolean;
  is_prepayment_allowed: boolean;
  images360: any[];
  has_discounted_item: boolean;
  barcodes: string[];
  updated_at: string;
  price_indexes: {
    external_index_data: {
      minimal_price: string;
      minimal_price_currency: string;
      price_index_value: number;
    };
    ozon_index_data: {
      minimal_price: string;
      minimal_price_currency: string;
      price_index_value: number;
    };
    price_index: string;
    self_marketplaces_index_data: {
      minimal_price: string;
      minimal_price_currency: string;
      price_index_value: number;
    };
  };
  status: {
    state: string;
    state_failed_moderation_reasons: string[];
    moderate_status: string;
    decline_reasons: string[];
    validation_state: string;
    state_name: string;
    state_description: string;
    is_failed_moderation: boolean;
    is_created: boolean;
    state_tooltip: string;
    item_errors: Array<{
      code: string;
      field: string;
      attribute_id: number;
      attribute_name: string;
      optional_description_elements: any;
      state_description: string;
      level: string;
    }>;
    state_updated_at: string;
  };
  state: string;
  service_type: string;
  fbo_sku: number;
  fbs_sku: number;
  currency_code2: string;
  tags: any[];
  loyalty_earn_rate: number;
  created_at: string;
  parent_id: number;
  rich_content_json: string;
  primary_image: string;
  brand: string;
  acquisition?: {
    url: string;
    text: string;
  };
}

interface ProductImportResponse {
  task_id: string;
}

interface ProductImportInfoResponse {
  result: Array<{
    offer_id: string;
    product_id: number;
    status: string;
    errors: Array<{
      code: string;
      message: string;
    }>;
  }>;
}

interface ProductAttributesResponse {
  items: Array<{
    product_id: number;
    offer_id: string;
    attributes: Array<{
      attribute_id: number;
      complex_id: number;
      values: Array<{
        dictionary_value_id: number;
        value: string;
      }>;
    }>;
  }>;
  total: number;
  last_id: string;
}

interface ProductCertificationTypesResponse {
  certificate_types: Array<{
    id: number;
    name: string;
    is_required: boolean;
  }>;
}

interface ProductPicturesImportResponse {
  pictures: Array<{
    product_id: number;
    status: string;
    url: string;
    error: string;
  }>;
}

interface ProductPicturesResponse {
  items: Array<{
    product_id: number;
    images: Array<{
      file_name: string;
      default: boolean;
      index: number;
    }>;
  }>;
}

interface ProductRatingResponse {
  products: Array<{
    offer_id: string;
    sku: number;
    rating: string;
    groups: Array<{
      key: string;
      rating: string;
      count: number;
    }>;
  }>;
}

interface RelatedSKUResponse {
  items: Array<{
    sku: number;
    related_skus: number[];
  }>;
}

interface DiscountedProductInfoResponse {
  items: Array<{
    discounted_sku: number;
    original_sku: number;
    condition: string;
    defects: string[];
    discount_percentage: number;
  }>;
}

interface ProductDescriptionResponse {
  description: string;
  short_description: string;
  rich_content_json: string;
}

interface ProductSubscriptionResponse {
  subscription_info: {
    subscription_plan: string;
    is_auto_renewal: boolean;
    next_payment_date: string;
    status: string;
  };
}

interface UploadQuotaResponse {
  quota: {
    used: number;
    limit: number;
    reset_date: string;
  };
}

interface UpdateOfferIDResponse {
  errors: Array<{
    offer_id: string;
    error: string;
  }>;
}

interface DeleteProductsResponse {
  status: Array<{
    is_deleted: boolean;
    offer_id: string;
    product_id: number;
    error: string;
  }>;
}

Примеры использования

Создание нового товара

// 1. Импорт товара
const importResult = await productApi.importProducts({
  items: [
    {
      offer_id: "SMARTPHONE_001",
      barcode: "1234567890123",
      category_id: 15621,
      name: "Смартфон Premium XY",
      price: "45000",
      old_price: "50000",
      currency_code: "RUB",
      vat: "0.20",
      height: 150,
      depth: 10,
      width: 75,
      dimension_unit: "mm",
      weight: 200,
      weight_unit: "g",
      images: [
        { file_name: "smartphone_main.jpg", default: true },
        { file_name: "smartphone_side.jpg", default: false }
      ],
      attributes: [
        {
          complex_id: 0,
          id: 85, // Бренд
          values: [{ dictionary_value_id: 971082156 }]
        },
        {
          complex_id: 0,
          id: 5076, // Цвет
          values: [{ value: "Черный" }]
        }
      ]
    }
  ]
});

// 2. Проверка статуса импорта
const status = await productApi.getImportProductsInfo({
  task_id: importResult.task_id
});

// 3. Добавление изображений
if (status.result[0].status === "imported") {
  await productApi.importProductPictures({
    product_id: status.result[0].product_id,
    images: [
      {
        file_name: "smartphone_main.jpg",
        url: "https://example.com/images/smartphone_main.jpg"
      },
      {
        file_name: "smartphone_side.jpg", 
        url: "https://example.com/images/smartphone_side.jpg"
      }
    ]
  });
}

Управление каталогом товаров

// Получение списка товаров с фильтрацией
const productsList = await productApi.getProductsList({
  filter: {
    visibility: "VISIBLE",
    offer_id: ["SMARTPHONE_001", "TABLET_002"]
  },
  sort: "updated_at",
  sort_dir: "desc",
  limit: 50
});

// Получение подробной информации
const productInfo = await productApi.getProductInfo({
  offer_id: "SMARTPHONE_001"
});

// Обновление атрибутов
await productApi.updateProductAttributes({
  items: [
    {
      offer_id: "SMARTPHONE_001",
      attributes: [
        {
          complex_id: 0,
          id: 5076, // Цвет
          values: [{ value: "Синий" }]
        },
        {
          complex_id: 0,
          id: 8229, // Память
          values: [{ value: "128 ГБ" }]
        }
      ]
    }
  ]
});

Анализ производительности товаров

// Рейтинг товаров
const ratings = await productApi.getProductRating({
  products: [
    { offer_id: "SMARTPHONE_001" },
    { offer_id: "TABLET_002" },
    { sku: 987654321 }
  ]
});

ratings.products.forEach(product => {
  console.log(`Товар ${product.offer_id}: рейтинг ${product.rating}`);
  product.groups.forEach(group => {
    console.log(`  ${group.key}: ${group.rating} (${group.count} отзывов)`);
  });
});

// Связанные товары
const relatedSkus = await productApi.getRelatedSKU({
  sku: [987654321, 123456789]
});

relatedSkus.items.forEach(item => {
  console.log(`SKU ${item.sku} связан с: ${item.related_skus.join(", ")}`);
});

Сложные сценарии

ProductCatalogManager - Система управления каталогом

class ProductCatalogManager {
  constructor(private api: ProductApi) {}

  async createProductFamily(familyData: ProductFamilyData): Promise<ProductFamily> {
    const tasks: string[] = [];
    
    // Импорт всех товаров семейства
    for (const product of familyData.products) {
      const importResult = await this.api.importProducts({
        items: [product]
      });
      tasks.push(importResult.task_id);
    }

    // Ожидание завершения импорта
    const results = await Promise.all(
      tasks.map(taskId => this.waitForImportCompletion(taskId))
    );

    // Добавление изображений
    await Promise.all(
      results.map(result => this.addProductImages(result))
    );

    return {
      family_id: familyData.family_id,
      products: results,
      created_at: new Date().toISOString()
    };
  }

  private async waitForImportCompletion(taskId: string): Promise<ProductImportResult> {
    let attempts = 0;
    const maxAttempts = 30;

    while (attempts < maxAttempts) {
      const status = await this.api.getImportProductsInfo({ task_id: taskId });
      
      if (status.result[0].status === "imported") {
        return status.result[0];
      }
      
      if (status.result[0].status === "failed") {
        throw new Error(`Import failed: ${status.result[0].errors.map(e => e.message).join(", ")}`);
      }

      await new Promise(resolve => setTimeout(resolve, 2000));
      attempts++;
    }

    throw new Error("Import timeout");
  }

  private async addProductImages(result: ProductImportResult): Promise<void> {
    if (result.images && result.images.length > 0) {
      await this.api.importProductPictures({
        product_id: result.product_id,
        images: result.images
      });
    }
  }

  async optimizeCatalog(): Promise<CatalogOptimizationReport> {
    // Получение всех товаров
    const allProducts = await this.getAllProducts();
    
    // Анализ производительности
    const performanceAnalysis = await this.analyzePerformance(allProducts);
    
    // Рекомендации по оптимизации
    return {
      total_products: allProducts.length,
      performance_analysis: performanceAnalysis,
      recommendations: this.generateRecommendations(performanceAnalysis)
    };
  }

  private async getAllProducts(): Promise<ProductInfo[]> {
    const products: ProductInfo[] = [];
    let lastId = "";

    do {
      const response = await this.api.getProductsList({
        filter: { visibility: "VISIBLE" },
        limit: 1000,
        last_id: lastId || undefined
      });

      for (const product of response.items) {
        const detailedInfo = await this.api.getProductInfo({
          product_id: product.product_id
        });
        products.push(detailedInfo);
      }

      lastId = response.last_id;
    } while (lastId);

    return products;
  }
}

interface ProductFamilyData {
  family_id: string;
  products: ProductImportRequest['items'];
}

interface ProductFamily {
  family_id: string;
  products: ProductImportResult[];
  created_at: string;
}

interface ProductImportResult {
  offer_id: string;
  product_id: number;
  status: string;
  images?: Array<{ file_name: string; url: string; }>;
}

interface CatalogOptimizationReport {
  total_products: number;
  performance_analysis: PerformanceAnalysis;
  recommendations: string[];
}

interface PerformanceAnalysis {
  low_rating_products: number;
  missing_images: number;
  incomplete_attributes: number;
  archive_candidates: number;
}

AutomatedProductAnalyzer - Система аналитики товаров

class AutomatedProductAnalyzer {
  constructor(private api: ProductApi) {}

  async generateInsightsReport(filters?: ProductListRequest['filter']): Promise<ProductInsightsReport> {
    // Получение товаров для анализа
    const products = await this.getProductsForAnalysis(filters);
    
    // Параллельный сбор данных
    const [ratings, stocks, prices, relatedData] = await Promise.all([
      this.collectRatingsData(products),
      this.collectStocksData(products),
      this.collectPricesData(products),
      this.collectRelatedSkuData(products)
    ]);

    // Анализ трендов
    const trends = this.analyzeTrends(products, ratings, stocks, prices);
    
    // Генерация рекомендаций
    const recommendations = this.generateActionableRecommendations(
      products, ratings, stocks, prices, relatedData
    );

    return {
      analysis_date: new Date().toISOString(),
      products_analyzed: products.length,
      ratings_analysis: this.analyzeRatings(ratings),
      inventory_analysis: this.analyzeInventory(stocks),
      pricing_analysis: this.analyzePricing(prices),
      trends_analysis: trends,
      cross_selling_opportunities: this.findCrossSelling(relatedData),
      actionable_recommendations: recommendations
    };
  }

  private async collectRatingsData(products: ProductInfo[]): Promise<Map<string, ProductRating>> {
    const ratingsMap = new Map<string, ProductRating>();
    const chunkSize = 100;

    for (let i = 0; i < products.length; i += chunkSize) {
      const chunk = products.slice(i, i + chunkSize);
      const ratingsResponse = await this.api.getProductRating({
        products: chunk.map(p => ({ offer_id: p.offer_id }))
      });

      ratingsResponse.products.forEach(rating => {
        ratingsMap.set(rating.offer_id, rating);
      });

      // Rate limiting
      await new Promise(resolve => setTimeout(resolve, 100));
    }

    return ratingsMap;
  }

  private generateActionableRecommendations(
    products: ProductInfo[],
    ratings: Map<string, ProductRating>,
    stocks: Map<string, ProductStock>,
    prices: Map<string, ProductPrice>,
    relatedData: Map<number, number[]>
  ): ActionableRecommendation[] {
    const recommendations: ActionableRecommendation[] = [];

    products.forEach(product => {
      const rating = ratings.get(product.offer_id);
      const stock = stocks.get(product.offer_id);
      const price = prices.get(product.offer_id);

      // Низкий рейтинг
      if (rating && parseFloat(rating.rating) < 4.0) {
        recommendations.push({
          type: "quality_improvement",
          priority: "high",
          offer_id: product.offer_id,
          action: "Анализ отзывов и улучшение качества товара",
          expected_impact: "Повышение рейтинга на 0.5+ баллов"
        });
      }

      // Избыточные остатки
      if (stock && stock.present > 100 && stock.reserved < 10) {
        recommendations.push({
          type: "inventory_optimization",
          priority: "medium",
          offer_id: product.offer_id,
          action: "Проведение акции или снижение цены для ускорения оборачиваемости",
          expected_impact: "Снижение остатков на 30-50%"
        });
      }

      // Ценовая оптимизация
      if (price && rating && parseFloat(rating.rating) > 4.5 && parseFloat(price.price) < parseFloat(price.old_price || "0") * 0.8) {
        recommendations.push({
          type: "pricing_optimization",
          priority: "high",
          offer_id: product.offer_id,
          action: "Возможность повышения цены на 10-15% при высоком рейтинге",
          expected_impact: "Увеличение маржинальности на 10-15%"
        });
      }
    });

    return recommendations.sort((a, b) => {
      const priorityOrder = { "high": 3, "medium": 2, "low": 1 };
      return priorityOrder[b.priority] - priorityOrder[a.priority];
    });
  }
}

interface ProductInsightsReport {
  analysis_date: string;
  products_analyzed: number;
  ratings_analysis: RatingsAnalysis;
  inventory_analysis: InventoryAnalysis;
  pricing_analysis: PricingAnalysis;
  trends_analysis: TrendsAnalysis;
  cross_selling_opportunities: CrossSellingOpportunity[];
  actionable_recommendations: ActionableRecommendation[];
}

interface ActionableRecommendation {
  type: "quality_improvement" | "inventory_optimization" | "pricing_optimization" | "marketing_boost" | "cross_selling";
  priority: "high" | "medium" | "low";
  offer_id: string;
  action: string;
  expected_impact: string;
}

Обработка ошибок

try {
  const result = await productApi.importProducts({
    items: [productData]
  });
  
  // Отслеживание статуса импорта
  const status = await productApi.getImportProductsInfo({
    task_id: result.task_id
  });
  
  status.result.forEach(item => {
    if (item.errors.length > 0) {
      console.error(`Ошибки для ${item.offer_id}:`, item.errors);
    }
  });
} catch (error) {
  if (error.response?.status === 400) {
    console.error("Ошибка валидации данных:", error.response.data);
  } else if (error.response?.status === 429) {
    console.error("Превышен лимит запросов, повтор через 60 секунд");
    await new Promise(resolve => setTimeout(resolve, 60000));
  } else {
    console.error("Неожиданная ошибка:", error.message);
  }
}

Лучшие практики

Оптимизация производительности

// Батчинг запросов для больших объемов данных
async function batchProductOperations<T>(
  items: T[],
  operation: (batch: T[]) => Promise<any>,
  batchSize: number = 100
): Promise<any[]> {
  const results = [];
  
  for (let i = 0; i < items.length; i += batchSize) {
    const batch = items.slice(i, i + batchSize);
    const result = await operation(batch);
    results.push(result);
    
    // Rate limiting между батчами
    if (i + batchSize < items.length) {
      await new Promise(resolve => setTimeout(resolve, 200));
    }
  }
  
  return results;
}

Управление жизненным циклом товара

class ProductLifecycleManager {
  async createProduct(productData: ProductCreationData): Promise<string> {
    // 1. Импорт → 2. Изображения → 3. Атрибуты → 4. Активация
    const importResult = await this.api.importProducts({
      items: [productData.basicInfo]
    });
    
    await this.waitForImport(importResult.task_id);
    await this.addImages(productData.images);
    await this.setAttributes(productData.attributes);
    
    return productData.basicInfo.offer_id;
  }

  async retireProduct(offerId: string): Promise<void> {
    // 1. Архивирование → 2. Анализ связанных → 3. Очистка
    const productInfo = await this.api.getProductInfo({ offer_id: offerId });
    
    await this.api.archiveProducts({
      product_id: [productInfo.product_id]
    });
    
    // Анализ влияния на связанные товары
    await this.analyzeRelatedImpact(productInfo.sku);
  }
}

Интеграционные заметки

  • Rate Limiting: API поддерживает до 1000 запросов в минуту
  • Batch Processing: Рекомендуется обрабатывать товары партиями по 100 штук
  • Асинхронный импорт: Импорт товаров выполняется асинхронно, требуется отслеживание статуса
  • Изображения: Загрузка изображений выполняется отдельно после создания товара
  • Атрибуты: Критически важны для модерации и видимости товара
  • SKU связи: Система автоматически определяет связанные товары для кросс-продаж
  • Квоты: Существуют лимиты на загрузку изображений и создание товаров