{
  "openapi": "3.1.0",
  "info": {
    "title": "Бери товар — API поставщика",
    "version": "1.1.0",
    "description": "Фактический контракт существующего API и отдельной проверки подключения. Все примеры вымышлены: замените цены, даты, склад, реквизиты товара и фото данными своей системы. Доступ по Bearer-ключу одобренного поставщика; перед изменениями доступ перепроверяется. Документ не обещает OAuth, вебхуки, автоматические исходящие запросы к системе поставщика или тестовый импорт каталога."
  },
  "servers": [
    {
      "url": "/"
    }
  ],
  "security": [
    {
      "supplierBearer": []
    }
  ],
  "tags": [
    {
      "name": "Каталог и остатки"
    },
    {
      "name": "Резервирование"
    },
    {
      "name": "Проверка подключения"
    }
  ],
  "paths": {
    "/api/supplier/v1/products": {
      "post": {
        "operationId": "importSupplierProducts",
        "tags": [
          "Каталог и остатки"
        ],
        "summary": "Передать карточки товаров",
        "description": "Пакет 1..500 записей; фактически прочитанное тело до 2097152 байт, Content-Length должен совпадать. HTTP200 допускает частичный приём, HTTP422 означает отсутствие принятых строк. Для 1С передайте source:one_c_ut_11_5. Приём сохраняет предоставленные факты, включая неполную карточку: категория, штрихкоды, фотографии, габариты, вес, характеристики и ТН ВЭД не обязательны. Для этого источника конечная нулевая цена и нулевой остаток допустимы. Недостающие сведения возвращаются в result.warnings для дозаполнения в личном кабинете; это не errors и не готовность к продаже или публикации. Переданные некорректные типы, отрицательные/неконечные числа, небезопасные ссылки и чужие фотографии отклоняются. Все строки с повторяющимся стабильным ID исключаются. Все предоставленные фотографии сохраняются, без заявления об их проверке. Поставщик определяется только Bearer-ключом. Для receipt:{schemaVersion:2,batchId:UUID} передайте неизменный sourceVersion:UUID в каждой строке. Пропущенные описательные поля сохраняются только в точной существующей паре поставщик/externalId; совпадение артикула не присваивает другую карточку. Цена, валюта, количество, склад и updatedAt должны передаваться явно. Читайте receipt.items по ID/sourceVersion и сохранённым cardVersion/stockVersion; accepted или HTTP200 не доказывают применение всех компонентов. Явные пустые списки могут очистить ранее переданный список; отсутствие поля его не стирает.",
        "x-max-declared-content-length": 2097152,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 500,
                    "items": {
                      "$ref": "#/components/schemas/Product"
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "products": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 500,
                        "items": {}
                      },
                      "source": {
                        "type": "string",
                        "description": "Для расширения 1С: one_c_ut_11_5. Без этого точного значения действует прежний общий импорт."
                      },
                      "receipt": {
                        "$ref": "#/components/schemas/OneCReceiptRequest"
                      }
                    },
                    "required": [
                      "products"
                    ],
                    "allOf": [
                      {
                        "if": {
                          "allOf": [
                            {
                              "not": {
                                "required": [
                                  "receipt"
                                ]
                              }
                            },
                            {
                              "not": {
                                "properties": {
                                  "source": {
                                    "const": "one_c_ut_11_5"
                                  }
                                },
                                "required": [
                                  "source"
                                ]
                              }
                            }
                          ]
                        },
                        "then": {
                          "properties": {
                            "products": {
                              "items": {
                                "$ref": "#/components/schemas/Product"
                              }
                            }
                          }
                        }
                      },
                      {
                        "if": {
                          "allOf": [
                            {
                              "not": {
                                "required": [
                                  "receipt"
                                ]
                              }
                            },
                            {
                              "properties": {
                                "source": {
                                  "const": "one_c_ut_11_5"
                                }
                              },
                              "required": [
                                "source"
                              ]
                            }
                          ]
                        },
                        "then": {
                          "properties": {
                            "products": {
                              "items": {
                                "$ref": "#/components/schemas/OneCProduct"
                              }
                            }
                          }
                        }
                      },
                      {
                        "if": {
                          "required": [
                            "receipt"
                          ]
                        },
                        "then": {
                          "required": [
                            "source"
                          ],
                          "properties": {
                            "source": {
                              "const": "one_c_ut_11_5"
                            },
                            "products": {
                              "items": {
                                "$ref": "#/components/schemas/OneCReceiptProduct"
                              }
                            }
                          }
                        }
                      }
                    ]
                  }
                ]
              },
              "examples": {
                "general": {
                  "summary": "Общий API импорт",
                  "value": {
                    "products": [
                      {
                        "externalId": "product-1001",
                        "sku": "SUPPLIER-1001",
                        "name": "Керамическая кружка, 350 мл",
                        "category": "Посуда / Кружки",
                        "barcodes": [
                          "4601234567893"
                        ],
                        "price": 249.9,
                        "currency": "RUB",
                        "availableQuantity": 24,
                        "warehouseId": "warehouse-1",
                        "images": [
                          "https://example.com/products/mug-1001.jpg"
                        ],
                        "updatedAt": "2026-09-18T10:00:00.000Z",
                        "status": "active",
                        "description": "Керамическая кружка в индивидуальной упаковке.",
                        "brand": "Пример бренда",
                        "country": "Россия",
                        "packageLengthCm": 12,
                        "packageWidthCm": 10,
                        "packageHeightCm": 11,
                        "weightKg": 0.42,
                        "packageCount": 1,
                        "minimumOrderQuantity": 1,
                        "orderQuantityStep": 1,
                        "characteristics": {
                          "Материал": "Керамика",
                          "Объём, мл": 350
                        }
                      }
                    ]
                  }
                },
                "oneC": {
                  "summary": "Полный пакет расширения 1С УТ 11.5",
                  "value": {
                    "source": "one_c_ut_11_5",
                    "products": [
                      {
                        "externalId": "product-1001",
                        "sku": "SUPPLIER-1001",
                        "name": "Керамическая кружка, 350 мл",
                        "category": "Посуда / Кружки",
                        "barcodes": [
                          "4601234567893"
                        ],
                        "price": 249.9,
                        "currency": "RUB",
                        "availableQuantity": 24,
                        "warehouseId": "warehouse-1",
                        "images": [
                          "https://example.com/products/mug-1001.jpg"
                        ],
                        "updatedAt": "2026-09-18T10:00:00.000Z",
                        "status": "active",
                        "description": "Керамическая кружка в индивидуальной упаковке.",
                        "brand": "Пример бренда",
                        "country": "Россия",
                        "packageLengthCm": 12,
                        "packageWidthCm": 10,
                        "packageHeightCm": 11,
                        "packageCount": 1,
                        "minimumOrderQuantity": 1,
                        "orderQuantityStep": 1,
                        "characteristics": {
                          "Материал": "Керамика",
                          "Объём, мл": 350
                        },
                        "packageWeightKg": 0.42
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Полностью или частично принят; проверяйте result.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportReply"
                },
                "examples": {
                  "accepted": {
                    "value": {
                      "ok": true,
                      "result": {
                        "id": "10000000-0000-4000-8000-000000000001",
                        "supplierId": "example-supplier",
                        "source": "api_products",
                        "receivedAt": "2026-09-18T10:00:01.000Z",
                        "accepted": 1,
                        "rejected": 0,
                        "issues": []
                      }
                    }
                  },
                  "partial": {
                    "summary": "Одна из двух строк принята. Статус HTTP200.",
                    "value": {
                      "ok": true,
                      "result": {
                        "id": "10000000-0000-4000-8000-000000000002",
                        "supplierId": "example-supplier",
                        "source": "api_products",
                        "receivedAt": "2026-09-18T10:00:01.000Z",
                        "accepted": 1,
                        "rejected": 1,
                        "issues": [
                          {
                            "row": 3,
                            "field": "price",
                            "message": "Цена должна быть больше нуля"
                          }
                        ]
                      }
                    }
                  },
                  "oneCPartial": {
                    "summary": "Частичный приём 1С с номером исходной записи",
                    "value": {
                      "ok": true,
                      "result": {
                        "id": "10000000-0000-4000-8000-000000000004",
                        "supplierId": "example-supplier",
                        "source": "one_c_ut_11_5",
                        "receivedAt": "2026-09-18T10:00:01.000Z",
                        "accepted": 1,
                        "rejected": 1,
                        "issues": [
                          {
                            "row": 2,
                            "field": "characteristics",
                            "message": "Некорректный формат переданного поля characteristics."
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON/обёртка/число записей.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Нет действующего Bearer-ключа одобренного поставщика; ключ также перепроверяется перед записью.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Каталог на паузе либо изменён/очищен во время обработки.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Заявленный Content-Length превышает лимит.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ни одна строка не принята.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportReply"
                }
              }
            }
          }
        },
        "x-max-body-bytes": 2097152
      }
    },
    "/api/supplier/v1/stocks": {
      "post": {
        "operationId": "updateSupplierStocks",
        "tags": [
          "Каталог и остатки"
        ],
        "summary": "Обновить остатки по складам",
        "description": "Пакет 0..1000 записей. Ограничение фактически прочитанного тела 1048576 байт; Content-Length, если передан, проверяется отдельно и не заменяет подсчёт байтов потока. Корректные строки могут сохраниться при ошибках остальных: читайте accepted/rejected/issues. HTTP200 используется и для частичного приёма; HTTP207 не возвращается. HTTP422 означает отсутствие принятых записей, кроме корректного пустого массива (200). Ранее сохранённые товары и отсутствующие в пакете склады не удаляются.",
        "x-max-declared-content-length": 1048576,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "array",
                    "minItems": 0,
                    "maxItems": 1000,
                    "items": {
                      "$ref": "#/components/schemas/Stock"
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "stocks": {
                        "type": "array",
                        "minItems": 0,
                        "maxItems": 1000,
                        "items": {
                          "$ref": "#/components/schemas/Stock"
                        }
                      }
                    },
                    "required": [
                      "stocks"
                    ]
                  }
                ]
              },
              "example": {
                "stocks": [
                  {
                    "externalId": "product-1001",
                    "warehouseId": "warehouse-1",
                    "availableQuantity": 0,
                    "updatedAt": "2026-09-18T10:05:00.000Z"
                  },
                  {
                    "externalId": "product-1001",
                    "warehouseId": "warehouse-2",
                    "availableQuantity": 7,
                    "updatedAt": "2026-09-18T10:04:00.000Z"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Полностью или частично принят; проверяйте result.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportReply"
                },
                "example": {
                  "ok": true,
                  "result": {
                    "id": "10000000-0000-4000-8000-000000000003",
                    "supplierId": "example-supplier",
                    "source": "api_stocks",
                    "receivedAt": "2026-09-18T10:05:01.000Z",
                    "accepted": 2,
                    "rejected": 0,
                    "issues": []
                  }
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON/обёртка/число записей.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Нет действующего Bearer-ключа одобренного поставщика; ключ также перепроверяется перед записью.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Каталог на паузе либо изменён/очищен во время обработки.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Заявленный Content-Length превышает лимит.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Ни одна строка не принята.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportReply"
                }
              }
            }
          }
        }
      }
    },
    "/api/supplier/v1/health": {
      "get": {
        "operationId": "getSupplierDataHealth",
        "tags": [
          "Каталог и остатки"
        ],
        "summary": "Прочитать состояние данных поставщика",
        "description": "Свежесть проверяется по updatedAt и receivedAt каждого склада. Для наблюдений 1С срок актуальности по умолчанию 600 секунд, настройка ограничена 60–1800 секундами; он доступен в limits.oneCStockMaxAgeSeconds. Ошибка конфигурации даёт 0 и отказ свежести. Для остальных каналов сохраняется 30 минут. Неизвестный или устаревший склад блокирует доступность, количество сохраняется как история и не подменяется нулём. Карточка, дубликат или отказ не обновляют часы остатка.",
        "responses": {
          "200": {
            "description": "Состояние сохранённых данных.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthReply"
                },
                "example": {
                  "ok": true,
                  "status": {
                    "health": "healthy",
                    "lastCatalogSyncAt": "2026-09-18T10:00:01.000Z",
                    "lastStockSyncAt": "2026-09-18T10:05:01.000Z",
                    "lastErrorAt": null,
                    "lastError": null,
                    "products": 1,
                    "activeProducts": 1,
                    "totalStock": 7,
                    "apiKey": {
                      "mask": "bt_supplier_…example",
                      "createdAt": "2026-09-18T09:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "API-ключ недействителен либо поставщик не одобрен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/supplier/v1/reservations": {
      "get": {
        "operationId": "listSupplierReservations",
        "tags": [
          "Резервирование"
        ],
        "summary": "Получить заявки текущего поставщика",
        "description": "Сначала фильтрация по поставщику и status, затем сортировка createdAt по убыванию и limit. История завершённых заявок не вытесняет pending при фильтре. Максимум 200, курсора/постраничного продолжения нет. При чтении истёкшие pending становятся expired. Используйте deadlineAt: обычная заявка рассчитана на ответ в течение 2 минут. status фильтрует состояние резерва, не состояние отгрузки. Для дальнейшей обработки получайте status=confirmed с той же парой schemaVersion=2 и warehouseId и учитывайте отдельные shipmentStatus/readyAt/shippedAt/externalShipmentId/shipmentMessage. Получение заявки, ready и shipped не подтверждают резерв и не означают приёмку на складе. Только запись ответа schemaVersion=2 для указанного warehouseId содержит fulfillmentDestination:{id,name,address}|null и fulfillmentDestinationIssue:null|not_assigned|ambiguous|destination_incomplete|snapshot_missing. В формате конкретного склада поля присутствуют с фильтром pending, с другими статусами и без фильтра. Прежний ответ без schemaVersion/warehouseId содержит только поля резерва, без назначения и shipment-полей. Это сохранённый адрес склада фулфилмента для передачи поставщиком. Снимок формируется при создании заявки и сохраняется через confirmed/ready/shipped и архив; настройки склада после создания его не заменяют. Старые снимки без адреса дают snapshot_missing, без подстановки нынешних данных. Без schemaVersion и warehouseId возвращаются только прежние заявки без физического источника. Для точного склада обязательны вместе schemaVersion=2 и warehouseId. Сначала фильтруются поставщик, физический источник и status, затем limit. Неизвестный/другой источник не подменяется общим остатком. Некорректная или неполная пара параметров возвращает 400.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "pending, confirmed, rejected или expired; отсутствие/пустая строка означает все. Неизвестное значение возвращает пустой список."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 100
            },
            "description": "Результат ограничивается диапазоном 1..200. Нецелое/некорректное значение заменяется 100."
          },
          {
            "name": "schemaVersion",
            "in": "query",
            "schema": {
              "type": "string",
              "const": "2"
            },
            "description": "Передаётся только вместе с warehouseId для source-aware обмена."
          },
          {
            "name": "warehouseId",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100,
              "pattern": "^(?!\\s)(?!.*\\s$)[^\\x00-\\x1f\\x7f]+$",
              "description": "Точный ID физического склада, который передаётся с остатком. Название города не заменяет ID."
            },
            "description": "Передаётся только вместе с schemaVersion=2."
          }
        ],
        "responses": {
          "200": {
            "description": "Список только этого поставщика.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ReservationsReply"
                    },
                    {
                      "$ref": "#/components/schemas/WarehouseReservationsReply"
                    }
                  ]
                },
                "examples": {
                  "pending": {
                    "summary": "Ожидающая заявка с сохранённым адресом передачи",
                    "value": {
                      "ok": true,
                      "reservations": [
                        {
                          "id": "20000000-0000-4000-8000-000000000001",
                          "marketplace": "ozon",
                          "marketplaceOrderId": 123456,
                          "externalProductId": "product-1001",
                          "sku": "SUPPLIER-1001",
                          "quantity": 2,
                          "purchasePriceKopecks": 24990,
                          "status": "pending",
                          "externalReservationId": null,
                          "supplierMessage": null,
                          "deadlineAt": "2026-09-18T10:12:00.000Z",
                          "createdAt": "2026-09-18T10:10:00.000Z",
                          "updatedAt": "2026-09-18T10:10:00.000Z"
                        }
                      ]
                    }
                  },
                  "notAssigned": {
                    "summary": "Нет назначенного адреса",
                    "value": {
                      "ok": true,
                      "schemaVersion": 2,
                      "warehouseId": "warehouse-1001",
                      "reservations": [
                        {
                          "id": "20000000-0000-4000-8000-000000000001",
                          "marketplace": "ozon",
                          "marketplaceOrderId": 123456,
                          "externalProductId": "product-1001",
                          "sku": "SUPPLIER-1001",
                          "quantity": 2,
                          "purchasePriceKopecks": 24990,
                          "status": "pending",
                          "externalReservationId": null,
                          "supplierMessage": null,
                          "deadlineAt": "2026-09-18T10:12:00.000Z",
                          "createdAt": "2026-09-18T10:10:00.000Z",
                          "updatedAt": "2026-09-18T10:10:00.000Z",
                          "marketplaceOrderItemId": null,
                          "supplierWarehouseId": "warehouse-1001",
                          "shipmentStatus": null,
                          "readyAt": null,
                          "shippedAt": null,
                          "externalShipmentId": null,
                          "shipmentMessage": null,
                          "fulfillmentDestination": null,
                          "fulfillmentDestinationIssue": "not_assigned"
                        }
                      ]
                    }
                  },
                  "legacy": {
                    "summary": "Старая заявка без сохранённого адреса",
                    "value": {
                      "ok": true,
                      "schemaVersion": 2,
                      "warehouseId": "warehouse-1001",
                      "reservations": [
                        {
                          "id": "20000000-0000-4000-8000-000000000001",
                          "marketplace": "ozon",
                          "marketplaceOrderId": 123456,
                          "externalProductId": "product-1001",
                          "sku": "SUPPLIER-1001",
                          "quantity": 2,
                          "purchasePriceKopecks": 24990,
                          "status": "pending",
                          "externalReservationId": null,
                          "supplierMessage": null,
                          "deadlineAt": "2026-09-18T10:12:00.000Z",
                          "createdAt": "2026-09-18T10:10:00.000Z",
                          "updatedAt": "2026-09-18T10:10:00.000Z",
                          "marketplaceOrderItemId": null,
                          "supplierWarehouseId": "warehouse-1001",
                          "shipmentStatus": null,
                          "readyAt": null,
                          "shippedAt": null,
                          "externalShipmentId": null,
                          "shipmentMessage": null,
                          "fulfillmentDestination": null,
                          "fulfillmentDestinationIssue": "snapshot_missing"
                        }
                      ]
                    }
                  },
                  "warehouse": {
                    "summary": "Заявки одного физического склада",
                    "value": {
                      "ok": true,
                      "schemaVersion": 2,
                      "warehouseId": "warehouse-1001",
                      "reservations": [
                        {
                          "id": "20000000-0000-4000-8000-000000000001",
                          "marketplace": "ozon",
                          "marketplaceOrderId": 123456,
                          "externalProductId": "product-1001",
                          "sku": "SUPPLIER-1001",
                          "quantity": 2,
                          "purchasePriceKopecks": 24990,
                          "status": "pending",
                          "externalReservationId": null,
                          "supplierMessage": null,
                          "deadlineAt": "2026-09-18T10:12:00.000Z",
                          "createdAt": "2026-09-18T10:10:00.000Z",
                          "updatedAt": "2026-09-18T10:10:00.000Z",
                          "marketplaceOrderItemId": null,
                          "supplierWarehouseId": "warehouse-1001",
                          "shipmentStatus": null,
                          "readyAt": null,
                          "shippedAt": null,
                          "externalShipmentId": null,
                          "shipmentMessage": null,
                          "fulfillmentDestination": {
                            "id": "40000000-0000-4000-8000-000000000001",
                            "name": "Пример фулфилмента",
                            "address": "Тестовый город, Складская улица, дом 1"
                          },
                          "fulfillmentDestinationIssue": null
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "API-ключ недействителен либо поставщик не одобрен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "answerSupplierReservation",
        "tags": [
          "Резервирование"
        ],
        "summary": "Подтвердить резерв или сообщить отдельный этап поставки",
        "description": "Не создаёт новую заявку. Ответ должен относиться к reservationId текущего поставщика. confirmed требует номера реального резерва в системе поставщика. Повтор того же конечного статуса возвращает уже сохранённую запись и не меняет номер/сообщение. Другой статус или expired дают 409. Отдельный объект shipmentStatus:ready сообщает готовность только после сохранённого confirmed с номером резерва. Затем shipmentStatus:shipped требует externalShipmentId и сохранённого назначения фулфилмента; напрямую отправлять shipped нельзя. В одном запросе нельзя смешивать status и shipmentStatus либо номера резерва и отгрузки. Для этапов поставки повтор того же этапа с тем же номером и сообщением безопасен; изменённый повтор или обратный переход дают 409. Готовность/отгрузка не являются успешным резервированием или приёмкой склада. Поля fulfillmentDestination и fulfillmentDestinationIssue возвращаются только для source-aware запроса с schemaVersion:2 и warehouseId; этот формат обязателен для готовности и отгрузки. В прежнем ответе без склада этих полей нет. Для новой shipped необходимо полное сохранённое назначение с названием и адресом и fulfillmentDestinationIssue:null. Ранее сохранённая shipped при точном повторе прежнего номера и сообщения возвращает HTTP200 и старое состояние даже у legacy записи без полного адреса; это не создание новой отгрузки. Для заявки физического склада в каждом действии обязательны schemaVersion:2 и warehouseId того же источника. Старый PATCH и другой warehouseId не подтверждают и не отгружают такую заявку. Source-aware PATCH не усыновляет старую заявку без источника.",
        "x-max-declared-content-length": 20000,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/ReservationDecision"
                  },
                  {
                    "$ref": "#/components/schemas/WarehouseReservationDecision"
                  },
                  {
                    "$ref": "#/components/schemas/WarehouseReservationShipment"
                  }
                ]
              },
              "examples": {
                "confirm": {
                  "summary": "Подтвердить реальный резерв",
                  "value": {
                    "reservationId": "20000000-0000-4000-8000-000000000001",
                    "status": "confirmed",
                    "externalReservationId": "RESERVE-5001",
                    "message": "Товар зарезервирован"
                  }
                },
                "ready": {
                  "summary": "После confirmed: готовность к передаче",
                  "value": {
                    "schemaVersion": 2,
                    "warehouseId": "warehouse-1001",
                    "reservationId": "20000000-0000-4000-8000-000000000001",
                    "shipmentStatus": "ready",
                    "message": "Товар готов к передаче"
                  }
                },
                "shipped": {
                  "summary": "После ready: фактическая отгрузка",
                  "value": {
                    "schemaVersion": 2,
                    "warehouseId": "warehouse-1001",
                    "reservationId": "20000000-0000-4000-8000-000000000001",
                    "shipmentStatus": "shipped",
                    "externalShipmentId": "SHIPMENT-7001",
                    "message": "Отгружено на назначенный фулфилмент"
                  }
                },
                "warehouseConfirm": {
                  "summary": "Подтверждение конкретного физического склада",
                  "value": {
                    "reservationId": "20000000-0000-4000-8000-000000000001",
                    "status": "confirmed",
                    "externalReservationId": "RESERVE-5001",
                    "message": "Товар зарезервирован",
                    "schemaVersion": 2,
                    "warehouseId": "warehouse-1001"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Сохранённая заявка.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ReservationReply"
                    },
                    {
                      "$ref": "#/components/schemas/WarehouseReservationReply"
                    }
                  ]
                },
                "examples": {
                  "confirm": {
                    "summary": "Резерв подтверждён",
                    "value": {
                      "ok": true,
                      "reservation": {
                        "id": "20000000-0000-4000-8000-000000000001",
                        "marketplace": "ozon",
                        "marketplaceOrderId": 123456,
                        "externalProductId": "product-1001",
                        "sku": "SUPPLIER-1001",
                        "quantity": 2,
                        "purchasePriceKopecks": 24990,
                        "status": "confirmed",
                        "externalReservationId": "RESERVE-5001",
                        "supplierMessage": "Товар зарезервирован",
                        "deadlineAt": "2026-09-18T10:12:00.000Z",
                        "createdAt": "2026-09-18T10:10:00.000Z",
                        "updatedAt": "2026-09-18T10:10:30.000Z"
                      }
                    }
                  },
                  "ready": {
                    "summary": "Готовность сохранена отдельно от резерва",
                    "value": {
                      "ok": true,
                      "schemaVersion": 2,
                      "warehouseId": "warehouse-1001",
                      "reservation": {
                        "id": "20000000-0000-4000-8000-000000000001",
                        "marketplace": "ozon",
                        "marketplaceOrderId": 123456,
                        "externalProductId": "product-1001",
                        "sku": "SUPPLIER-1001",
                        "quantity": 2,
                        "purchasePriceKopecks": 24990,
                        "status": "confirmed",
                        "externalReservationId": "RESERVE-5001",
                        "supplierMessage": "Товар зарезервирован",
                        "deadlineAt": "2026-09-18T10:12:00.000Z",
                        "createdAt": "2026-09-18T10:10:00.000Z",
                        "updatedAt": "2026-09-18T10:11:00.000Z",
                        "marketplaceOrderItemId": null,
                        "supplierWarehouseId": "warehouse-1001",
                        "shipmentStatus": "ready",
                        "readyAt": "2026-09-18T10:11:00.000Z",
                        "shippedAt": null,
                        "externalShipmentId": null,
                        "shipmentMessage": "Товар готов к передаче",
                        "fulfillmentDestination": {
                          "id": "40000000-0000-4000-8000-000000000001",
                          "name": "Пример фулфилмента",
                          "address": "Тестовый город, Складская улица, дом 1"
                        },
                        "fulfillmentDestinationIssue": null
                      }
                    }
                  },
                  "shipped": {
                    "summary": "Отгрузка сохранена отдельно от складской приёмки",
                    "value": {
                      "ok": true,
                      "schemaVersion": 2,
                      "warehouseId": "warehouse-1001",
                      "reservation": {
                        "id": "20000000-0000-4000-8000-000000000001",
                        "marketplace": "ozon",
                        "marketplaceOrderId": 123456,
                        "externalProductId": "product-1001",
                        "sku": "SUPPLIER-1001",
                        "quantity": 2,
                        "purchasePriceKopecks": 24990,
                        "status": "confirmed",
                        "externalReservationId": "RESERVE-5001",
                        "supplierMessage": "Товар зарезервирован",
                        "deadlineAt": "2026-09-18T10:12:00.000Z",
                        "createdAt": "2026-09-18T10:10:00.000Z",
                        "updatedAt": "2026-09-18T10:11:30.000Z",
                        "marketplaceOrderItemId": null,
                        "supplierWarehouseId": "warehouse-1001",
                        "shipmentStatus": "shipped",
                        "readyAt": "2026-09-18T10:11:00.000Z",
                        "shippedAt": "2026-09-18T10:11:30.000Z",
                        "externalShipmentId": "SHIPMENT-7001",
                        "shipmentMessage": "Отгружено на назначенный фулфилмент",
                        "fulfillmentDestination": {
                          "id": "40000000-0000-4000-8000-000000000001",
                          "name": "Пример фулфилмента",
                          "address": "Тестовый город, Складская улица, дом 1"
                        },
                        "fulfillmentDestinationIssue": null
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Некорректный JSON/ответ; заявка не найдена; отсутствует обязательный номер.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Ключ недействителен/отозван или поставщик не одобрен.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Резерв уже завершён с другим статусом, включая expired. Для поставки: резерв не confirmed, неверная последовательность, изменённый повтор, обратный переход или отсутствие сохранённого назначения фулфилмента. Новая shipped также блокируется при destination_incomplete или snapshot_missing; поставщик не подменяет адрес в теле запроса.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Заявленный Content-Length больше 20000 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Ответ не удалось сохранить. Сверьте состояние GET перед повтором.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/supplier/v1/connection-test": {
      "get": {
        "operationId": "receiveSupplierConnectionTest",
        "tags": [
          "Проверка подключения"
        ],
        "summary": "Получить начатую в кабинете проверку",
        "description": "Поставщик предварительно начинает проверку в кабинете. GET отдаёт challenge на 10 минут от старта; при первом получении записывает только отметку и токен в отдельную коллекцию проверок. Повторный GET возвращает тот же токен. test:null — нет ожидающей проверки, она завершена, истекла или сменился API-ключ. Товары, остатки, заявки и деньги не меняются; реальный обмен не включается.",
        "responses": {
          "200": {
            "description": "Challenge или null.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectionTestReply"
                },
                "example": {
                  "ok": true,
                  "test": {
                    "id": "30000000-0000-4000-8000-000000000001",
                    "kind": "connection_test",
                    "expiresAt": "2026-09-18T10:20:00.000Z",
                    "replyToken": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Недействительный ключ/нет одобрения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Состояние проверки не допускает запрос.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Не удалось прочитать или записать состояние проверки.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "acknowledgeSupplierConnectionTest",
        "tags": [
          "Проверка подключения"
        ],
        "summary": "Вернуть полученный тестовый ответ",
        "description": "Верните test.id и точный replyToken из GET с result:received до expiresAt. Ответ относится только к проверке текущего поставщика и текущего API-ключа. Повтор уже принятого ответа с тем же токеном и ключом идемпотентен, в том числе послеTTL. Новая проверка/смена ключа отменяет прежний challenge. Реальный резерв и рабочий обмен этим не создаются.",
        "x-max-declared-content-length": 4000,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConnectionAcknowledgement"
              },
              "example": {
                "testId": "30000000-0000-4000-8000-000000000001",
                "replyToken": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                "result": "received"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Проверка выполнена.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectionPassed"
                },
                "example": {
                  "ok": true,
                  "status": "passed"
                }
              }
            }
          },
          "400": {
            "description": "Передайте testId/replyToken строками и result:received.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Недействительный/отозванный API-ключ или нет одобрения.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Нет текущей полученной проверки, неверен ID/токен, первый ответ просрочен либо ключ/проверка заменены.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Заявленный Content-Length больше 4000 байт.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Не удалось сохранить результат проверки.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/supplier/v1/tnved-status": {
      "get": {
        "operationId": "getSupplierTnvedStatus",
        "summary": "Результаты проверки ТН ВЭД по товарам поставщика",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,15}$"
            },
            "description": "Значение nextCursor предыдущего ответа; для первой страницы не передавайте."
          }
        ],
        "responses": {
          "200": {
            "description": "До 50 сохранённых проверок только этого поставщика. Пустой список не означает, что ТН ВЭД не требуется.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "items": {
                      "type": "array",
                      "maxItems": 50,
                      "items": {
                        "type": "object",
                        "properties": {
                          "productId": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "marketplace": {
                            "type": "string",
                            "enum": [
                              "wb",
                              "ozon",
                              "yandex"
                            ]
                          },
                          "checkedAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "state": {
                            "type": "string",
                            "enum": [
                              "missing",
                              "invalid",
                              "unchecked",
                              "ok",
                              "not_required"
                            ]
                          },
                          "required": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "productId",
                          "name",
                          "marketplace",
                          "checkedAt",
                          "state",
                          "required",
                          "message"
                        ]
                      }
                    }
                  },
                  "required": [
                    "ok",
                    "items",
                    "nextCursor"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Некорректный cursor"
          },
          "401": {
            "description": "Недействительный ключ или поставщик не одобрен"
          },
          "503": {
            "description": "Результаты временно недоступны"
          }
        }
      }
    },
    "/api/supplier/v1/photos": {
      "post": {
        "operationId": "uploadNativeSupplierPhoto",
        "tags": [
          "Каталог и остатки"
        ],
        "summary": "Передать изображение обычного товара 1С",
        "description": "Новый канал выключен по умолчанию; подключается отдельно после нативной проверки. Ключ одобренного поставщика проверяется до чтения и перед сохранением. Фактические байты и исходный SHA256 проверяются, JPEG/PNG/WebP декодируется и переупаковывается без исходных метаданных. Точная пара поставщик/товар и исходный файл/версия неизменны; другой хеш той же версии отклоняется. В ответе identity подтверждает поставщика текущего ключа, а asset содержит исходные ID/дату/хеш и реальный адрес из серверного APP_ORIGIN, не из Host. До ссылки в принятой карточке staged-фото не выдаётся публично. Настроены квоты и ограничение одновременных загрузок; квитанция фото не подтверждает карточку, резерв или публикацию.",
        "x-max-body-bytes": 5242880,
        "parameters": [
          {
            "in": "header",
            "name": "x-product-id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
            }
          },
          {
            "in": "header",
            "name": "x-native-file-id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
            }
          },
          {
            "in": "header",
            "name": "x-source-updated-at",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(?:\\.\\d{3})?Z$"
            },
            "description": "Фактическая универсальная дата модификации исходного файла, не время повторной отправки."
          },
          {
            "in": "header",
            "name": "x-source-sha256",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{64}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "image/jpeg": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/png": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/webp": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Точный повтор: возвращён прежний сохранённый ресурс",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SupplierPhotoReply"
                }
              }
            }
          },
          "201": {
            "description": "Очищенное изображение сохранено",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SupplierPhotoReply"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные поля, тело или изображение",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorReply"
                }
              }
            }
          },
          "401": {
            "description": "Ключ недействителен, отозван или поставщик не одобрен",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorReply"
                }
              }
            }
          },
          "409": {
            "description": "Версия исходного фото конфликтует либо каталог изменён/на паузе",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorReply"
                }
              }
            }
          },
          "413": {
            "description": "Фактический размер либо квота превышены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorReply"
                }
              }
            }
          },
          "415": {
            "description": "Формат фотографии не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorReply"
                }
              }
            }
          },
          "422": {
            "description": "Исходный SHA256 не совпадает",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorReply"
                }
              }
            }
          },
          "429": {
            "description": "Все ограниченные места загрузки заняты",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorReply"
                }
              }
            }
          },
          "503": {
            "description": "Фотообмен пока не включён либо защищённый адрес не настроен",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorReply"
                }
              }
            }
          }
        }
      }
    },
    "/api/supplier/v1/photos/asset": {
      "get": {
        "operationId": "getReferencedSupplierProductPhoto",
        "tags": [
          "Каталог и остатки"
        ],
        "security": [],
        "summary": "Получить очищенное фото принятой карточки",
        "description": "Выдаёт только фактически сохранённое и проверенное изображение, на которое ссылается принятая карточка того же поставщика и товара. API-ключ не содержится в URL. Staged-фото, документы, поддержка и произвольные локальные файлы недоступны. При каждом запросе проверяются ссылка карточки, размер и хеш файла; публичного кеша нет.",
        "parameters": [
          {
            "in": "query",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Проверенные очищенные байты",
            "content": {
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "404": {
            "description": "Нет принятой карточки с этой фотографией либо ID некорректен"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "supplierBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "API-ключ создаётся в кабинете одобренного поставщика. Заголовок Authorization: Bearer <API_KEY>; ключ не помещают в URL."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "ok": {
            "const": false
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "ok",
          "message"
        ]
      },
      "Product": {
        "type": "object",
        "properties": {
          "externalId": {
            "type": "string",
            "maxLength": 100,
            "description": "Стабильный ID товара в системе поставщика; одинаковый для разных складов.",
            "minLength": 1
          },
          "sku": {
            "type": "string",
            "maxLength": 100,
            "description": "Артикул поставщика.",
            "minLength": 1
          },
          "name": {
            "type": "string",
            "maxLength": 300,
            "description": "Название.",
            "minLength": 1
          },
          "category": {
            "type": "string",
            "maxLength": 200,
            "description": "Категория поставщика. Не обязательна для приёма строки, но нужна для дальнейшей подготовки карточки."
          },
          "barcodes": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[0-9]{8,14}$"
            },
            "description": "Не обязательны для приёма строки; нужны для готовой карточки. Нормализатор сохраняет все переданные непустые значения."
          },
          "price": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 100000000,
            "description": "Закупочная цена одной товарной единицы в рублях, не в копейках."
          },
          "currency": {
            "type": "string",
            "const": "RUB"
          },
          "availableQuantity": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000000,
            "description": "Точное количество товарных единиц. Ноль допустим и передаётся явно."
          },
          "warehouseId": {
            "type": "string",
            "maxLength": 100,
            "description": "Стабильный ID склада поставщика.",
            "minLength": 1
          },
          "images": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^https://"
            },
            "description": "Прямые HTTPS-ссылки. Пустой массив допустим для приёма, но не означает готовность карточки. Доступность фотографий проверяется отдельно."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "maxLength": 64,
            "description": "Время изменения в источнике. Используйте ISO8601 с часовым поясом; не более 5 минут в будущем. При повторной передаче неизменённых данных сохраните исходное время; для нового остатка передайте новое время фактической проверки."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive"
            ]
          },
          "description": {
            "type": "string",
            "maxLength": 20000,
            "description": "Необязательное описание; лишние символы обрезаются."
          },
          "brand": {
            "type": "string",
            "maxLength": 300,
            "description": "Необязательный бренд."
          },
          "country": {
            "type": "string",
            "maxLength": 300,
            "description": "Необязательная страна."
          },
          "packageLengthCm": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Длина упаковки в сантиметрах."
          },
          "packageWidthCm": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Ширина упаковки в сантиметрах."
          },
          "packageHeightCm": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Высота упаковки в сантиметрах."
          },
          "weightKg": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Вес в килограммах."
          },
          "packageCount": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000,
            "description": "Число упаковок товарной единицы."
          },
          "minimumOrderQuantity": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Фактический минимальный заказ; не число предметов внутри заводского набора. Для доступности селлеру существующие правила требуют 1."
          },
          "orderQuantityStep": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Фактический шаг заказа. Для доступности селлеру существующие правила требуют 1."
          },
          "characteristics": {
            "type": "object",
            "additionalProperties": true,
            "description": "Необязательные характеристики. Ключи до 200 символов; нормализатор ограничивает размеры и игнорирует неподдерживаемые значения."
          },
          "tnved": {
            "type": "string",
            "pattern": "^(?:[0-9]{10}|[0-9]{14})$",
            "description": "Код ТН ВЭД поставщика. Передавайте вместе с товаром, если известен. Сохраните ведущие нули. Обязательность и допустимость проверяются после подтверждения категории для конкретной площадки; отсутствие кода не запрещает приём строки."
          }
        },
        "required": [
          "externalId",
          "sku",
          "name",
          "price",
          "currency",
          "availableQuantity",
          "warehouseId",
          "updatedAt",
          "status"
        ],
        "description": "Канонический JSON-формат. Числовые поля также принимают числовые строки (запятая как разделитель дроби); строки обрезают пробелы. Дополнительные данные упаковки, характеристик, категории, штрихкодов и фото нужны для дальнейшей готовности товара, хотя API принимает строку без них. Принятие строки не равно публикации или продаже. Неполные данные не дополняются выдуманными значениями. Нормализатор также принимает алиасы: external_id/id→externalId; article/vendorCode→sku; title→name; categoryName→category; barcode→barcodes; purchasePrice→price; quantity/stock→availableQuantity; warehouse_id/warehouse→warehouseId; imageUrls/image→images; updated_at→updatedAt. Списки barcodes/images также принимают строку с разделителями ; , |. Каноническая схема ниже показывает рекомендуемый формат; избыток необязательных списков/текста нормализуется, а не гарантированно отклоняется. Дополнительные поля и вложенные сведения поставщика сохраняются внутри карточки товара. Они не обязательны. Пропущенные дополнительные поля сохраняют прежние значения, переданные объект/список/null заменяют поле целиком. Реквизиты и файлы документов передаются с товаром; ключ доступа передаётся только в заголовке.",
        "additionalProperties": true
      },
      "Stock": {
        "type": "object",
        "properties": {
          "externalId": {
            "type": "string",
            "maxLength": 100,
            "description": "ID уже переданной карточки товара.",
            "minLength": 1
          },
          "warehouseId": {
            "type": "string",
            "maxLength": 100,
            "description": "ID склада поставщика.",
            "minLength": 1
          },
          "availableQuantity": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000000,
            "description": "Точное количество товарных единиц. Ноль допустим и передаётся явно."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "maxLength": 64,
            "description": "Время изменения в источнике. Используйте ISO8601 с часовым поясом; не более 5 минут в будущем. При повторной передаче неизменённых данных сохраните исходное время; для нового остатка передайте новое время фактической проверки."
          }
        },
        "required": [
          "externalId",
          "warehouseId",
          "availableQuantity",
          "updatedAt"
        ],
        "description": "Канонический JSON-формат; нормализатор также поддерживает алиасы external_id/id, warehouse_id/warehouse, quantity/stock, updated_at и целочисленные числовые строки. Версия учитывается отдельно для пары externalId+warehouseId; повтор одинаковых данных с той же датой допустим. Другое количество с той же датой и более старые данные отклоняются. Нулевой остаток не пропускается. Отсутствующие в пакете склады не обнуляются. Пустой пакет не подтверждает свежесть количеств по складам."
      },
      "ImportIssue": {
        "type": "object",
        "properties": {
          "row": {
            "type": "integer",
            "minimum": 1,
            "description": "Номер исходной строки без перенумерации после отсева. Для source:one_c_ut_11_5 первая запись имеет номер 1; для общего API — 2, как строка после заголовка файла."
          },
          "field": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "row",
          "field",
          "message"
        ]
      },
      "ImportResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "supplierId": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "api_products",
              "api_stocks",
              "one_c_ut_11_5"
            ]
          },
          "receivedAt": {
            "type": "string",
            "format": "date-time"
          },
          "accepted": {
            "type": "integer",
            "minimum": 0
          },
          "rejected": {
            "type": "integer",
            "minimum": 0
          },
          "issues": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImportIssue"
            },
            "description": "Для общего API первые 100 замечаний; для ограниченного пакета 1С сохраняются все замечания с исходными номерами строк. Замечания могут относиться и к частично обновлённой принятой строке."
          },
          "warnings": {
            "type": "array",
            "maxItems": 4000,
            "items": {
              "$ref": "#/components/schemas/ImportIssue"
            },
            "description": "Подсказки о дозаполнении карточек 1С; отдельно от ошибок. Сохраняются с исходными номерами строк. Не меняют applied/disposition и не подтверждают публикацию."
          }
        },
        "required": [
          "id",
          "supplierId",
          "source",
          "receivedAt",
          "accepted",
          "rejected",
          "issues"
        ],
        "allOf": [
          {
            "if": {
              "properties": {
                "source": {
                  "enum": [
                    "api_products",
                    "api_stocks"
                  ]
                }
              },
              "required": [
                "source"
              ]
            },
            "then": {
              "properties": {
                "issues": {
                  "maxItems": 100
                }
              }
            }
          }
        ]
      },
      "ImportReply": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "result": {
            "$ref": "#/components/schemas/ImportResult"
          },
          "receipt": {
            "$ref": "#/components/schemas/OneCProductReceipt"
          }
        },
        "required": [
          "ok",
          "result"
        ]
      },
      "Health": {
        "type": "object",
        "properties": {
          "health": {
            "type": "string",
            "enum": [
              "empty",
              "healthy",
              "warning",
              "stopped"
            ]
          },
          "lastCatalogSyncAt": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "lastStockSyncAt": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "lastErrorAt": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "lastError": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "products": {
            "type": "integer",
            "minimum": 0
          },
          "activeProducts": {
            "type": "integer",
            "minimum": 0
          },
          "totalStock": {
            "type": "integer",
            "minimum": 0,
            "description": "Сумма сохранённых количеств всех товаров, включая неактивные. Не является разрешением продавать; учитывайте свежесть."
          },
          "apiKey": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "mask": {
                    "type": "string"
                  },
                  "createdAt": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "required": [
                  "mask",
                  "createdAt"
                ]
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "health",
          "lastCatalogSyncAt",
          "lastStockSyncAt",
          "lastErrorAt",
          "lastError",
          "products",
          "activeProducts",
          "totalStock",
          "apiKey"
        ]
      },
      "HealthReply": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "status": {
            "$ref": "#/components/schemas/Health"
          },
          "limits": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "oneCStockMaxAgeSeconds": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1800
              }
            },
            "required": [
              "oneCStockMaxAgeSeconds"
            ]
          },
          "identity": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "schemaVersion": {
                "const": 1
              },
              "supplierId": {
                "type": "string",
                "minLength": 1
              }
            },
            "required": [
              "schemaVersion",
              "supplierId"
            ]
          }
        },
        "required": [
          "ok",
          "status"
        ]
      },
      "Reservation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "marketplace": {
            "type": "string",
            "enum": [
              "wildberries",
              "yandex",
              "ozon"
            ]
          },
          "marketplaceOrderId": {
            "type": "integer",
            "minimum": 1
          },
          "externalProductId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "sku": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10000
          },
          "purchasePriceKopecks": {
            "type": "integer",
            "minimum": 1,
            "description": "Закупочная цена одной товарной единицы в копейках. 24990 означает 249,90 руб."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "confirmed",
              "rejected",
              "expired"
            ]
          },
          "externalReservationId": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ]
          },
          "supplierMessage": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ]
          },
          "deadlineAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "marketplace",
          "marketplaceOrderId",
          "externalProductId",
          "sku",
          "quantity",
          "purchasePriceKopecks",
          "status",
          "externalReservationId",
          "supplierMessage",
          "deadlineAt",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false,
        "description": "Прежний публичный формат без schemaVersion/warehouseId: только поля резерва. Для конкретного физического склада и отгрузки используйте WarehouseReservation."
      },
      "ReservationsReply": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "reservations": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "$ref": "#/components/schemas/Reservation"
            }
          }
        },
        "required": [
          "ok",
          "reservations"
        ],
        "not": {
          "anyOf": [
            {
              "required": [
                "schemaVersion"
              ]
            },
            {
              "required": [
                "warehouseId"
              ]
            }
          ]
        }
      },
      "ReservationDecision": {
        "type": "object",
        "properties": {
          "reservationId": {
            "type": "string",
            "description": "ID полученной заявки."
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "rejected"
            ]
          },
          "externalReservationId": {
            "type": "string",
            "maxLength": 200,
            "description": "Обязательный непустой послеtrim номер в системе поставщика при confirmed. При rejected не обязателен."
          },
          "message": {
            "type": "string",
            "description": "Необязательное пояснение. Сервер trim и обрезает до 500 символов."
          }
        },
        "required": [
          "reservationId",
          "status"
        ],
        "allOf": [
          {
            "if": {
              "properties": {
                "status": {
                  "const": "confirmed"
                }
              },
              "required": [
                "status"
              ]
            },
            "then": {
              "required": [
                "externalReservationId"
              ],
              "properties": {
                "externalReservationId": {
                  "type": "string",
                  "minLength": 1,
                  "pattern": "\\S",
                  "maxLength": 200
                }
              }
            }
          }
        ],
        "not": {
          "anyOf": [
            {
              "required": [
                "shipmentStatus"
              ]
            },
            {
              "required": [
                "externalShipmentId"
              ]
            },
            {
              "required": [
                "schemaVersion"
              ]
            },
            {
              "required": [
                "warehouseId"
              ]
            }
          ]
        }
      },
      "ReservationReply": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "reservation": {
            "$ref": "#/components/schemas/Reservation"
          }
        },
        "required": [
          "ok",
          "reservation"
        ],
        "not": {
          "anyOf": [
            {
              "required": [
                "schemaVersion"
              ]
            },
            {
              "required": [
                "warehouseId"
              ]
            }
          ]
        }
      },
      "ConnectionChallenge": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "const": "connection_test"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "replyToken": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$",
            "description": "Токен только текущей проверки. Возвращается авторизованному клиенту, не является API-ключом."
          }
        },
        "required": [
          "id",
          "kind",
          "expiresAt",
          "replyToken"
        ]
      },
      "ConnectionTestReply": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "test": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ConnectionChallenge"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "ok",
          "test"
        ]
      },
      "ConnectionAcknowledgement": {
        "type": "object",
        "properties": {
          "testId": {
            "type": "string",
            "description": "ID из GET test.id."
          },
          "replyToken": {
            "type": "string",
            "description": "Точный replyToken из GET. Неверный токен даёт 409."
          },
          "result": {
            "const": "received"
          }
        },
        "required": [
          "testId",
          "replyToken",
          "result"
        ]
      },
      "ConnectionPassed": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "status": {
            "const": "passed"
          }
        },
        "required": [
          "ok",
          "status"
        ]
      },
      "OneCProduct": {
        "type": "object",
        "properties": {
          "externalId": {
            "type": "string",
            "maxLength": 100,
            "description": "Стабильный ID товара в системе поставщика; одинаковый для разных складов.",
            "minLength": 1
          },
          "sku": {
            "type": "string",
            "maxLength": 100,
            "description": "Артикул поставщика.",
            "minLength": 1
          },
          "name": {
            "type": "string",
            "maxLength": 300,
            "description": "Название.",
            "minLength": 1
          },
          "category": {
            "type": "string",
            "maxLength": 200,
            "description": "Категория поставщика. Не обязательна для приёма строки, но нужна для дальнейшей подготовки карточки."
          },
          "barcodes": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[0-9]{8,14}$"
            },
            "description": "Не обязательны для приёма строки; нужны для готовой карточки. Нормализатор сохраняет все переданные непустые значения."
          },
          "price": {
            "type": "number",
            "maximum": 100000000,
            "description": "Предоставленная закупочная цена, конечное число от 0 до 100000000 рублей. Ноль не допускает продажу/публикацию.",
            "minimum": 0
          },
          "currency": {
            "type": "string",
            "const": "RUB"
          },
          "availableQuantity": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000000,
            "description": "Точное количество товарных единиц. Ноль допустим и передаётся явно."
          },
          "warehouseId": {
            "type": "string",
            "maxLength": 100,
            "description": "Стабильный ID склада поставщика.",
            "minLength": 1
          },
          "images": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^https://"
            },
            "description": "Прямые HTTPS-ссылки. Пустой массив допустим для приёма, но не означает готовность карточки. Доступность фотографий проверяется отдельно."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "maxLength": 64,
            "description": "Время изменения в источнике. Используйте ISO8601 с часовым поясом; не более 5 минут в будущем. При повторной передаче неизменённых данных сохраните исходное время; для нового остатка передайте новое время фактической проверки."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive"
            ]
          },
          "description": {
            "type": "string",
            "maxLength": 20000,
            "description": "Необязательное описание; лишние символы обрезаются."
          },
          "brand": {
            "type": "string",
            "maxLength": 300,
            "description": "Необязательный бренд."
          },
          "country": {
            "type": "string",
            "maxLength": 300,
            "description": "Необязательная страна."
          },
          "packageLengthCm": {
            "type": "number",
            "description": "Длина упаковки в сантиметрах.",
            "minimum": 0
          },
          "packageWidthCm": {
            "type": "number",
            "description": "Ширина упаковки в сантиметрах.",
            "minimum": 0
          },
          "packageHeightCm": {
            "type": "number",
            "description": "Высота упаковки в сантиметрах.",
            "minimum": 0
          },
          "weightKg": {
            "type": "number",
            "description": "Вес в килограммах.",
            "minimum": 0
          },
          "packageCount": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000,
            "description": "Число упаковок товарной единицы."
          },
          "minimumOrderQuantity": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Фактический минимальный заказ; не число предметов внутри заводского набора. Для доступности селлеру существующие правила требуют 1."
          },
          "orderQuantityStep": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Фактический шаг заказа. Для доступности селлеру существующие правила требуют 1."
          },
          "characteristics": {
            "type": "object",
            "additionalProperties": true,
            "description": "Необязательные характеристики. Ключи до 200 символов; нормализатор ограничивает размеры и игнорирует неподдерживаемые значения."
          },
          "tnved": {
            "type": "string",
            "pattern": "^(?:[0-9]{10}|[0-9]{14})$",
            "description": "Код ТН ВЭД поставщика. Передавайте вместе с товаром, если известен. Сохраните ведущие нули. Обязательность и допустимость проверяются после подтверждения категории для конкретной площадки; отсутствие кода не запрещает приём строки."
          },
          "packageWeightKg": {
            "type": "number",
            "minimum": 0,
            "description": "Предоставленный вес упаковки, без добавленного веса или догадки о брутто для weightKg."
          }
        },
        "required": [
          "externalId",
          "sku",
          "name",
          "price",
          "currency",
          "availableQuantity",
          "warehouseId",
          "updatedAt",
          "status"
        ],
        "description": "Каноническая карточка 1С для приёма предоставленных фактов. Описательные поля и фотографии необязательны, их отсутствие возвращается предупреждениями; они не дополняются выдуманными значениями. Конечные нулевые цена и измерения допустимы в черновике, но требования продажи/публикации остаются строгими. Предоставленный weightKg не объявляется брутто; packageWeightKg имеет явно предоставленный смысл веса упаковки. Все предоставленные значения проверяются по типу и безопасности. Дополнительные поля и вложенные сведения поставщика сохраняются внутри карточки товара. Они не обязательны. Пропущенные дополнительные поля сохраняют прежние значения, переданные объект/список/null заменяют поле целиком. Реквизиты и файлы документов передаются с товаром; ключ доступа передаётся только в заголовке.",
        "examples": [
          {
            "externalId": "product-1001",
            "sku": "SUPPLIER-1001",
            "name": "Керамическая кружка, 350 мл",
            "category": "Посуда / Кружки",
            "barcodes": [
              "4601234567893"
            ],
            "price": 249.9,
            "currency": "RUB",
            "availableQuantity": 24,
            "warehouseId": "warehouse-1",
            "images": [
              "https://example.com/products/mug-1001.jpg"
            ],
            "updatedAt": "2026-09-18T10:00:00.000Z",
            "status": "active",
            "description": "Керамическая кружка в индивидуальной упаковке.",
            "brand": "Пример бренда",
            "country": "Россия",
            "packageLengthCm": 12,
            "packageWidthCm": 10,
            "packageHeightCm": 11,
            "packageCount": 1,
            "minimumOrderQuantity": 1,
            "orderQuantityStep": 1,
            "characteristics": {
              "Материал": "Керамика",
              "Объём, мл": 350
            },
            "packageWeightKg": 0.42
          }
        ],
        "additionalProperties": true
      },
      "ReservationShipment": {
        "type": "object",
        "description": "Совместимое имя схемы примера. Готовность/отгрузка требуют schemaVersion:2 и warehouseId; прежний запрос без склада сервер не принимает.",
        "properties": {
          "reservationId": {
            "type": "string",
            "description": "ID полученной и уже подтверждённой заявки."
          },
          "shipmentStatus": {
            "type": "string",
            "enum": [
              "ready",
              "shipped"
            ]
          },
          "externalShipmentId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "\\S",
            "description": "Обязателен для shipped; запрещён для ready."
          },
          "message": {
            "type": "string",
            "maxLength": 500,
            "description": "Необязательное пояснение этапа поставки; после trim не более 500 знаков. При повторе сохраните тот же текст."
          },
          "schemaVersion": {
            "const": 2
          },
          "warehouseId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "pattern": "^(?!\\s)(?!.*\\s$)[^\\x00-\\x1f\\x7f]+$",
            "description": "Точный ID физического склада, который передаётся с остатком. Название города не заменяет ID."
          }
        },
        "required": [
          "reservationId",
          "shipmentStatus",
          "schemaVersion",
          "warehouseId"
        ],
        "not": {
          "anyOf": [
            {
              "required": [
                "status"
              ]
            },
            {
              "required": [
                "externalReservationId"
              ]
            }
          ]
        },
        "allOf": [
          {
            "if": {
              "properties": {
                "shipmentStatus": {
                  "const": "shipped"
                }
              },
              "required": [
                "shipmentStatus"
              ]
            },
            "then": {
              "required": [
                "externalShipmentId"
              ]
            }
          },
          {
            "if": {
              "properties": {
                "shipmentStatus": {
                  "const": "ready"
                }
              },
              "required": [
                "shipmentStatus"
              ]
            },
            "then": {
              "not": {
                "required": [
                  "externalShipmentId"
                ]
              }
            }
          }
        ]
      },
      "FulfillmentDestination": {
        "type": "object",
        "additionalProperties": false,
        "description": "Сохранённое при создании заявки назначение поставщик → фулфилмент. ID, название и адрес исходного склада не меняются от последующих настроек. Выдаётся только вместе с заявкой текущего поставщика.",
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1,
            "description": "ID назначенного фулфилмента."
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "pattern": "\\S",
            "description": "Сохранённое название склада."
          },
          "address": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300,
            "pattern": "\\S",
            "description": "Сохранённый адрес склада фулфилмента для передачи товара поставщиком; не пункт приёмки площадки."
          }
        },
        "required": [
          "id",
          "name",
          "address"
        ],
        "examples": [
          {
            "id": "40000000-0000-4000-8000-000000000001",
            "name": "Пример фулфилмента",
            "address": "Тестовый город, Складская улица, дом 1"
          }
        ]
      },
      "OneCReceiptRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "schemaVersion": {
            "const": 2
          },
          "batchId": {
            "type": "string",
            "format": "uuid",
            "not": {
              "const": "00000000-0000-0000-0000-000000000000"
            }
          },
          "initialSupplierStatus": {
            "const": "active",
            "description": "Явное начальное состояние выбранных поставщиком новых товаров. Только действительно неизвестный этому поставщику externalId с отсутствующим products[].status получает active. Уже существующий inactive не активируется; локальный кеш клиента не доказывает новизну карточки."
          }
        },
        "required": [
          "schemaVersion",
          "batchId"
        ]
      },
      "OneCReceiptProduct": {
        "type": "object",
        "description": "Для receipt.schemaVersion=2 допускается новая неполная карточка с собственными базовыми ID, артикулом, названием и статусом. Только существующая точная пара поставщик/externalId наследует пропущенные описательные поля; совпадение артикула ничего не присваивает. Цена, валюта, количество, склад и updatedAt не наследуются. SourceVersion — неизменный UUID исходной отправки, а не часы или доказательство владения. Отсутствующие данные не разрешают продажу/публикацию. Дополнительные поля и вложенные сведения поставщика сохраняются внутри карточки товара. Они не обязательны. Пропущенные дополнительные поля сохраняют прежние значения, переданные объект/список/null заменяют поле целиком. Реквизиты и файлы документов передаются с товаром; ключ доступа передаётся только в заголовке.",
        "properties": {
          "externalId": {
            "type": "string",
            "maxLength": 100,
            "description": "Стабильный ID товара в системе поставщика; одинаковый для разных складов.",
            "minLength": 1
          },
          "sku": {
            "type": "string",
            "maxLength": 100,
            "description": "Артикул поставщика.",
            "minLength": 1
          },
          "name": {
            "type": "string",
            "maxLength": 300,
            "description": "Название.",
            "minLength": 1
          },
          "category": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200,
                "description": "Категория поставщика. Не обязательна для приёма строки, но нужна для дальнейшей подготовки карточки."
              },
              {
                "type": "null"
              }
            ]
          },
          "barcodes": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "string",
                  "pattern": "^[0-9]{8,14}$"
                },
                "description": "Не обязательны для приёма строки; нужны для готовой карточки. Нормализатор сохраняет все переданные непустые значения."
              },
              {
                "type": "null"
              }
            ]
          },
          "price": {
            "type": "number",
            "maximum": 100000000,
            "description": "Предоставленная закупочная цена, конечное число от 0 до 100000000 рублей. Ноль не допускает продажу/публикацию.",
            "minimum": 0
          },
          "currency": {
            "type": "string",
            "const": "RUB"
          },
          "availableQuantity": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000000,
            "description": "Точное количество товарных единиц. Ноль допустим и передаётся явно."
          },
          "warehouseId": {
            "type": "string",
            "maxLength": 100,
            "description": "Стабильный ID склада поставщика.",
            "minLength": 1
          },
          "images": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "string",
                  "pattern": "^https://"
                },
                "description": "Прямые HTTPS-ссылки. Пустой массив допустим для приёма, но не означает готовность карточки. Доступность фотографий проверяется отдельно."
              },
              {
                "type": "null"
              }
            ]
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "maxLength": 64,
            "description": "Время изменения в источнике. Используйте ISO8601 с часовым поясом; не более 5 минут в будущем. При повторной передаче неизменённых данных сохраните исходное время; для нового остатка передайте новое время фактической проверки."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive"
            ]
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 20000,
                "description": "Необязательное описание; лишние символы обрезаются."
              },
              {
                "type": "null"
              }
            ]
          },
          "brand": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 300,
                "description": "Необязательный бренд."
              },
              {
                "type": "null"
              }
            ]
          },
          "country": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 300,
                "description": "Необязательная страна."
              },
              {
                "type": "null"
              }
            ]
          },
          "packageLengthCm": {
            "anyOf": [
              {
                "type": "number",
                "description": "Длина упаковки в сантиметрах.",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "packageWidthCm": {
            "anyOf": [
              {
                "type": "number",
                "description": "Ширина упаковки в сантиметрах.",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "packageHeightCm": {
            "anyOf": [
              {
                "type": "number",
                "description": "Высота упаковки в сантиметрах.",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "weightKg": {
            "anyOf": [
              {
                "type": "number",
                "description": "Вес в килограммах.",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "packageCount": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 1,
                "maximum": 1000,
                "description": "Число упаковок товарной единицы."
              },
              {
                "type": "null"
              }
            ]
          },
          "minimumOrderQuantity": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Фактический минимальный заказ; не число предметов внутри заводского набора. Для доступности селлеру существующие правила требуют 1."
          },
          "orderQuantityStep": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Фактический шаг заказа. Для доступности селлеру существующие правила требуют 1."
          },
          "characteristics": {
            "anyOf": [
              {
                "type": "object",
                "maxProperties": 200,
                "additionalProperties": {
                  "oneOf": [
                    {
                      "type": "string",
                      "maxLength": 2000
                    },
                    {
                      "type": "number"
                    },
                    {
                      "type": "boolean"
                    },
                    {
                      "type": "array",
                      "maxItems": 50,
                      "items": {
                        "type": "string",
                        "maxLength": 2000
                      }
                    }
                  ]
                },
                "description": "Необязательные характеристики. Ключи до 200 символов; нормализатор ограничивает размеры и игнорирует неподдерживаемые значения."
              },
              {
                "type": "null"
              }
            ],
            "additionalProperties": true
          },
          "tnved": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^(?:[0-9]{10}|[0-9]{14})$",
                "description": "Код ТН ВЭД поставщика. Передавайте вместе с товаром, если известен. Сохраните ведущие нули. Обязательность и допустимость проверяются после подтверждения категории для конкретной площадки; отсутствие кода не запрещает приём строки."
              },
              {
                "type": "null"
              }
            ]
          },
          "sourceVersion": {
            "type": "string",
            "format": "uuid",
            "not": {
              "const": "00000000-0000-0000-0000-000000000000"
            }
          },
          "packageWeightKg": {
            "anyOf": [
              {
                "type": "number",
                "minimum": 0,
                "description": "Предоставленный вес упаковки, без добавленного веса или догадки о брутто для weightKg."
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "externalId",
          "sourceVersion",
          "price",
          "currency",
          "availableQuantity",
          "warehouseId",
          "updatedAt"
        ],
        "additionalProperties": true
      },
      "OneCReceiptItem": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "row": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500
          },
          "externalProductId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "submittedVersion": {
            "type": "string",
            "format": "uuid",
            "not": {
              "const": "00000000-0000-0000-0000-000000000000"
            }
          },
          "warehouseId": {
            "type": "string"
          },
          "submittedContentHash": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[a-f0-9]{64}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "cardVersion": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "stockVersion": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "cardContentHash": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[a-f0-9]{64}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "stockContentHash": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[a-f0-9]{64}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "applied": {
            "type": "boolean"
          },
          "disposition": {
            "type": "string",
            "enum": [
              "applied",
              "duplicate",
              "stale",
              "rejected"
            ]
          },
          "cardDisposition": {
            "type": "string",
            "enum": [
              "applied",
              "duplicate",
              "stale",
              "rejected"
            ]
          },
          "stockDisposition": {
            "type": "string",
            "enum": [
              "applied",
              "duplicate",
              "stale",
              "rejected"
            ]
          }
        },
        "required": [
          "row",
          "externalProductId",
          "submittedVersion",
          "warehouseId",
          "submittedContentHash",
          "cardVersion",
          "stockVersion",
          "cardContentHash",
          "stockContentHash",
          "applied",
          "disposition",
          "cardDisposition",
          "stockDisposition"
        ]
      },
      "OneCProductReceipt": {
        "type": "object",
        "additionalProperties": false,
        "description": "Возвращается только после сохранения результата. Не подтверждает публикацию, резервирование или ЭДО. applied=true означает, что и карточка, и наблюдение остатка применены либо точно повторяют сохранённую версию. stale/rejected не продвигают курсор. Хеши информационные: хеш исходной неполной строки не равен хешу итоговой карточки.",
        "properties": {
          "schemaVersion": {
            "const": 2
          },
          "supplierId": {
            "type": "string",
            "minLength": 1
          },
          "batchId": {
            "type": "string",
            "format": "uuid",
            "not": {
              "const": "00000000-0000-0000-0000-000000000000"
            }
          },
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 500,
            "items": {
              "$ref": "#/components/schemas/OneCReceiptItem"
            }
          }
        },
        "required": [
          "schemaVersion",
          "supplierId",
          "batchId",
          "items"
        ]
      },
      "SupplierPhotoAsset": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
          },
          "externalProductId": {
            "type": "string",
            "format": "uuid",
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
          },
          "nativeFileId": {
            "type": "string",
            "format": "uuid",
            "pattern": "^(?!00000000-0000-0000-0000-000000000000$)[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
          },
          "sourceUpdatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "sourceDigest": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "digest": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "mimeType": {
            "enum": [
              "image/jpeg",
              "image/png",
              "image/webp"
            ]
          },
          "size": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5242880
          },
          "width": {
            "type": "integer",
            "minimum": 1
          },
          "height": {
            "type": "integer",
            "minimum": 1
          },
          "url": {
            "type": "string",
            "pattern": "^https://"
          },
          "duplicate": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "externalProductId",
          "nativeFileId",
          "sourceUpdatedAt",
          "sourceDigest",
          "digest",
          "mimeType",
          "size",
          "width",
          "height",
          "url",
          "duplicate"
        ]
      },
      "SupplierPhotoReply": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "ok": {
            "const": true
          },
          "identity": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "schemaVersion": {
                "const": 1
              },
              "supplierId": {
                "type": "string",
                "minLength": 1
              }
            },
            "required": [
              "schemaVersion",
              "supplierId"
            ]
          },
          "asset": {
            "$ref": "#/components/schemas/SupplierPhotoAsset"
          }
        },
        "required": [
          "ok",
          "identity",
          "asset"
        ]
      },
      "WarehouseReservationDecision": {
        "type": "object",
        "properties": {
          "reservationId": {
            "type": "string",
            "description": "ID полученной заявки."
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "rejected"
            ]
          },
          "externalReservationId": {
            "type": "string",
            "maxLength": 200,
            "description": "Обязательный непустой послеtrim номер в системе поставщика при confirmed. При rejected не обязателен."
          },
          "message": {
            "type": "string",
            "description": "Необязательное пояснение. Сервер trim и обрезает до 500 символов."
          },
          "schemaVersion": {
            "const": 2
          },
          "warehouseId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "pattern": "^(?!\\s)(?!.*\\s$)[^\\x00-\\x1f\\x7f]+$",
            "description": "Точный ID физического склада, который передаётся с остатком. Название города не заменяет ID."
          }
        },
        "required": [
          "reservationId",
          "status",
          "schemaVersion",
          "warehouseId"
        ],
        "allOf": [
          {
            "if": {
              "properties": {
                "status": {
                  "const": "confirmed"
                }
              },
              "required": [
                "status"
              ]
            },
            "then": {
              "required": [
                "externalReservationId"
              ],
              "properties": {
                "externalReservationId": {
                  "type": "string",
                  "minLength": 1,
                  "pattern": "\\S",
                  "maxLength": 200
                }
              }
            }
          }
        ],
        "not": {
          "anyOf": [
            {
              "required": [
                "shipmentStatus"
              ]
            },
            {
              "required": [
                "externalShipmentId"
              ]
            }
          ]
        }
      },
      "WarehouseReservationShipment": {
        "type": "object",
        "description": "Отдельное сообщение после подтверждённого резерва. Только ready → shipped; прямой shipped, обратный переход, pending/rejected/expired и попытка сменить сохранённое сообщение дают 409. Для shipped требуется ранее назначенный в сохранённом акте фулфилмент и номер реальной отгрузки. Повтор идентичного этапа, номера и нормализованного сообщения идемпотентен. Для новой shipped дополнительно требуется полный сохранённый fulfillmentDestination и отсутствие fulfillmentDestinationIssue. Эти данные не передаются клиентом в PATCH. Старый уже сохранённый shipped допускает точный идемпотентный повтор без создания новой отгрузки.",
        "properties": {
          "reservationId": {
            "type": "string",
            "description": "ID полученной и уже подтверждённой заявки."
          },
          "shipmentStatus": {
            "type": "string",
            "enum": [
              "ready",
              "shipped"
            ]
          },
          "externalShipmentId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "\\S",
            "description": "Обязателен для shipped; запрещён для ready."
          },
          "message": {
            "type": "string",
            "maxLength": 500,
            "description": "Необязательное пояснение этапа поставки; после trim не более 500 знаков. При повторе сохраните тот же текст."
          },
          "schemaVersion": {
            "const": 2
          },
          "warehouseId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "pattern": "^(?!\\s)(?!.*\\s$)[^\\x00-\\x1f\\x7f]+$",
            "description": "Точный ID физического склада, который передаётся с остатком. Название города не заменяет ID."
          }
        },
        "required": [
          "reservationId",
          "shipmentStatus",
          "schemaVersion",
          "warehouseId"
        ],
        "not": {
          "anyOf": [
            {
              "required": [
                "status"
              ]
            },
            {
              "required": [
                "externalReservationId"
              ]
            }
          ]
        },
        "allOf": [
          {
            "if": {
              "properties": {
                "shipmentStatus": {
                  "const": "shipped"
                }
              },
              "required": [
                "shipmentStatus"
              ]
            },
            "then": {
              "required": [
                "externalShipmentId"
              ]
            }
          },
          {
            "if": {
              "properties": {
                "shipmentStatus": {
                  "const": "ready"
                }
              },
              "required": [
                "shipmentStatus"
              ]
            },
            "then": {
              "not": {
                "required": [
                  "externalShipmentId"
                ]
              }
            }
          }
        ]
      },
      "WarehouseReservation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "marketplace": {
            "type": "string",
            "enum": [
              "wildberries",
              "yandex",
              "ozon"
            ]
          },
          "marketplaceOrderId": {
            "type": "integer",
            "minimum": 1
          },
          "externalProductId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "sku": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10000
          },
          "purchasePriceKopecks": {
            "type": "integer",
            "minimum": 1,
            "description": "Закупочная цена одной товарной единицы в копейках. 24990 означает 249,90 руб."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "confirmed",
              "rejected",
              "expired"
            ]
          },
          "externalReservationId": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ]
          },
          "supplierMessage": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ]
          },
          "deadlineAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "marketplaceOrderItemId": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100
              },
              {
                "type": "null"
              }
            ]
          },
          "shipmentStatus": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "ready",
                  "shipped"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Отдельный этап поставки; status резерва остаётся confirmed. null — готовность ещё не сообщена."
          },
          "readyAt": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "shippedAt": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          },
          "externalShipmentId": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ]
          },
          "shipmentMessage": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ]
          },
          "fulfillmentDestination": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FulfillmentDestination"
              },
              {
                "type": "null"
              }
            ],
            "description": "Куда передать товар. Снимок назначения сохраняется в begin и переносится в акт при confirmed; GET и PATCH читают этот снимок без пересчёта по текущим настройкам. null запрещает новую автоматическую отгрузку."
          },
          "fulfillmentDestinationIssue": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "not_assigned",
                  "ambiguous",
                  "destination_incomplete",
                  "snapshot_missing"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "null — полный сохранённый адрес. not_assigned — не был назначен склад; ambiguous — несколько назначений; destination_incomplete — отсутствуют название или адрес в сохранённом назначении; snapshot_missing — старый снимок без адреса. При ненулевой причине обратитесь в «Бери товар» для разбора заявки, не подставляйте сегодняшний адрес."
          },
          "supplierWarehouseId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "pattern": "^(?!\\s)(?!.*\\s$)[^\\x00-\\x1f\\x7f]+$",
            "description": "Точный ID физического склада, который передаётся с остатком. Название города не заменяет ID."
          }
        },
        "required": [
          "id",
          "marketplace",
          "marketplaceOrderId",
          "externalProductId",
          "sku",
          "quantity",
          "purchasePriceKopecks",
          "status",
          "externalReservationId",
          "supplierMessage",
          "deadlineAt",
          "createdAt",
          "updatedAt",
          "marketplaceOrderItemId",
          "shipmentStatus",
          "readyAt",
          "shippedAt",
          "externalShipmentId",
          "shipmentMessage",
          "fulfillmentDestination",
          "fulfillmentDestinationIssue",
          "supplierWarehouseId"
        ],
        "allOf": [
          {
            "if": {
              "properties": {
                "fulfillmentDestination": {
                  "type": "object"
                }
              },
              "required": [
                "fulfillmentDestination"
              ]
            },
            "then": {
              "properties": {
                "fulfillmentDestinationIssue": {
                  "const": null
                }
              }
            },
            "else": {
              "properties": {
                "fulfillmentDestinationIssue": {
                  "type": "string",
                  "enum": [
                    "not_assigned",
                    "ambiguous",
                    "destination_incomplete",
                    "snapshot_missing"
                  ]
                }
              }
            }
          }
        ]
      },
      "WarehouseReservationsReply": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "reservations": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "$ref": "#/components/schemas/WarehouseReservation"
            }
          },
          "schemaVersion": {
            "const": 2
          },
          "warehouseId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "pattern": "^(?!\\s)(?!.*\\s$)[^\\x00-\\x1f\\x7f]+$",
            "description": "Точный ID физического склада, который передаётся с остатком. Название города не заменяет ID."
          }
        },
        "required": [
          "ok",
          "reservations",
          "schemaVersion",
          "warehouseId"
        ]
      },
      "WarehouseReservationReply": {
        "type": "object",
        "properties": {
          "ok": {
            "const": true
          },
          "reservation": {
            "$ref": "#/components/schemas/WarehouseReservation"
          },
          "schemaVersion": {
            "const": 2
          },
          "warehouseId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "pattern": "^(?!\\s)(?!.*\\s$)[^\\x00-\\x1f\\x7f]+$",
            "description": "Точный ID физического склада, который передаётся с остатком. Название города не заменяет ID."
          }
        },
        "required": [
          "ok",
          "reservation",
          "schemaVersion",
          "warehouseId"
        ]
      }
    }
  }
}
