{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/akeda-ru/json-schema/akeda-ru-marketplace-store-schema.json",
  "title": "MarketplaceStore",
  "description": "Магазин маркетплейса в кабинете. Форма одна для Ozon, Wildberries, Яндекс Маркета, Ламоды и Летуаль — их различает только поле platform. Ключи, токены и proxy в ответ не попадают; вместо них возвращаются безопасные признаки настройки. Магазины Ламоды и Летуаль живут только в кабинете — сборщик их не грузит, external_id у них отрицательный; у Летуаль реквизитов нет вовсе.",
  "x-generated": "2026-11-01",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/akeda-ru-openapi.yaml#/components/schemas/MarketplaceStore",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "id",
    "platform",
    "name",
    "tax_percent",
    "tax_source",
    "is_active",
    "has_fbs",
    "has_jam",
    "credentials_configured",
    "ozon_client_id_set",
    "ozon_api_key_set",
    "ozon_pf_client_id_set",
    "ozon_pf_client_secret_set",
    "wb_token_set",
    "ym_business_id_set",
    "ym_api_key_set",
    "lamoda_client_id_set",
    "lamoda_client_secret_set",
    "proxy_set",
    "config_sync_status",
    "connection_status"
  ],
  "properties": {
    "id": {
      "$ref": "#/$defs/UUID"
    },
    "platform": {
      "type": "string",
      "enum": [
        "ozon",
        "wildberries",
        "yandex",
        "lamoda",
        "letoile"
      ],
      "description": "Платформа задаётся маршрутом, а не телом запроса"
    },
    "name": {
      "type": "string"
    },
    "external_id": {
      "type": "integer",
      "format": "int64",
      "minimum": -9007199254740992,
      "maximum": 2147483647,
      "readOnly": true,
      "description": "Внутренний идентификатор MPTrack; назначается после передачи настройки и не вводится пользователем. У магазина Ламоды (сборщик её не грузит) номер назначает кабинет — он отрицательный и не меньше −2^53"
    },
    "tax_percent": {
      "type": "string",
      "readOnly": true,
      "description": "Процент налога с того, что заплатил покупатель, на сегодня — им считают ОПиУ, декомпозиция, воронка и цены; decimal строкой. При источнике policy выводится из учётной политики юрлица магазина, при store — ручная ставка магазина"
    },
    "tax_source": {
      "type": "string",
      "enum": [
        "policy",
        "store"
      ],
      "readOnly": true,
      "description": "Источник налога на сегодня: policy — система налогообложения юрлица магазина из учётной политики, store — ставка, заданная в магазине вручную (переопределение)"
    },
    "tax": {
      "$ref": "#/$defs/MarketplaceStoreTax"
    },
    "cost": {
      "$ref": "#/$defs/MarketplaceStoreCost"
    },
    "is_active": {
      "type": "boolean"
    },
    "has_fbs": {
      "type": "boolean",
      "description": "Для подключения включена загрузка схемы FBS"
    },
    "has_jam": {
      "type": "boolean",
      "description": "Для подключения Wildberries включена аналитика «Джем»"
    },
    "credentials_configured": {
      "type": "boolean",
      "readOnly": true,
      "description": "Есть хотя бы один сохранённый API-реквизит"
    },
    "ozon_client_id_set": {
      "type": "boolean",
      "readOnly": true
    },
    "ozon_api_key_set": {
      "type": "boolean",
      "readOnly": true
    },
    "ozon_pf_client_id_set": {
      "type": "boolean",
      "readOnly": true
    },
    "ozon_pf_client_secret_set": {
      "type": "boolean",
      "readOnly": true
    },
    "wb_token_set": {
      "type": "boolean",
      "readOnly": true
    },
    "ym_business_id_set": {
      "type": "boolean",
      "readOnly": true
    },
    "ym_api_key_set": {
      "type": "boolean",
      "readOnly": true
    },
    "lamoda_client_id_set": {
      "type": "boolean",
      "readOnly": true
    },
    "lamoda_client_secret_set": {
      "type": "boolean",
      "readOnly": true
    },
    "proxy_set": {
      "type": "boolean",
      "readOnly": true
    },
    "config_sync_status": {
      "type": "string",
      "enum": [
        "not_configured",
        "synced",
        "error"
      ],
      "readOnly": true,
      "description": "Состояние передачи настройки в MPTrack"
    },
    "config_synced_at": {
      "type": "string",
      "format": "date-time",
      "readOnly": true
    },
    "collector_local_only": {
      "type": "boolean",
      "readOnly": true,
      "description": "Стенд не боевой: магазин у сборщика общий с боевым стендом, поэтому выключение и удаление меняют только этот кабинет, а загрузки у сборщика продолжаются"
    },
    "credentials_withheld": {
      "type": "boolean",
      "readOnly": true,
      "description": "Реквизиты магазина сняты при копии кабинета с другого стенда: шифроблоб не переносится, на этом стенде реквизиты не заданы. Номер магазина у сборщика сохранён; признак уходит, когда ключ введут здесь заново"
    },
    "token_class": {
      "type": "string",
      "enum": [
        "basic",
        "personal",
        "test",
        "service",
        "unknown"
      ],
      "readOnly": true,
      "description": "Безопасная классификация токена Wildberries без раскрытия токена: basic — ограниченный базовый, personal — персональный, test — тестовый, service — сервисный, unknown — тип не определён"
    },
    "credential": {
      "type": "object",
      "readOnly": true,
      "additionalProperties": false,
      "required": [
        "kind",
        "scopes",
        "read_only"
      ],
      "description": "Несекретные сведения о ключе площадки: тип, категории доступа или роли, только чтение и срок действия. Wildberries — разобрано из самого токена; Ozon — роли и срок по методу Ozon /v1/roles, только при key_info=1",
      "properties": {
        "kind": {
          "type": "string",
          "enum": [
            "basic",
            "personal",
            "test",
            "service",
            "unknown",
            "ozon"
          ],
          "description": "Тип ключа по полю acc токена Wildberries; ozon — ключ Seller API Ozon"
        },
        "roles": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Роли ключа Ozon названиями площадки"
        },
        "scopes": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "content",
              "analytics",
              "prices",
              "marketplace",
              "statistics",
              "promotion",
              "feedbacks",
              "chat",
              "supplies",
              "returns",
              "documents",
              "finance",
              "users"
            ]
          },
          "description": "Категории методов, к которым у ключа есть доступ"
        },
        "read_only": {
          "type": "boolean",
          "description": "Ключ только на чтение"
        },
        "expires_at": {
          "type": "string",
          "format": "date-time",
          "description": "Когда ключ перестанет работать"
        }
      }
    },
    "write_key": {
      "$ref": "#/$defs/MarketplaceStoreWriteKey"
    },
    "connection_status": {
      "type": "string",
      "enum": [
        "not_checked",
        "pending",
        "disabled",
        "ok",
        "warning",
        "error"
      ],
      "readOnly": true,
      "description": "Безопасное состояние подключения в ERP: not_checked — проверка ещё не запускалась, pending — MPTrack проверяет реквизиты или запускает первую загрузку, disabled — загрузки отключены, ok — подключение работает, warning — требуется внимание, error — подключение не работает. Сырые статусы и тексты MPTrack не публикуются"
    },
    "connection_error_code": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9_.-]{0,63}$",
      "readOnly": true,
      "description": "Безопасный стабильный код состояния подключения; сырой текст ошибки не публикуется"
    },
    "last_etl_at": {
      "type": "string",
      "format": "date-time",
      "readOnly": true,
      "description": "Момент последней успешной загрузки этого подключения"
    },
    "initial_load_ready_at": {
      "oneOf": [
        {
          "type": "string",
          "format": "date-time"
        },
        {
          "type": "null"
        }
      ],
      "readOnly": true,
      "description": "Когда первичная загрузка магазина подтвердилась журналом сборщика. null — карточки, остатки или заказы ещё не загружены, и решения разбора и ввод начального остатка закрыты; подробности — marketplaceGetStoreInitialLoad"
    },
    "article_size_separator": {
      "type": "string",
      "enum": [
        "",
        "-",
        "/",
        "_"
      ],
      "description": "Разделитель базы и размера в артикуле продавца, объявленный владельцем магазина. Пустая строка — правило не объявлено, и размер берётся только из полей площадки. Применяется на Ozon, где каждый размер продаётся своим артикулом"
    },
    "catalog_auto_create": {
      "oneOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "description": "Новые карточки площадки без единого совпадения загрузка каталога заводит товарами сама (true) или оставляет новыми до решения человека (false). null — решение ещё не принято: первая загрузка включит автосоздание только в кабинете без активных товаров и запишет решение. Применяется к Ozon и Wildberries"
    },
    "business_id": {
      "oneOf": [
        {
          "$ref": "#/$defs/UUID"
        },
        {
          "type": "null"
        }
      ],
      "readOnly": true,
      "description": "Бизнес магазина — бизнес юрлица из учётных настроек; по нему магазин и его отчёты сужаются областью доступа участника. null — юрлицо ещё не выбрано в кабинете с несколькими бизнесами: такой магазин видит только доступ ко всем бизнесам"
    }
  },
  "$defs": {
    "MarketplaceStoreCost": {
      "type": "object",
      "readOnly": true,
      "additionalProperties": false,
      "required": [
        "source",
        "valid_from"
      ],
      "description": "Себестоимость магазина на сегодня для списка магазинов: действующая версия учётной настройки, метод оценки склада юрлица и запуск склада площадки. Поля нет — источник себестоимости не задан",
      "properties": {
        "source": {
          "type": "string",
          "enum": [
            "manual",
            "stock"
          ],
          "description": "manual — ставки в товарах маркетплейса; stock — из складского учёта"
        },
        "valid_from": {
          "type": "string",
          "format": "date",
          "description": "С какого дня действует источник"
        },
        "stock_method": {
          "type": "string",
          "enum": [
            "fifo",
            "moving_average"
          ],
          "description": "Метод оценки склада юрлица; поля нет — складская политика не настроена"
        },
        "stock_from": {
          "type": "string",
          "format": "date",
          "description": "Только у stock: с какого дня склад площадки ведётся в учёте"
        },
        "stock_opened_on": {
          "type": "string",
          "format": "date",
          "description": "Только у stock: день запуска склада площадки; поля нет — склад не запущен, недели ждут запуска"
        }
      }
    },
    "MarketplaceStoreTax": {
      "type": "object",
      "readOnly": true,
      "additionalProperties": false,
      "required": [
        "source",
        "state",
        "percent",
        "company_id"
      ],
      "description": "Налог магазина на сегодня с объяснением. Процент от выручки выводится из учётной политики только у режимов с налогом от дохода (УСН и АУСН «доходы», НПД); у ОСНО, УСН/АУСН «доходы минус расходы» и ЕСХН налог берётся с прибыли юрлица и считается в разделе «Налоги», с выручки магазина его нет",
      "properties": {
        "source": {
          "type": "string",
          "enum": [
            "policy",
            "store"
          ],
          "description": "Источник: policy — учётная политика юрлица, store — ставка магазина вручную"
        },
        "state": {
          "type": "string",
          "enum": [
            "manual",
            "policy",
            "profit_based",
            "fixed",
            "not_set",
            "no_company"
          ],
          "description": "manual — ручная ставка магазина; policy — процент из системы налогообложения юрлица; profit_based — режим юрлица берёт налог с прибыли; fixed — патент, фиксированная стоимость; not_set — у юрлица не задана система налогообложения или её ставка; no_company — у магазина не выбрано юрлицо"
        },
        "percent": {
          "type": "string",
          "description": "Процент налога с выручки на сегодня, decimal строкой"
        },
        "company_id": {
          "oneOf": [
            {
              "$ref": "#/$defs/UUID"
            },
            {
              "type": "null"
            }
          ],
          "description": "Юрлицо магазина, чья учётная политика даёт налог; null — ручная ставка или юрлицо не выбрано"
        },
        "company_name": {
          "type": "string",
          "description": "Название юрлица"
        },
        "regime": {
          "type": "string",
          "enum": [
            "osno",
            "usn_income",
            "usn_income_expense",
            "ausn_income",
            "ausn_income_expense",
            "eshn",
            "psn",
            "npd"
          ],
          "description": "Система налогообложения юрлица на сегодня"
        },
        "regime_rate": {
          "type": "string",
          "description": "Ставка системы налогообложения в процентах, как в учётной политике"
        },
        "regime_valid_from": {
          "type": "string",
          "format": "date",
          "description": "С какого дня действует система налогообложения юрлица"
        }
      }
    },
    "MarketplaceStoreWriteKey": {
      "type": "object",
      "readOnly": true,
      "additionalProperties": false,
      "required": [
        "set",
        "scopes",
        "read_only",
        "ability",
        "set_by",
        "set_at",
        "checked_at",
        "last_used_at"
      ],
      "description": "Признаки ключа магазина на запись в площадку (марки в сборочные задания FBS); сам ключ не возвращается",
      "properties": {
        "set": {
          "type": "boolean",
          "description": "Ключ задан"
        },
        "mask": {
          "type": "string",
          "description": "Последние 4 символа токена или Api-Key"
        },
        "kind": {
          "type": "string",
          "enum": [
            "basic",
            "personal",
            "test",
            "service",
            "unknown"
          ],
          "description": "Тип токена Wildberries"
        },
        "scopes": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Категории токена Wildberries"
        },
        "read_only": {
          "type": "boolean",
          "description": "Токен только на чтение"
        },
        "ability": {
          "type": "string",
          "enum": [
            "ready",
            "no_key",
            "no_write_scope",
            "unchecked"
          ],
          "description": "Можно ли передавать марки: ready — можно, no_key — ключа нет, no_write_scope — нет права записи, unchecked — не проверено"
        },
        "set_by": {
          "type": [
            "integer",
            "null"
          ],
          "format": "int64",
          "description": "Кто задал ключ"
        },
        "set_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time",
          "description": "Когда задан ключ"
        },
        "checked_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time",
          "description": "Когда ключ проверяли"
        },
        "check_result": {
          "type": "string",
          "enum": [
            "ready",
            "no_write_scope",
            "rejected",
            "unchecked",
            "unavailable"
          ],
          "description": "Итог последней проверки без записи"
        },
        "last_used_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time",
          "description": "Когда ключом последний раз передавали марки"
        },
        "last_result": {
          "type": "string",
          "enum": [
            "not_sent",
            "sent",
            "accepted",
            "rejected"
          ],
          "description": "Итог последней передачи марок"
        },
        "last_error_code": {
          "type": "string",
          "description": "Код отказа последней передачи"
        }
      }
    },
    "UUID": {
      "type": "string",
      "format": "uuid"
    }
  }
}