{
  "openapi": "3.1.0",
  "info": {
    "title": "API для интеграций",
    "version": "1.0.0",
    "description": "Публичный API платформы: ключи интеграций, области доступа, единый формат ошибок application/problem+json. Три независимые ячейки (RU, EN, ID): ключ работает только в своей ячейке."
  },
  "servers": [
    {
      "url": "https://formula-cream.pro/api/public/v1",
      "description": "Ячейка RU"
    },
    {
      "url": "https://wfacademy.org/api/public/v1",
      "description": "Ячейка EN"
    },
    {
      "url": "https://wfacademy.id/api/public/v1",
      "description": "Ячейка ID"
    }
  ],
  "tags": [
    {
      "name": "account",
      "description": "Аккаунт"
    },
    {
      "name": "conversations",
      "description": "Диалоги"
    },
    {
      "name": "analytics",
      "description": "Аналитика"
    },
    {
      "name": "dashboards",
      "description": "Дашборды"
    },
    {
      "name": "leads",
      "description": "Лиды"
    },
    {
      "name": "articles",
      "description": "Статьи"
    },
    {
      "name": "strategist",
      "description": "Стратег"
    },
    {
      "name": "webhooks",
      "description": "Вебхуки"
    },
    {
      "name": "channels",
      "description": "Каналы"
    },
    {
      "name": "cards",
      "description": "Карточки товаров"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/me": {
      "get": {
        "operationId": "getMe",
        "tags": [
          "account"
        ],
        "summary": "Кто я",
        "description": "Возвращает арендатора, интеграцию, ключ с действующими областями, пределы частоты и состояние кошелька. Областей не требует: нужен лишь действующий ключ. Удобно для проверки подключения и для выбора ячейки.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Описание ключа и аккаунта.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "service_unavailable",
          "internal_error"
        ]
      }
    },
    "/me/encryption-key": {
      "put": {
        "operationId": "putEncryptionKey",
        "tags": [
          "account"
        ],
        "summary": "Открытый ключ для формата JWE",
        "description": "Только ячейки EN и ID; на RU — 404. Регистрирует или меняет открытый ключ получателя (JWK), на который формируются значения полей с персональными данными в формате JWE (RFC 7516). Ключевую пару создаёте вы и храните закрытый ключ у себя; закрытые части JWK отклоняются. EN: ECDH-ES+A256KW (P-256, P-384, X25519) или RSA-OAEP-256 (от 2048 бит). ID: ECDH-ES+A256KW (P-384, X25519) или RSA-OAEP-256 / RSA-OAEP-384 (от 3072 бит). enc — A256GCM. Тот же ключ повторно — changed: false. Новый ключ действует сразу; прежний ещё 7 суток можно запросить заголовком Encryption-Key-Id. Регистрация переводит режим off в optional; режим required меняется только в кабинете.",
        "security": [
          {
            "bearerAuth": [
              "webhooks:manage"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Открытый ключ получателя.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PiiEncryptionKeyPut"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Настройка после регистрации.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PiiEncryptionKeyResult"
                }
              }
            }
          },
          "400": {
            "description": "Bad request. Тело запроса не JSON либо неверный Content-Type или заголовок.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Invalid state. Действие недопустимо в текущем состоянии ресурса.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "Payload too large. Тело запроса больше 256 КБ.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "write",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "not_found",
          "bad_request",
          "validation_failed",
          "payload_too_large",
          "invalid_state"
        ],
        "x-cells": [
          "en",
          "id"
        ]
      }
    },
    "/wallet": {
      "get": {
        "operationId": "getWallet",
        "tags": [
          "account"
        ],
        "summary": "Кошелёк и состояние обмена",
        "description": "Возвращает остаток кошелька арендатора, его состояние (ok, low, negative, blocked, unknown), признак остановки обмена и адрес пополнения. Областей не требует и работает даже при остановленном обмене: именно здесь видно, почему остальные маршруты отвечают 402 wallet_suspended. Остаток меньше нуля или заблокированный кошелёк останавливают обмен; после пополнения он возобновляется сам в течение 30 секунд.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Состояние кошелька.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Wallet"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "service_unavailable",
          "internal_error"
        ]
      }
    },
    "/operations/{id}": {
      "get": {
        "operationId": "getOperation",
        "tags": [
          "account"
        ],
        "summary": "Состояние операции",
        "description": "Возвращает асинхронную операцию, созданную вашей интеграцией (ответ 202 с конвертом operation): состояние queued, running, succeeded, failed или canceled, ресурс результата и стоимость для платных операций. Отдельной области маршрут не требует: нужна та же область, что и у создавшего операцию запроса (например, ai_seller:invoke для ответа ИИ-продажника). Операция другой интеграции или другого арендатора — 404. Вместо частого опроса подпишитесь на событие operation.completed.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор операции (uuid) из конверта operation."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Операция.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperationEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing, pii_transfer_not_allowed. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "pii_transfer_not_allowed",
          "not_found"
        ]
      }
    },
    "/conversations": {
      "get": {
        "operationId": "listConversations",
        "tags": [
          "conversations"
        ],
        "summary": "Список диалогов",
        "description": "Диалоги арендатора по возрастанию updated_at, постранично по курсору: чтобы забрать изменения, храните updated_at последнего увиденного и передавайте его в updated_after. Диалогов с мягким удалением нет, поэтому include_deleted сейчас ничего не добавляет. Ответ содержит персональные данные клиентов: каждая выдача записывается в журнал выдач, на RU нужны список разрешённых IP и страна получателя RU (иначе 403 pii_transfer_not_allowed). Диалоги личных ящиков и чаты кабинета ученика не отдаются. Поля с персональными данными (у диалога — external_customer_id, у сообщения — content и attachments) приходят, только если названы в fields=. На ячейках EN и ID их значения могут приходить в формате JWE (режим интеграции и заголовок Encryption-Key-Id); при режиме required без ключа — 409 encryption_key_required.",
        "security": [
          {
            "bearerAuth": [
              "conversations:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "description": "Размер страницы: от 1 до 100, по умолчанию 25.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Значение next_cursor из предыдущего ответа. Живёт 24 часа; при смене фильтров начинайте заново."
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Тип канала: api, telegram, website …"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Состояние диалога, например open."
            }
          },
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "ai",
                "operator"
              ],
              "description": "ai — ведёт ИИ, operator — ведёт человек."
            }
          },
          {
            "name": "updated_after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Диалоги, изменённые строго позже момента. ISO 8601 с поясом."
            }
          },
          {
            "name": "include_deleted",
            "in": "query",
            "required": false,
            "schema": {
              "default": false,
              "description": "Принимается для единообразия; сейчас ничего не меняет.",
              "type": "boolean"
            }
          },
          {
            "name": "fields",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 2000,
              "description": "Через запятую — какие поля вернуть (id есть всегда). Без параметра возвращаются все поля, КРОМЕ полей с персональными данными; поле с персональными данными приходит, только если названо явно: верхнее (title, content) или вложенное (contact.email, score.reason). Неизвестное имя — 422. В журнал выдач попадают только выданные поля."
            }
          },
          {
            "name": "Encryption-Key-Id",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 128,
              "description": "Только ячейки EN и ID: каким зарегистрированным ключом (kid) сформировать JWE — действующим или прежним в течение 7 суток после смены. Заданный заголовок включает формат JWE и при режиме off."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница диалогов.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationPage"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing, pii_transfer_not_allowed. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Encryption key is required. Интеграция настроена выдавать поля с персональными данными только в формате JWE (режим required), а открытый ключ получателя не зарегистрирован. Бывает только на ячейках EN и ID.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "pii_transfer_not_allowed",
          "validation_failed",
          "encryption_key_required"
        ]
      },
      "post": {
        "operationId": "createConversation",
        "tags": [
          "conversations"
        ],
        "summary": "Найти или завести диалог",
        "description": "Диалог клиента вашего канала (канал api интеграции) по внешнему идентификатору: есть активный — он же (200), нет — новый (201) и событие conversation.created. Один и тот же external_customer_id двух разных интеграций — разные клиенты. Имя, почта и телефон пишутся только в пустые поля контакта. Канал подключается в кабинете (Настройки → API); без него — 409 channel_not_configured. Повтор с тем же Idempotency-Key — тот же диалог. Ответ содержит персональные данные клиентов: каждая выдача записывается в журнал выдач, на RU нужны список разрешённых IP и страна получателя RU (иначе 403 pii_transfer_not_allowed). Диалоги личных ящиков и чаты кабинета ученика не отдаются.",
        "security": [
          {
            "bearerAuth": [
              "conversations:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "description": "Уникальная строка (обычно UUID v4), новая для каждой новой операции. Повтор с тем же ключом и телом даёт тот же результат."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Клиент вашего канала.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConversationCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Диалог (новый — 201, найденный — 200).",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          },
          "400": {
            "description": "Возможные коды: bad_request, idempotency_key_required. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing, pii_transfer_not_allowed. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Возможные коды: channel_not_configured, idempotency_conflict, operation_in_progress, invalid_state. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "Payload too large. Тело запроса больше 256 КБ.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "write",
        "x-idempotent": true,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "pii_transfer_not_allowed",
          "validation_failed",
          "bad_request",
          "payload_too_large",
          "channel_not_configured",
          "idempotency_key_required",
          "idempotency_conflict",
          "operation_in_progress",
          "invalid_state"
        ]
      }
    },
    "/conversations/{id}": {
      "get": {
        "operationId": "getConversation",
        "tags": [
          "conversations"
        ],
        "summary": "Получить диалог",
        "description": "Один диалог. Чужой, несуществующий и недоступный публичному API диалог одинаково отвечает not_found. Ответ содержит персональные данные клиентов: каждая выдача записывается в журнал выдач, на RU нужны список разрешённых IP и страна получателя RU (иначе 403 pii_transfer_not_allowed). Диалоги личных ящиков и чаты кабинета ученика не отдаются. Поля с персональными данными (у диалога — external_customer_id, у сообщения — content и attachments) приходят, только если названы в fields=. На ячейках EN и ID их значения могут приходить в формате JWE (режим интеграции и заголовок Encryption-Key-Id); при режиме required без ключа — 409 encryption_key_required.",
        "security": [
          {
            "bearerAuth": [
              "conversations:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор диалога (uuid)."
            }
          },
          {
            "name": "fields",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 2000,
              "description": "Через запятую — какие поля вернуть (id есть всегда). Без параметра возвращаются все поля, КРОМЕ полей с персональными данными; поле с персональными данными приходит, только если названо явно: верхнее (title, content) или вложенное (contact.email, score.reason). Неизвестное имя — 422. В журнал выдач попадают только выданные поля."
            }
          },
          {
            "name": "Encryption-Key-Id",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 128,
              "description": "Только ячейки EN и ID: каким зарегистрированным ключом (kid) сформировать JWE — действующим или прежним в течение 7 суток после смены. Заданный заголовок включает формат JWE и при режиме off."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Диалог.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing, pii_transfer_not_allowed. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Encryption key is required. Интеграция настроена выдавать поля с персональными данными только в формате JWE (режим required), а открытый ключ получателя не зарегистрирован. Бывает только на ячейках EN и ID.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "pii_transfer_not_allowed",
          "not_found",
          "validation_failed",
          "encryption_key_required"
        ]
      }
    },
    "/conversations/{id}/messages": {
      "get": {
        "operationId": "listConversationMessages",
        "tags": [
          "conversations"
        ],
        "summary": "Сообщения диалога",
        "description": "Сообщения диалога от старых к новым, постранично по курсору (created_at, id). Внутренние заметки операторов не отдаются. Вложения — временные подписанные ссылки; внешние адреса файлов мессенджеров не раскрываются. Ответ содержит персональные данные клиентов: каждая выдача записывается в журнал выдач, на RU нужны список разрешённых IP и страна получателя RU (иначе 403 pii_transfer_not_allowed). Диалоги личных ящиков и чаты кабинета ученика не отдаются. Поля с персональными данными (у диалога — external_customer_id, у сообщения — content и attachments) приходят, только если названы в fields=. На ячейках EN и ID их значения могут приходить в формате JWE (режим интеграции и заголовок Encryption-Key-Id); при режиме required без ключа — 409 encryption_key_required.",
        "security": [
          {
            "bearerAuth": [
              "conversations:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор диалога (uuid)."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "description": "Размер страницы: от 1 до 100, по умолчанию 25.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Значение next_cursor из предыдущего ответа. Живёт 24 часа; при смене фильтров начинайте заново."
            }
          },
          {
            "name": "include_deleted",
            "in": "query",
            "required": false,
            "schema": {
              "default": false,
              "description": "true — вернуть и удалённые сообщения как «надгробия» (deleted: true, без текста).",
              "type": "boolean"
            }
          },
          {
            "name": "fields",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 2000,
              "description": "Через запятую — какие поля вернуть (id есть всегда). Без параметра возвращаются все поля, КРОМЕ полей с персональными данными; поле с персональными данными приходит, только если названо явно: верхнее (title, content) или вложенное (contact.email, score.reason). Неизвестное имя — 422. В журнал выдач попадают только выданные поля."
            }
          },
          {
            "name": "Encryption-Key-Id",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 128,
              "description": "Только ячейки EN и ID: каким зарегистрированным ключом (kid) сформировать JWE — действующим или прежним в течение 7 суток после смены. Заданный заголовок включает формат JWE и при режиме off."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница сообщений.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessagePage"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing, pii_transfer_not_allowed. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Encryption key is required. Интеграция настроена выдавать поля с персональными данными только в формате JWE (режим required), а открытый ключ получателя не зарегистрирован. Бывает только на ячейках EN и ID.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "pii_transfer_not_allowed",
          "not_found",
          "validation_failed",
          "encryption_key_required"
        ]
      },
      "post": {
        "operationId": "createConversationMessage",
        "tags": [
          "conversations"
        ],
        "summary": "Сообщение клиента и ответ ИИ",
        "description": "Записывает сообщение клиента в диалог канала интеграции (conversations:write) и, при ai_reply=auto и области ai_seller:invoke, запускает ответ ИИ-продажника асинхронно: 202 с message_id, ai_reply.status=queued и операцией conversation.ai_reply. ?wait=N (0–20 с) ждёт ТО ЖЕ задание: успело — 200 с итогом (ai_reply, reply.id, operation.usage.cost в валюте кошелька), нет — 202. Без ai_seller:invoke или с ai_reply=none — 201, ai_reply.status=skipped, reason=not_requested, ИИ не вызывается и ничего не списывается. Текста ответа ИИ здесь нет — читайте GET /conversations/{id}/messages или ждите message.created. Повтор того же Idempotency-Key во время выполнения — тот же 202, после — итог; повторно сообщение не пишется и не оплачивается. Платная часть: не больше 5 одновременных операций на интеграцию (429 concurrency_limit), максимум стоимости одной операции и суточный предел интеграции (402 spend_limit_reached) — проверяются до записи, отказ ничего не записывает и освобождает Idempotency-Key. Диалог другого канала или арендатора — 404, закрытый — 409 invalid_state.",
        "security": [
          {
            "bearerAuth": [
              "conversations:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор диалога (uuid)."
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "description": "Уникальная строка (обычно UUID v4), новая для каждой новой операции. Повтор с тем же ключом и телом даёт тот же результат."
            }
          },
          {
            "name": "wait",
            "in": "query",
            "required": false,
            "schema": {
              "default": 0,
              "description": "Секунды ожидания ответа ИИ, 0–20. Не входит в ключ идемпотентности.",
              "type": "integer",
              "minimum": 0,
              "maximum": 20
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Сообщение клиента.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MessageCreate"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Принято; ответ ИИ готовится (202), готов в пределах wait (200) или не запрашивался (201).",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageAccepted"
                }
              }
            }
          },
          "400": {
            "description": "Возможные коды: bad_request, idempotency_key_required. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Возможные коды: wallet_suspended, spend_limit_reached. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing, pii_transfer_not_allowed. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Возможные коды: channel_not_configured, invalid_state, idempotency_conflict, operation_in_progress. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "Payload too large. Тело запроса больше 256 КБ.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Возможные коды: rate_limited, concurrency_limit. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Возможные коды: service_unavailable, upstream_unavailable. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "write",
        "x-idempotent": true,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "pii_transfer_not_allowed",
          "validation_failed",
          "bad_request",
          "payload_too_large",
          "not_found",
          "channel_not_configured",
          "invalid_state",
          "idempotency_key_required",
          "idempotency_conflict",
          "operation_in_progress",
          "concurrency_limit",
          "spend_limit_reached",
          "upstream_unavailable"
        ]
      }
    },
    "/analytics/timeseries": {
      "get": {
        "operationId": "getAnalyticsTimeseries",
        "tags": [
          "analytics"
        ],
        "summary": "Временные ряды",
        "description": "Ряды от одной до восьми метрик по дням или неделям с итогом и сравнением с предыдущим периодом. Каждый ряд несёт свою доступность и дату полноты данных; дни без данных заполнены нулями.",
        "security": [
          {
            "bearerAuth": [
              "analytics:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "metric",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "От 1 до 8 уникальных метрик через запятую: sessions, pageviews, visitors, bounce_rate, impressions, clicks, ctr, position, ai_referrals, bot_hits, leads, deals_won, revenue."
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Начало периода, включительно. Формат YYYY-MM-DD.",
              "example": "2026-09-01"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Конец периода, включительно; не позже последних полных суток (позднее значение обрезается и возвращается в ответе). Формат YYYY-MM-DD.",
              "example": "2026-09-30"
            }
          },
          {
            "name": "granularity",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "day",
                "week"
              ],
              "description": "Шаг ряда; по умолчанию day."
            }
          },
          {
            "name": "engine",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "google",
                "yandex",
                "bing"
              ],
              "description": "Поисковик для impressions, clicks, ctr, position; по умолчанию поисковик рынка ячейки."
            }
          },
          {
            "name": "cluster",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
              "description": "Идентификатор кластера запросов; чужой или несуществующий даёт not_found."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Один ряд либо items в порядке запроса.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TimeseriesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "validation_failed",
          "not_found"
        ]
      }
    },
    "/analytics/traffic-sources": {
      "get": {
        "operationId": "getAnalyticsTrafficSources",
        "tags": [
          "analytics"
        ],
        "summary": "Источники трафика",
        "description": "Источники первого визита за период: сессии, посетители и лиды. Только агрегаты по дню и источнику; строк визитов, IP и хешей нет.",
        "security": [
          {
            "bearerAuth": [
              "analytics:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Начало периода, включительно. Формат YYYY-MM-DD.",
              "example": "2026-09-01"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Конец периода, включительно; не позже последних полных суток (позднее значение обрезается и возвращается в ответе). Формат YYYY-MM-DD.",
              "example": "2026-09-30"
            }
          },
          {
            "name": "include",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "series"
              ],
              "description": "series добавляет ряд по дням в каждый источник."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Источники, больше сессий первыми.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrafficSourcesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "validation_failed"
        ]
      }
    },
    "/analytics/funnel": {
      "get": {
        "operationId": "getAnalyticsFunnel",
        "tags": [
          "analytics"
        ],
        "summary": "Воронка",
        "description": "Путь от показов в поиске до выручки: ступени со своей доступностью и датой, каналы и продукты. Расчёт общий с кабинетом. engine=both показывает движки раздельно и не складывает их.",
        "security": [
          {
            "bearerAuth": [
              "analytics:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Начало периода, включительно. Формат YYYY-MM-DD.",
              "example": "2026-09-01"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Конец периода, включительно; не позже последних полных суток (позднее значение обрезается и возвращается в ответе). Формат YYYY-MM-DD.",
              "example": "2026-09-30"
            }
          },
          {
            "name": "engine",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "yandex",
                "google",
                "both"
              ],
              "description": "По умолчанию поисковик рынка; both доступен не на всех рынках."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Воронка периода.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FunnelResponse"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "validation_failed"
        ]
      }
    },
    "/analytics/visibility": {
      "get": {
        "operationId": "getAnalyticsVisibility",
        "tags": [
          "analytics"
        ],
        "summary": "Видимость",
        "description": "Доля видимости, распределение позиций, доля голоса (всегда без имён конкурентов), цитирование в ИИ и регионы. Каждый раздел самостоятелен: своя доступность, источник и дата.",
        "security": [
          {
            "bearerAuth": [
              "analytics:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Начало периода, включительно. Формат YYYY-MM-DD.",
              "example": "2026-09-01"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Конец периода, включительно; не позже последних полных суток (позднее значение обрезается и возвращается в ответе). Формат YYYY-MM-DD.",
              "example": "2026-09-30"
            }
          },
          {
            "name": "compare",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Добавить сравнение с предыдущим периодом; по умолчанию false."
            }
          },
          {
            "name": "engine",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "yandex",
                "google",
                "both"
              ],
              "description": "По умолчанию поисковик рынка."
            }
          },
          {
            "name": "cluster",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
              "description": "Идентификатор кластера запросов; чужой или несуществующий даёт not_found."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Пять разделов видимости.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VisibilityResponse"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "validation_failed",
          "not_found"
        ]
      }
    },
    "/dashboards/overview": {
      "get": {
        "operationId": "getDashboardOverview",
        "tags": [
          "dashboards"
        ],
        "summary": "Дашборд «Обзор»",
        "description": "Срез экрана «Обзор»: до одиннадцати блоков, каждый со своей доступностью (ok, no_data, no_source, not_connected) и датой данных. Сбой одного источника не превращается в пустой блок: ответ 503.",
        "security": [
          {
            "bearerAuth": [
              "dashboards:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Начало периода, включительно. Формат YYYY-MM-DD.",
              "example": "2026-09-01"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Конец периода, включительно; не позже последних полных суток (позднее значение обрезается и возвращается в ответе). Формат YYYY-MM-DD.",
              "example": "2026-09-30"
            }
          },
          {
            "name": "blocks",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Блоки через запятую; по умолчанию все: strategist, kpi, funnel, attention, ads, ai_assistants, popular_pages, clusters, data_trust, sitemap_health, status."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Запрошенные блоки в порядке экрана.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OverviewResponse"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "validation_failed"
        ]
      }
    },
    "/dashboards/pulse": {
      "get": {
        "operationId": "getDashboardPulse",
        "tags": [
          "dashboards"
        ],
        "summary": "Дашборд «Пульс»",
        "description": "Находки «Пульса»: темы спроса, которые начали расти, с источниками сигнала и связанной темой очереди стратега.",
        "security": [
          {
            "bearerAuth": [
              "dashboards:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Начало периода, включительно. Формат YYYY-MM-DD.",
              "example": "2026-09-01"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Конец периода, включительно; не позже последних полных суток (позднее значение обрезается и возвращается в ответе). Формат YYYY-MM-DD.",
              "example": "2026-09-30"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Находки периода.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PulseResponse"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "validation_failed"
        ]
      }
    },
    "/leads": {
      "get": {
        "operationId": "listLeads",
        "tags": [
          "leads"
        ],
        "summary": "Список лидов",
        "description": "Лиды арендатора по возрастанию updated_at, постранично по курсору. По умолчанию архивные лиды не возвращаются. include_deleted=true пока даёт 422 not_supported: удалённые лиды (tombstones) не хранятся. Поля с персональными данными (contact.first_name, contact.last_name, contact.email, contact.phone, contact.geo_country, contact.geo_city, title, intent, ai_summary, score.reason, next_action, lost_reason) приходят, только если названы в fields=; каждая выдача записывается в журнал выдач, на RU нужны разрешённые адреса и страна получателя RU (иначе 403 pii_transfer_not_allowed). На ячейках EN и ID значения этих полей могут приходить в формате JWE (режим интеграции и заголовок Encryption-Key-Id); при режиме required без ключа — 409 encryption_key_required.",
        "security": [
          {
            "bearerAuth": [
              "leads:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "description": "Размер страницы: от 1 до 100, по умолчанию 25.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Значение next_cursor из предыдущего ответа. Живёт 24 часа; при смене фильтров начинайте заново."
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "new",
                "qualified",
                "proposal",
                "negotiation",
                "won",
                "lost"
              ],
              "description": "Канонический статус."
            }
          },
          {
            "name": "archived",
            "in": "query",
            "required": false,
            "schema": {
              "default": false,
              "description": "true — только архивные; по умолчанию false — только неархивные.",
              "type": "boolean"
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Лиды, изменённые не раньше этого момента (включительно). ISO 8601: дата или дата-время с поясом."
            }
          },
          {
            "name": "updated_after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "То же, но строго позже момента (для обхода «с последнего увиденного»). Нельзя вместе с updated_since."
            }
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 100,
              "description": "Точное значение источника лида."
            }
          },
          {
            "name": "include_deleted",
            "in": "query",
            "required": false,
            "schema": {
              "default": false,
              "description": "true — вернуть также «надгробия» удалённых записей {id, deleted_at} (хранятся 30 суток).",
              "type": "boolean"
            }
          },
          {
            "name": "fields",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 2000,
              "description": "Через запятую — какие поля вернуть (id есть всегда). Без параметра возвращаются все поля, КРОМЕ полей с персональными данными; поле с персональными данными приходит, только если названо явно: верхнее (title, content) или вложенное (contact.email, score.reason). Неизвестное имя — 422. В журнал выдач попадают только выданные поля."
            }
          },
          {
            "name": "Encryption-Key-Id",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 128,
              "description": "Только ячейки EN и ID: каким зарегистрированным ключом (kid) сформировать JWE — действующим или прежним в течение 7 суток после смены. Заданный заголовок включает формат JWE и при режиме off."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница лидов.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadPage"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing, pii_transfer_not_allowed. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Encryption key is required. Интеграция настроена выдавать поля с персональными данными только в формате JWE (режим required), а открытый ключ получателя не зарегистрирован. Бывает только на ячейках EN и ID.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "pii_transfer_not_allowed",
          "validation_failed",
          "encryption_key_required"
        ]
      }
    },
    "/leads/{id}": {
      "get": {
        "operationId": "getLead",
        "tags": [
          "leads"
        ],
        "summary": "Получить лид",
        "description": "Карточка лида: контакт, атрибуция, оценка (балл, класс A–D, причина, флаги), версия. Заголовок ETag равен полю etag. Поля с персональными данными (contact.first_name, contact.last_name, contact.email, contact.phone, contact.geo_country, contact.geo_city, title, intent, ai_summary, score.reason, next_action, lost_reason) приходят, только если названы в fields=; каждая выдача записывается в журнал выдач, на RU нужны разрешённые адреса и страна получателя RU (иначе 403 pii_transfer_not_allowed). На ячейках EN и ID значения этих полей могут приходить в формате JWE (режим интеграции и заголовок Encryption-Key-Id); при режиме required без ключа — 409 encryption_key_required.",
        "security": [
          {
            "bearerAuth": [
              "leads:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор лида (uuid)."
            }
          },
          {
            "name": "fields",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 2000,
              "description": "Через запятую — какие поля вернуть (id есть всегда). Без параметра возвращаются все поля, КРОМЕ полей с персональными данными; поле с персональными данными приходит, только если названо явно: верхнее (title, content) или вложенное (contact.email, score.reason). Неизвестное имя — 422. В журнал выдач попадают только выданные поля."
            }
          },
          {
            "name": "Encryption-Key-Id",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 128,
              "description": "Только ячейки EN и ID: каким зарегистрированным ключом (kid) сформировать JWE — действующим или прежним в течение 7 суток после смены. Заданный заголовок включает формат JWE и при режиме off."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Лид.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Lead"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing, pii_transfer_not_allowed. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Encryption key is required. Интеграция настроена выдавать поля с персональными данными только в формате JWE (режим required), а открытый ключ получателя не зарегистрирован. Бывает только на ячейках EN и ID.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "pii_transfer_not_allowed",
          "not_found",
          "validation_failed",
          "encryption_key_required"
        ]
      }
    },
    "/articles": {
      "get": {
        "operationId": "listArticles",
        "tags": [
          "articles"
        ],
        "summary": "Список статей",
        "description": "Статьи вашего арендатора (раздел SEO) без содержимого, по убыванию updated_at. Статьи общего блога площадки сюда не входят. include_deleted=true даёт 422 not_supported: удалённые статьи не хранятся.",
        "security": [
          {
            "bearerAuth": [
              "articles:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "description": "Размер страницы: от 1 до 100, по умолчанию 25.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Значение next_cursor из предыдущего ответа. Живёт 24 часа; при смене фильтров начинайте заново."
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "review",
                "approved",
                "published",
                "rejected",
                "transferred",
                "external"
              ],
              "description": "Статус статьи."
            }
          },
          {
            "name": "updated_after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Только статьи, изменённые строго позже момента. ISO 8601: дата или дата-время."
            }
          },
          {
            "name": "include_deleted",
            "in": "query",
            "required": false,
            "schema": {
              "default": false,
              "description": "true — вернуть также «надгробия» удалённых записей {id, deleted_at} (хранятся 30 суток).",
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница статей.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArticlePage"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "validation_failed"
        ]
      }
    },
    "/articles/{id}": {
      "get": {
        "operationId": "getArticle",
        "tags": [
          "articles"
        ],
        "summary": "Получить статью",
        "description": "Статья с содержимым в формате html (по умолчанию), markdown или blocks и состоянием выкладки (publication). HTML очищен от скриптов; тело больше 2 000 000 байт даёт 422.",
        "security": [
          {
            "bearerAuth": [
              "articles:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор статьи."
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "default": "html",
              "description": "Формат содержимого.",
              "type": "string",
              "enum": [
                "html",
                "markdown",
                "blocks"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Статья.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Article"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "not_found",
          "validation_failed"
        ]
      }
    },
    "/strategist/reports": {
      "get": {
        "operationId": "listStrategistReports",
        "tags": [
          "strategist"
        ],
        "summary": "Список отчётов стратега",
        "description": "Шапки ежедневных и недельных отчётов, новые первыми; в каждой есть data_as_of — актуальность данных. Креативные прогоны не возвращаются.",
        "security": [
          {
            "bearerAuth": [
              "strategist:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "description": "Размер страницы: от 1 до 100, по умолчанию 25.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Значение next_cursor из предыдущего ответа. Живёт 24 часа; при смене фильтров начинайте заново."
            }
          },
          {
            "name": "report_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "daily",
                "weekly"
              ],
              "description": "Вид отчёта."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница отчётов.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StrategistReportPage"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "validation_failed"
        ]
      }
    },
    "/strategist/reports/{id}": {
      "get": {
        "operationId": "getStrategistReport",
        "tags": [
          "strategist"
        ],
        "summary": "Получить отчёт стратега",
        "description": "Отчёт целиком: выводы, действия с обоснованием и доказательства. Названия конкурентов скрыты; снимок аналитики, модель и стоимость не отдаются.",
        "security": [
          {
            "bearerAuth": [
              "strategist:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор отчёта."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Отчёт.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StrategistReport"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "not_found"
        ]
      }
    },
    "/strategist/topics": {
      "get": {
        "operationId": "listStrategistTopics",
        "tags": [
          "strategist"
        ],
        "summary": "Очередь тем",
        "description": "Темы статей, предложенные стратегом, по убыванию оценки тренда. include_deleted=true даёт 422 not_supported: удалённые темы не хранятся.",
        "security": [
          {
            "bearerAuth": [
              "strategist:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "description": "Размер страницы: от 1 до 100, по умолчанию 25.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Значение next_cursor из предыдущего ответа. Живёт 24 часа; при смене фильтров начинайте заново."
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "proposed",
                "approved",
                "generating",
                "generated",
                "rejected",
                "duplicate",
                "expired"
              ],
              "description": "Состояние темы."
            }
          },
          {
            "name": "include_deleted",
            "in": "query",
            "required": false,
            "schema": {
              "default": false,
              "description": "true — вернуть также «надгробия» удалённых записей {id, deleted_at} (хранятся 30 суток).",
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница тем.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StrategistTopicPage"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "validation_failed"
        ]
      }
    },
    "/strategist/topics/{id}": {
      "get": {
        "operationId": "getStrategistTopic",
        "tags": [
          "strategist"
        ],
        "summary": "Получить тему",
        "description": "Тема очереди. Если по теме создана статья, её идентификатор в generated_article_id.",
        "security": [
          {
            "bearerAuth": [
              "strategist:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор темы."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Тема.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StrategistTopic"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "not_found"
        ]
      }
    },
    "/strategist/actions": {
      "get": {
        "operationId": "listStrategistActions",
        "tags": [
          "strategist"
        ],
        "summary": "Действия стратега из ваших сессий",
        "description": "Действия, которые стратег предложил в сессиях ЭТОЙ интеграции, новые первыми. Действия сотрудников в кабинете и других интеграций не видны. Предложение живёт 7 суток, затем получает состояние expired.",
        "security": [
          {
            "bearerAuth": [
              "strategist:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "description": "Размер страницы: от 1 до 100, по умолчанию 25.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Значение next_cursor из предыдущего ответа. Живёт 24 часа; при смене фильтров начинайте заново."
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "proposed",
                "confirmed",
                "executed",
                "failed",
                "cancelled",
                "expired"
              ],
              "description": "Состояние действия."
            }
          },
          {
            "name": "session_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Только действия этой сессии (uuid)."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница действий.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StrategistActionPage"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "validation_failed"
        ]
      }
    },
    "/strategist/actions/{id}": {
      "get": {
        "operationId": "getStrategistAction",
        "tags": [
          "strategist"
        ],
        "summary": "Получить действие стратега",
        "description": "Действие из вашей сессии: состояние, результат (созданная тема) или причина сбоя. Чужое действие — 404.",
        "security": [
          {
            "bearerAuth": [
              "strategist:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор действия."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Действие.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StrategistAction"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "not_found"
        ]
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "tags": [
          "webhooks"
        ],
        "summary": "Список подписок",
        "description": "Подписки этой интеграции (не больше 10).",
        "security": [
          {
            "bearerAuth": [
              "webhooks:manage"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Страница подписок.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookPage"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing"
        ]
      },
      "post": {
        "operationId": "createWebhook",
        "tags": [
          "webhooks"
        ],
        "summary": "Создать подписку",
        "description": "Создаёт подписку на события. Секрета подписки нет: каждую доставку подписывает ключ платформы (JWS EdDSA с отделённой нагрузкой; заголовки Webhook-Event-Id, Webhook-Timestamp, Webhook-Signature), проверка — открытым ключом из GET /.well-known/jwks.json. Адрес проверяется защитой от SSRF; include_pii: true разрешён только для событий lead.*, contact.*, conversation.*.",
        "security": [
          {
            "bearerAuth": [
              "webhooks:manage"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "description": "Уникальная строка (обычно UUID v4), новая для каждой новой операции. Повтор с тем же ключом и телом даёт тот же результат."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Параметры подписки.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Подписка.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "description": "Возможные коды: bad_request, idempotency_key_required. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing, pii_transfer_not_allowed. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Возможные коды: idempotency_conflict, operation_in_progress, invalid_state. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "Payload too large. Тело запроса больше 256 КБ.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "write",
        "x-idempotent": true,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "pii_transfer_not_allowed",
          "bad_request",
          "validation_failed",
          "payload_too_large",
          "idempotency_key_required",
          "idempotency_conflict",
          "operation_in_progress",
          "invalid_state"
        ]
      }
    },
    "/webhooks/{id}": {
      "get": {
        "operationId": "getWebhook",
        "tags": [
          "webhooks"
        ],
        "summary": "Получить подписку",
        "description": "Подписка.",
        "security": [
          {
            "bearerAuth": [
              "webhooks:manage"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор подписки."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Подписка.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "not_found"
        ]
      },
      "patch": {
        "operationId": "updateWebhook",
        "tags": [
          "webhooks"
        ],
        "summary": "Изменить подписку",
        "description": "Меняет адрес, события, пометку, статус (active или paused) и include_pii. Передайте хотя бы одно поле.",
        "security": [
          {
            "bearerAuth": [
              "webhooks:manage"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор подписки."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Изменяемые поля.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Подписка после правки.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "description": "Bad request. Тело запроса не JSON либо неверный Content-Type или заголовок.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing, pii_transfer_not_allowed. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "Payload too large. Тело запроса больше 256 КБ.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "write",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "pii_transfer_not_allowed",
          "not_found",
          "bad_request",
          "validation_failed",
          "payload_too_large"
        ]
      },
      "delete": {
        "operationId": "deleteWebhook",
        "tags": [
          "webhooks"
        ],
        "summary": "Удалить подписку",
        "description": "Удаляет подписку вместе с журналом доставок. Повторное удаление вернёт not_found.",
        "security": [
          {
            "bearerAuth": [
              "webhooks:manage"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор подписки."
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Подписка удалена; тела нет.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "write",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "not_found"
        ]
      }
    },
    "/webhooks/{id}/test": {
      "post": {
        "operationId": "testWebhook",
        "tags": [
          "webhooks"
        ],
        "summary": "Тестовая доставка",
        "description": "Ставит в очередь событие webhook.test (livemode: false) только для этой подписки; подписано так же, как боевые события. Подписка должна быть active.",
        "security": [
          {
            "bearerAuth": [
              "webhooks:manage"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор подписки."
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "description": "Уникальная строка (обычно UUID v4), новая для каждой новой операции. Повтор с тем же ключом и телом даёт тот же результат."
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Событие поставлено в очередь.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookTestResult"
                }
              }
            }
          },
          "400": {
            "description": "Idempotency-Key header is required. Для этого запроса обязателен заголовок Idempotency-Key.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Возможные коды: invalid_state, idempotency_conflict, operation_in_progress. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "write",
        "x-idempotent": true,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "not_found",
          "invalid_state",
          "idempotency_key_required",
          "idempotency_conflict",
          "operation_in_progress"
        ]
      }
    },
    "/webhooks/{id}/deliveries": {
      "get": {
        "operationId": "listWebhookDeliveries",
        "tags": [
          "webhooks"
        ],
        "summary": "Журнал доставок",
        "description": "Попытки доставки подписки, новые первыми; хранятся 30 суток.",
        "security": [
          {
            "bearerAuth": [
              "webhooks:manage"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор подписки."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "description": "Размер страницы: от 1 до 100, по умолчанию 25.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Значение next_cursor из предыдущего ответа. Живёт 24 часа; при смене фильтров начинайте заново."
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "delivered",
                "failed",
                "dead"
              ],
              "description": "Фильтр по состоянию доставки."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница журнала.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryPage"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "not_found",
          "validation_failed"
        ]
      }
    },
    "/.well-known/jwks.json": {
      "get": {
        "operationId": "getWebhookJwks",
        "tags": [
          "webhooks"
        ],
        "summary": "Открытые ключи подписи вебхуков",
        "description": "Набор открытых ключей (JWKS) ячейки, которыми проверяется заголовок Webhook-Signature. Без авторизации, можно кэшировать (Cache-Control: max-age=300); встретив незнакомый kid — перечитайте набор. Подписываемая нагрузка — строка \"<Webhook-Event-Id>.<Webhook-Timestamp>.<тело запроса>\"; подпись — компактный JWS с пустой средней частью (RFC 7515, приложение F). Отбрасывайте доставки с Webhook-Timestamp старше 5 минут.",
        "security": [],
        "responses": {
          "200": {
            "description": "Набор ключей.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookJwks"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "service_unavailable",
          "internal_error"
        ]
      }
    },
    "/channels/{id}/widget": {
      "get": {
        "operationId": "getChannelWidget",
        "tags": [
          "channels"
        ],
        "summary": "Настройки чат-виджета",
        "description": "Оформление чат-виджета канала web_chat вашего аккаунта: ассистент, ожидание оператора, подпись, файлы посетителя, цвет и прочее. Канал другого типа или чужой — not_found.",
        "security": [
          {
            "bearerAuth": [
              "channels:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор канала web_chat."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Настройки виджета.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelWidget"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "not_found"
        ]
      },
      "patch": {
        "operationId": "updateChannelWidget",
        "tags": [
          "channels"
        ],
        "summary": "Изменить настройки чат-виджета",
        "description": "Та же проверка, что в кабинете: цвет #rrggbb, адреса картинок только https:// или путь вашего сайта, длины полей; ошибка — validation_failed с полями. Правка записывается в журнал аудита.",
        "security": [
          {
            "bearerAuth": [
              "channels:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор канала web_chat."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Изменяемые поля.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChannelWidgetUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Настройки после правки.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelWidget"
                }
              }
            }
          },
          "400": {
            "description": "Bad request. Тело запроса не JSON либо неверный Content-Type или заголовок.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "Payload too large. Тело запроса больше 256 КБ.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "write",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "not_found",
          "bad_request",
          "validation_failed",
          "payload_too_large"
        ]
      }
    },
    "/cards": {
      "get": {
        "operationId": "listCards",
        "tags": [
          "cards"
        ],
        "summary": "Список карточек",
        "description": "Карточки товаров аккаунта в порядке sort, затем создания. ai_enabled=true|false — только доступные (или недоступные) ИИ-продажнику.",
        "security": [
          {
            "bearerAuth": [
              "cards:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 50,
              "description": "Размер страницы, 1–100, по умолчанию 50.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Значение next_cursor из предыдущего ответа. Живёт 24 часа; при смене фильтров начинайте заново."
            }
          },
          {
            "name": "ai_enabled",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Фильтр по доступности ИИ-продажнику."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница карточек.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CardPage"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "validation_failed"
        ]
      },
      "post": {
        "operationId": "createCard",
        "tags": [
          "cards"
        ],
        "summary": "Создать карточку",
        "description": "Создаёт товар с карточкой. Код занят — validation_failed на /code. Адреса — только https:// или путь вашего сайта («/…»): javascript:, data:, http: и чужой путь хранилища отвергаются (validation_failed).",
        "security": [
          {
            "bearerAuth": [
              "cards:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "description": "Уникальная строка (обычно UUID v4), новая для каждой новой операции. Повтор с тем же ключом и телом даёт тот же результат."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Карточка.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CardCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Карточка.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Card"
                }
              }
            }
          },
          "400": {
            "description": "Возможные коды: bad_request, idempotency_key_required. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Возможные коды: idempotency_conflict, operation_in_progress. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "Payload too large. Тело запроса больше 256 КБ.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "write",
        "x-idempotent": true,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "bad_request",
          "validation_failed",
          "payload_too_large",
          "idempotency_key_required",
          "idempotency_conflict",
          "operation_in_progress"
        ]
      }
    },
    "/cards/{code}": {
      "get": {
        "operationId": "getCard",
        "tags": [
          "cards"
        ],
        "summary": "Получить карточку",
        "description": "Карточка по коду. Чужая или несуществующая — not_found.",
        "security": [
          {
            "bearerAuth": [
              "cards:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Код карточки."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Карточка.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Card"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "read",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "not_found"
        ]
      },
      "patch": {
        "operationId": "updateCard",
        "tags": [
          "cards"
        ],
        "summary": "Изменить карточку",
        "description": "Меняет переданные поля; передайте хотя бы одно. Уже отправленные сообщения не меняются — в них копия карточки. Адреса — только https:// или путь вашего сайта («/…»): javascript:, data:, http: и чужой путь хранилища отвергаются (validation_failed).",
        "security": [
          {
            "bearerAuth": [
              "cards:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Код карточки."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Изменяемые поля.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CardUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Карточка после правки.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Card"
                }
              }
            }
          },
          "400": {
            "description": "Bad request. Тело запроса не JSON либо неверный Content-Type или заголовок.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "Payload too large. Тело запроса больше 256 КБ.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "write",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "not_found",
          "bad_request",
          "validation_failed",
          "payload_too_large"
        ]
      },
      "delete": {
        "operationId": "deleteCard",
        "tags": [
          "cards"
        ],
        "summary": "Удалить карточку",
        "description": "Снимает карточку с товара (код, картинка, кнопки, доступ продажнику); сам товар остаётся. Повтор — not_found.",
        "security": [
          {
            "bearerAuth": [
              "cards:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Код карточки."
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Карточка снята; тела нет.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "write",
        "x-idempotent": false,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "not_found"
        ]
      }
    },
    "/conversations/{id}/cards": {
      "post": {
        "operationId": "sendConversationCards",
        "tags": [
          "cards"
        ],
        "summary": "Отправить карточки в диалог",
        "description": "Сообщение оператора с карточками (копия на момент отправки, адреса развёрнуты). Канал интеграции получает событие message.created; виджет сайта показывает карточки; Telegram, VK и Max — своим форматом; прочие каналы — текстом. Неизвестный или неактивный код — validation_failed на /codes. Диалог другого арендатора, кабинета ученика или личного ящика — not_found. Повтор того же Idempotency-Key — то же сообщение.",
        "security": [
          {
            "bearerAuth": [
              "conversations:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор диалога."
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "description": "Уникальная строка (обычно UUID v4), новая для каждой новой операции. Повтор с тем же ключом и телом даёт тот же результат."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Коды карточек и комментарий.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CardSend"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Сообщение записано.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CardSendResult"
                }
              }
            }
          },
          "400": {
            "description": "Возможные коды: bad_request, idempotency_key_required. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Возможные коды: invalid_api_key, wrong_cell, integration_inactive. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "Wallet is suspended. Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Возможные коды: tenant_inactive, ip_not_allowed, feature_not_in_plan, scope_missing, pii_transfer_not_allowed. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not found. Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Возможные коды: idempotency_conflict, operation_in_progress. Подробности: /developers/errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "Payload too large. Тело запроса больше 256 КБ.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed. Параметры не прошли проверку; подробности в errors[].",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Превышен предел частоты запросов.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable. Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-rate-class": "write",
        "x-idempotent": true,
        "x-status": "available",
        "x-error-codes": [
          "invalid_api_key",
          "wrong_cell",
          "integration_inactive",
          "tenant_inactive",
          "ip_not_allowed",
          "feature_not_in_plan",
          "rate_limited",
          "wallet_suspended",
          "service_unavailable",
          "internal_error",
          "scope_missing",
          "pii_transfer_not_allowed",
          "not_found",
          "bad_request",
          "validation_failed",
          "payload_too_large",
          "idempotency_key_required",
          "idempotency_conflict",
          "operation_in_progress"
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Ключ интеграции: Authorization: Bearer <ключ>. Имена областей справа — права, которые нужны маршруту."
      }
    },
    "headers": {
      "XRequestId": {
        "description": "Идентификатор запроса; указывайте его при обращении в поддержку.",
        "schema": {
          "type": "string"
        }
      }
    },
    "schemas": {
      "Money": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "string",
            "description": "Сумма СТРОКОЙ (не число с плавающей точкой), например \"123.45\"."
          },
          "currency": {
            "type": "string",
            "description": "Код валюты ISO 4217: RUB (RU), GBP (EN), IDR (ID)."
          }
        },
        "required": [
          "amount",
          "currency"
        ],
        "description": "Денежная сумма."
      },
      "FieldError": {
        "type": "object",
        "properties": {
          "field": {
            "type": "string",
            "description": "Путь к полю запроса в формате JSON Pointer (RFC 6901): \"/limit\", \"/events/0\"."
          },
          "code": {
            "type": "string",
            "description": "Машинный код причины: out_of_range, required, invalid_format…"
          },
          "message": {
            "type": "string",
            "description": "Пояснение для человека."
          }
        },
        "required": [
          "field",
          "code",
          "message"
        ],
        "description": "Ошибка проверки одного поля."
      },
      "Problem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "Ссылка на описание кода: https://<домен ячейки>/developers/errors#<code>."
          },
          "title": {
            "type": "string",
            "description": "Краткое название, одинаковое для кода."
          },
          "status": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "HTTP-статус."
          },
          "code": {
            "type": "string",
            "enum": [
              "invalid_api_key",
              "wrong_cell",
              "integration_inactive",
              "tenant_inactive",
              "scope_missing",
              "ip_not_allowed",
              "feature_not_in_plan",
              "pii_transfer_not_allowed",
              "not_found",
              "method_not_allowed",
              "bad_request",
              "idempotency_key_required",
              "idempotency_conflict",
              "operation_in_progress",
              "invalid_state",
              "channel_not_configured",
              "encryption_key_required",
              "precondition_failed",
              "precondition_required",
              "payload_too_large",
              "validation_failed",
              "rate_limited",
              "concurrency_limit",
              "spend_limit_reached",
              "insufficient_funds",
              "wallet_suspended",
              "internal_error",
              "service_unavailable",
              "upstream_unavailable"
            ],
            "description": "Стабильный машинный код. Ветвите логику по нему, а не по тексту."
          },
          "detail": {
            "type": "string",
            "description": "Пояснение к конкретному случаю. Не разбирайте этот текст."
          },
          "request_id": {
            "type": "string",
            "description": "Идентификатор запроса (совпадает с заголовком X-Request-Id). Указывайте при обращении в поддержку."
          },
          "errors": {
            "description": "Ошибки по полям (только validation_failed).",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FieldError"
            }
          },
          "correct_base_url": {
            "description": "Только wrong_cell: базовый адрес ячейки, где выпущен ключ.",
            "type": "string"
          },
          "topup_url": {
            "description": "Только wallet_suspended: адрес кабинета, где пополняется кошелёк.",
            "type": "string"
          },
          "balance": {
            "description": "Только wallet_suspended: остаток кошелька на момент отказа.",
            "anyOf": [
              {
                "$ref": "#/components/schemas/Money"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "code",
          "detail",
          "request_id"
        ],
        "description": "Ошибка в формате application/problem+json (RFC 9457)."
      },
      "Usage": {
        "type": "object",
        "properties": {
          "cost": {
            "$ref": "#/components/schemas/Money"
          },
          "model": {
            "type": "string",
            "description": "Модель, выполнившая операцию."
          }
        },
        "required": [
          "cost",
          "model"
        ],
        "description": "Стоимость платной операции."
      },
      "Operation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор операции."
          },
          "type": {
            "type": "string",
            "description": "Вид операции, например \"article.generation\"."
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "succeeded",
              "failed",
              "canceled"
            ],
            "description": "Состояние операции."
          },
          "created_at": {
            "type": "string",
            "description": "Время создания, ISO 8601 UTC."
          },
          "completed_at": {
            "description": "Время завершения; только для succeeded, failed, canceled.",
            "type": "string"
          },
          "resource": {
            "description": "Ресурс, к которому относится операция; по нему читают результат.",
            "type": "object",
            "properties": {
              "type": {
                "type": "string"
              },
              "id": {
                "type": "string"
              }
            },
            "required": [
              "type",
              "id"
            ]
          },
          "error": {
            "description": "Только для failed: код из каталога ошибок или код причины операции.",
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ]
          },
          "usage": {
            "description": "Только для платных операций.",
            "$ref": "#/components/schemas/Usage"
          }
        },
        "required": [
          "id",
          "type",
          "status",
          "created_at"
        ],
        "description": "Асинхронная операция (единый конверт для всех модулей)."
      },
      "OperationEnvelope": {
        "type": "object",
        "properties": {
          "operation": {
            "$ref": "#/components/schemas/Operation"
          }
        },
        "required": [
          "operation"
        ],
        "description": "Ответ 202 на создающий запрос."
      },
      "PiiEncryption": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "off",
              "optional",
              "required"
            ],
            "description": "off — поля с персональными данными выдаются как есть; optional — в формате JWE, если ключ зарегистрирован; required — только в формате JWE (без ключа — 409 encryption_key_required). Режим меняется в кабинете."
          },
          "key": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "kid": {
                    "type": "string",
                    "description": "Идентификатор ключа (из JWK или отпечаток RFC 7638)."
                  },
                  "alg": {
                    "type": "string",
                    "description": "Алгоритм согласования ключа: ECDH-ES+A256KW, RSA-OAEP-256 или RSA-OAEP-384."
                  },
                  "kty": {
                    "type": "string",
                    "enum": [
                      "EC",
                      "OKP",
                      "RSA"
                    ]
                  },
                  "crv": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Кривая (EC/OKP); null у RSA."
                  },
                  "rsa_bits": {
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Длина модуля RSA, бит; null у EC/OKP."
                  },
                  "thumbprint": {
                    "type": "string",
                    "description": "Отпечаток открытого ключа (RFC 7638, SHA-256)."
                  },
                  "created_at": {
                    "type": "string",
                    "description": "Когда ключ зарегистрирован, ISO 8601 UTC."
                  }
                },
                "required": [
                  "kid",
                  "alg",
                  "kty",
                  "crv",
                  "rsa_bits",
                  "thumbprint",
                  "created_at"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Действующий открытый ключ получателя; null — не зарегистрирован."
          },
          "previous_key": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "kid": {
                    "type": "string",
                    "description": "Идентификатор ключа (из JWK или отпечаток RFC 7638)."
                  },
                  "alg": {
                    "type": "string",
                    "description": "Алгоритм согласования ключа: ECDH-ES+A256KW, RSA-OAEP-256 или RSA-OAEP-384."
                  },
                  "kty": {
                    "type": "string",
                    "enum": [
                      "EC",
                      "OKP",
                      "RSA"
                    ]
                  },
                  "crv": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Кривая (EC/OKP); null у RSA."
                  },
                  "rsa_bits": {
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Длина модуля RSA, бит; null у EC/OKP."
                  },
                  "thumbprint": {
                    "type": "string",
                    "description": "Отпечаток открытого ключа (RFC 7638, SHA-256)."
                  },
                  "created_at": {
                    "type": "string",
                    "description": "Когда ключ зарегистрирован, ISO 8601 UTC."
                  },
                  "expires_at": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "kid",
                  "alg",
                  "kty",
                  "crv",
                  "rsa_bits",
                  "thumbprint",
                  "created_at",
                  "expires_at"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Прежний ключ после смены: его ещё можно запросить заголовком Encryption-Key-Id до expires_at (7 суток)."
          },
          "accepted": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "alg": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "crv": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "min_rsa_bits": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "enc": {
                    "type": "string",
                    "const": "A256GCM"
                  }
                },
                "required": [
                  "alg",
                  "crv",
                  "min_rsa_bits",
                  "enc"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Какие ключи принимает эта ячейка."
          }
        },
        "required": [
          "mode",
          "key",
          "previous_key",
          "accepted"
        ],
        "description": "Формат JWE (RFC 7516) полей с персональными данными: только ячейки EN и ID. Ключевую пару создаёте вы; платформе передаётся только открытый ключ."
      },
      "PiiEncryptionKeyPut": {
        "type": "object",
        "properties": {
          "jwk": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {},
            "description": "Открытый ключ получателя (JWK) с полем alg. Закрытые части (d, p, q, dp, dq, qi, k) не принимаются."
          }
        },
        "required": [
          "jwk"
        ],
        "description": "Тело регистрации ключа."
      },
      "PiiEncryptionKeyResult": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "off",
              "optional",
              "required"
            ],
            "description": "off — поля с персональными данными выдаются как есть; optional — в формате JWE, если ключ зарегистрирован; required — только в формате JWE (без ключа — 409 encryption_key_required). Режим меняется в кабинете."
          },
          "key": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "kid": {
                    "type": "string",
                    "description": "Идентификатор ключа (из JWK или отпечаток RFC 7638)."
                  },
                  "alg": {
                    "type": "string",
                    "description": "Алгоритм согласования ключа: ECDH-ES+A256KW, RSA-OAEP-256 или RSA-OAEP-384."
                  },
                  "kty": {
                    "type": "string",
                    "enum": [
                      "EC",
                      "OKP",
                      "RSA"
                    ]
                  },
                  "crv": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Кривая (EC/OKP); null у RSA."
                  },
                  "rsa_bits": {
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Длина модуля RSA, бит; null у EC/OKP."
                  },
                  "thumbprint": {
                    "type": "string",
                    "description": "Отпечаток открытого ключа (RFC 7638, SHA-256)."
                  },
                  "created_at": {
                    "type": "string",
                    "description": "Когда ключ зарегистрирован, ISO 8601 UTC."
                  }
                },
                "required": [
                  "kid",
                  "alg",
                  "kty",
                  "crv",
                  "rsa_bits",
                  "thumbprint",
                  "created_at"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Действующий открытый ключ получателя; null — не зарегистрирован."
          },
          "previous_key": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "kid": {
                    "type": "string",
                    "description": "Идентификатор ключа (из JWK или отпечаток RFC 7638)."
                  },
                  "alg": {
                    "type": "string",
                    "description": "Алгоритм согласования ключа: ECDH-ES+A256KW, RSA-OAEP-256 или RSA-OAEP-384."
                  },
                  "kty": {
                    "type": "string",
                    "enum": [
                      "EC",
                      "OKP",
                      "RSA"
                    ]
                  },
                  "crv": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Кривая (EC/OKP); null у RSA."
                  },
                  "rsa_bits": {
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Длина модуля RSA, бит; null у EC/OKP."
                  },
                  "thumbprint": {
                    "type": "string",
                    "description": "Отпечаток открытого ключа (RFC 7638, SHA-256)."
                  },
                  "created_at": {
                    "type": "string",
                    "description": "Когда ключ зарегистрирован, ISO 8601 UTC."
                  },
                  "expires_at": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "kid",
                  "alg",
                  "kty",
                  "crv",
                  "rsa_bits",
                  "thumbprint",
                  "created_at",
                  "expires_at"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Прежний ключ после смены: его ещё можно запросить заголовком Encryption-Key-Id до expires_at (7 суток)."
          },
          "accepted": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "alg": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "crv": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "min_rsa_bits": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "enc": {
                    "type": "string",
                    "const": "A256GCM"
                  }
                },
                "required": [
                  "alg",
                  "crv",
                  "min_rsa_bits",
                  "enc"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Какие ключи принимает эта ячейка."
          },
          "changed": {
            "type": "boolean",
            "description": "false — этот же ключ уже был зарегистрирован."
          }
        },
        "required": [
          "mode",
          "key",
          "previous_key",
          "accepted",
          "changed"
        ],
        "description": "Настройка после регистрации ключа."
      },
      "Me": {
        "type": "object",
        "properties": {
          "tenant": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ],
            "description": "Арендатор — владелец ключа."
          },
          "cell": {
            "type": "string",
            "enum": [
              "ru",
              "en",
              "id"
            ],
            "description": "Ячейка платформы: ru, en или id."
          },
          "base_url": {
            "type": "string",
            "description": "Базовый адрес API этой ячейки."
          },
          "integration": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ],
            "description": "Интеграция (служебная учётная запись), которой принадлежит ключ."
          },
          "channel_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Канал \"api\" интеграции; null — канал ещё не создан."
          },
          "key": {
            "type": "object",
            "properties": {
              "key_id": {
                "type": "string",
                "description": "Публичный идентификатор ключа (не секрет)."
              },
              "mode": {
                "type": "string",
                "enum": [
                  "live",
                  "test"
                ]
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "conversations:read",
                    "conversations:write",
                    "ai_seller:invoke",
                    "leads:read",
                    "leads:write",
                    "leads:score",
                    "analytics:read",
                    "analytics:write",
                    "dashboards:read",
                    "articles:read",
                    "articles:write",
                    "articles:generate",
                    "strategist:read",
                    "strategist:write",
                    "strategist:chat",
                    "webhooks:manage",
                    "channels:read",
                    "channels:write",
                    "cards:read",
                    "cards:write"
                  ]
                },
                "description": "Действующие области: область интеграции ∩ текущие права владельца ∩ лицензия."
              },
              "expires_at": {
                "type": "string",
                "description": "Срок действия ключа, ISO 8601 UTC."
              },
              "ip_allowlist": {
                "anyOf": [
                  {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Разрешённые адреса и сети (CIDR); null — любой адрес."
              }
            },
            "required": [
              "key_id",
              "mode",
              "scopes",
              "expires_at",
              "ip_allowlist"
            ]
          },
          "limits": {
            "type": "object",
            "properties": {
              "read_per_min": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "write_per_min": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "paid_per_min": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "paid_concurrency": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "description": "Одновременных платных операций ИИ на интеграцию; сверх — 429 concurrency_limit."
              },
              "max_operation_cost": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Money"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Максимум стоимости одной платной операции в валюте кошелька (оценка выше — 402 spend_limit_reached); null — не удалось прочитать."
              }
            },
            "required": [
              "read_per_min",
              "write_per_min",
              "paid_per_min",
              "paid_concurrency",
              "max_operation_cost"
            ],
            "description": "Пределы частоты запросов и платных операций."
          },
          "wallet": {
            "type": "object",
            "properties": {
              "balance": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Money"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Остаток кошелька в рублях; null — состояние неизвестно или арендатор не тарифицируется."
              },
              "state": {
                "type": "string",
                "enum": [
                  "ok",
                  "low",
                  "negative",
                  "blocked",
                  "unknown"
                ],
                "description": "ok — достаточно; low — мало средств; negative — остаток ниже нуля; blocked — кошелёк заблокирован; unknown — состояние получить не удалось. Подробности — GET /wallet."
              },
              "exchange": {
                "type": "string",
                "enum": [
                  "active",
                  "suspended"
                ],
                "description": "suspended при negative и blocked: все маршруты, кроме /me и /wallet, отвечают 402 wallet_suspended."
              },
              "topup_url": {
                "type": "string",
                "description": "Адрес кабинета, где пополняется кошелёк."
              },
              "daily_spend": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "limit": {
                        "anyOf": [
                          {
                            "$ref": "#/components/schemas/Money"
                          },
                          {
                            "type": "null"
                          }
                        ],
                        "description": "Суточный предел трат интеграции; null — не задан."
                      },
                      "used": {
                        "description": "Списано за платные операции интеграции с начала местных суток ячейки.",
                        "$ref": "#/components/schemas/Money"
                      }
                    },
                    "required": [
                      "limit",
                      "used"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Суточные траты интеграции; null — посчитать не удалось."
              }
            },
            "required": [
              "balance",
              "state",
              "exchange",
              "topup_url",
              "daily_spend"
            ],
            "description": "Кошелёк арендатора (ИИ-операции)."
          },
          "crm_mode": {
            "type": "string",
            "description": "Режим CRM арендатора: \"internal\" (наша CRM) или внешняя система."
          },
          "pii_encryption": {
            "description": "Только ячейки EN и ID: формат JWE полей с персональными данными; null — настройку прочитать не удалось. На ячейке RU поля нет.",
            "anyOf": [
              {
                "$ref": "#/components/schemas/PiiEncryption"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "tenant",
          "cell",
          "base_url",
          "integration",
          "channel_id",
          "key",
          "limits",
          "wallet",
          "crm_mode"
        ],
        "description": "Кто вы: арендатор, интеграция, ключ, пределы, кошелёк."
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор подписки."
          },
          "url": {
            "type": "string",
            "description": "Адрес приёма: https, порт 443, имя хоста (не IP), без переадресаций."
          },
          "events": {
            "minItems": 1,
            "maxItems": 50,
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Типы событий: точный тип или шаблон семейства \"семейство.*\". Доступные типы: conversation.created, message.created, conversation.handoff_requested, conversation.summary_ready, lead.created, lead.updated, lead.scored, lead.status_changed, lead.action_requested, task.created, task.completed, contact.merged, crm.mode_changed, article.ready, article.published, article.generation.failed, strategist.report.ready, strategist.turn.completed, operation.completed, api_key.expiring."
          },
          "include_pii": {
            "type": "boolean",
            "description": "Полная нагрузка с персональными данными; только для событий lead.*, contact.*, conversation.*. По умолчанию false."
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200,
                "description": "Пометка для вас, до 200 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused"
            ],
            "description": "active — доставки идут; paused — приостановлена."
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 UTC."
          },
          "updated_at": {
            "type": "string",
            "description": "ISO 8601 UTC."
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "include_pii",
          "description",
          "status",
          "created_at",
          "updated_at"
        ],
        "description": "Подписка на события. Секрета у подписки нет: каждую доставку подписывает ключ платформы (JWS EdDSA, заголовок Webhook-Signature), открытые ключи — GET /.well-known/jwks.json."
      },
      "WebhookJwk": {
        "type": "object",
        "properties": {
          "kty": {
            "type": "string",
            "const": "OKP"
          },
          "crv": {
            "type": "string",
            "const": "Ed25519"
          },
          "x": {
            "type": "string",
            "description": "Открытый ключ, base64url."
          },
          "kid": {
            "type": "string",
            "description": "Идентификатор ключа (отпечаток RFC 7638); совпадает с kid в заголовке подписи."
          },
          "alg": {
            "type": "string",
            "const": "EdDSA"
          },
          "use": {
            "type": "string",
            "const": "sig"
          }
        },
        "required": [
          "kty",
          "crv",
          "x",
          "kid",
          "alg",
          "use"
        ],
        "description": "Открытый ключ подписи вебхуков."
      },
      "WebhookJwks": {
        "type": "object",
        "properties": {
          "keys": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookJwk"
            },
            "description": "Действующий ключ и ключи, ещё живущие после ротации."
          }
        },
        "required": [
          "keys"
        ],
        "description": "Набор открытых ключей подписи вебхуков ячейки (RFC 7517)."
      },
      "WebhookCreate": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "Адрес приёма: https, порт 443, имя хоста (не IP), без переадресаций."
          },
          "events": {
            "minItems": 1,
            "maxItems": 50,
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Типы событий: точный тип или шаблон семейства \"семейство.*\". Доступные типы: conversation.created, message.created, conversation.handoff_requested, conversation.summary_ready, lead.created, lead.updated, lead.scored, lead.status_changed, lead.action_requested, task.created, task.completed, contact.merged, crm.mode_changed, article.ready, article.published, article.generation.failed, strategist.report.ready, strategist.turn.completed, operation.completed, api_key.expiring."
          },
          "include_pii": {
            "type": "boolean",
            "description": "Полная нагрузка с персональными данными; только для событий lead.*, contact.*, conversation.*. По умолчанию false."
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200,
                "description": "Пометка для вас, до 200 знаков."
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "url",
          "events"
        ],
        "description": "Тело создания подписки."
      },
      "WebhookUpdate": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "Адрес приёма: https, порт 443, имя хоста (не IP), без переадресаций."
          },
          "events": {
            "minItems": 1,
            "maxItems": 50,
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Типы событий: точный тип или шаблон семейства \"семейство.*\". Доступные типы: conversation.created, message.created, conversation.handoff_requested, conversation.summary_ready, lead.created, lead.updated, lead.scored, lead.status_changed, lead.action_requested, task.created, task.completed, contact.merged, crm.mode_changed, article.ready, article.published, article.generation.failed, strategist.report.ready, strategist.turn.completed, operation.completed, api_key.expiring."
          },
          "include_pii": {
            "type": "boolean",
            "description": "Полная нагрузка с персональными данными; только для событий lead.*, contact.*, conversation.*. По умолчанию false."
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200,
                "description": "Пометка для вас, до 200 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "description": "Приостановить или возобновить доставки.",
            "type": "string",
            "enum": [
              "active",
              "paused"
            ]
          }
        },
        "description": "Тело правки: передайте хотя бы одно поле."
      },
      "WebhookPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Webhook"
            }
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Курсор следующей страницы; null — список закончился. Живёт 24 часа."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "description": "Страница списка."
      },
      "WebhookTestResult": {
        "type": "object",
        "properties": {
          "event_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Идентификатор тестового события."
          },
          "type": {
            "type": "string",
            "const": "webhook.test"
          },
          "status": {
            "type": "string",
            "const": "queued",
            "description": "Событие в очереди; уйдёт на ближайшем запуске доставщика (до минуты)."
          }
        },
        "required": [
          "event_id",
          "type",
          "status"
        ],
        "description": "Ответ 202 на тестовую доставку. Тело события приходит на ваш адрес с livemode: false."
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор доставки."
          },
          "event_id": {
            "type": "string",
            "description": "Идентификатор события."
          },
          "state": {
            "type": "string",
            "enum": [
              "pending",
              "delivered",
              "failed",
              "dead"
            ],
            "description": "pending — ждёт попытки; delivered — доставлено; failed — попытка не удалась, будет повтор; dead — повторы исчерпаны."
          },
          "attempt": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Номер последней попытки (0 — ещё не было)."
          },
          "status_code": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ],
            "description": "HTTP-код ответа подписчика; null, если ответа не было."
          },
          "duration_ms": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ],
            "description": "Длительность попытки, мс."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Причина сбоя: тайм-аут, ошибка соединения или сертификата, ответ 3xx."
          },
          "next_attempt_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Время следующей попытки; null, если попыток больше не будет."
          },
          "delivered_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Время успешной доставки."
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "event_id",
          "state",
          "attempt",
          "status_code",
          "duration_ms",
          "error",
          "next_attempt_at",
          "delivered_at",
          "created_at"
        ],
        "description": "Запись журнала доставок (хранится 30 суток)."
      },
      "WebhookDeliveryPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookDelivery"
            }
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Курсор следующей страницы; null — список закончился. Живёт 24 часа."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "description": "Страница списка."
      },
      "ChannelWidgetPoweredBy": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "default",
              "custom",
              "hidden"
            ],
            "description": "default — название продукта ячейки; custom — ваш текст и ссылка; hidden — без подписи."
          },
          "text": {
            "description": "Текст подписи для custom, до 40 знаков.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 40
              },
              {
                "type": "null"
              }
            ]
          },
          "url": {
            "description": "Ссылка подписи для custom: только https://.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "mode"
        ],
        "description": "Подпись внизу виджета."
      },
      "ChannelWidgetFiles": {
        "type": "object",
        "properties": {
          "visitor_upload": {
            "type": "boolean",
            "description": "Посетитель может присылать файлы. По умолчанию true."
          },
          "max_mb": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "description": "Предел одного файла, МБ (1–10)."
          }
        },
        "required": [
          "visitor_upload",
          "max_mb"
        ],
        "description": "Файлы посетителя."
      },
      "ChannelWidget": {
        "type": "object",
        "properties": {
          "channel_id": {
            "type": "string",
            "description": "Идентификатор канала web_chat."
          },
          "name": {
            "type": "string",
            "description": "Имя канала."
          },
          "is_active": {
            "type": "boolean",
            "description": "Канал включён."
          },
          "assistant_name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 60,
                "description": "Имя ассистента в шапке; по умолчанию — имя канала. До 60 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "assistant_subtitle": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 80,
                "description": "Подзаголовок ассистента. До 80 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "assistant_avatar_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500,
                "description": "Иконка ассистента (шапка и лента). Только https:// или путь вашего сайта на этой ячейке, начинающийся с «/». До 500 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "queue_title": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 60,
                "description": "Заголовок шапки, пока диалог ждёт оператора. До 60 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "queue_subtitle": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 80,
                "description": "Подзаголовок ожидания оператора. До 80 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "queue_icon_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500,
                "description": "Иконка ожидания оператора. Только https:// или путь вашего сайта на этой ячейке, начинающийся с «/». До 500 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "powered_by": {
            "$ref": "#/components/schemas/ChannelWidgetPoweredBy"
          },
          "files": {
            "$ref": "#/components/schemas/ChannelWidgetFiles"
          },
          "color": {
            "anyOf": [
              {
                "type": "string",
                "description": "Цвет виджета: #rrggbb."
              },
              {
                "type": "null"
              }
            ]
          },
          "greeting": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500,
                "description": "Приветствие. До 500 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "position": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "bottom-right",
                  "bottom-left"
                ],
                "description": "Угол кнопки."
              },
              {
                "type": "null"
              }
            ]
          },
          "theme": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "light",
                  "dark"
                ],
                "description": "Тема."
              },
              {
                "type": "null"
              }
            ]
          },
          "bubble_text": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 60,
                "description": "Подсказка у кнопки. До 60 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "delay": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "maximum": 120,
                "description": "Задержка показа, секунды."
              },
              {
                "type": "null"
              }
            ]
          },
          "consent_text": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 600,
                "description": "Текст согласия перед первым сообщением. До 600 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "consent_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500,
                "description": "Ссылка на документ согласия: только https://."
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "channel_id",
          "name",
          "is_active",
          "assistant_name",
          "assistant_subtitle",
          "assistant_avatar_url",
          "queue_title",
          "queue_subtitle",
          "queue_icon_url",
          "powered_by",
          "files",
          "color",
          "greeting",
          "position",
          "theme",
          "bubble_text",
          "delay",
          "consent_text",
          "consent_url"
        ],
        "description": "Настройки чат-виджета канала. null — значение по умолчанию."
      },
      "ChannelWidgetUpdate": {
        "type": "object",
        "properties": {
          "assistant_name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 60,
                "description": "Имя ассистента в шапке; по умолчанию — имя канала. До 60 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "assistant_subtitle": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 80,
                "description": "Подзаголовок ассистента. До 80 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "assistant_avatar_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500,
                "description": "Иконка ассистента (шапка и лента). Только https:// или путь вашего сайта на этой ячейке, начинающийся с «/». До 500 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "queue_title": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 60,
                "description": "Заголовок шапки, пока диалог ждёт оператора. До 60 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "queue_subtitle": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 80,
                "description": "Подзаголовок ожидания оператора. До 80 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "queue_icon_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500,
                "description": "Иконка ожидания оператора. Только https:// или путь вашего сайта на этой ячейке, начинающийся с «/». До 500 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "powered_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ChannelWidgetPoweredBy"
              },
              {
                "type": "null"
              }
            ]
          },
          "files": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "visitor_upload": {
                    "type": "boolean",
                    "description": "Посетитель может присылать файлы. По умолчанию true."
                  },
                  "max_mb": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10,
                    "description": "Предел одного файла, МБ (1–10)."
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "color": {
            "anyOf": [
              {
                "type": "string",
                "description": "Цвет виджета: #rrggbb."
              },
              {
                "type": "null"
              }
            ]
          },
          "greeting": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500,
                "description": "Приветствие. До 500 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "position": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "bottom-right",
                  "bottom-left"
                ],
                "description": "Угол кнопки."
              },
              {
                "type": "null"
              }
            ]
          },
          "theme": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "light",
                  "dark"
                ],
                "description": "Тема."
              },
              {
                "type": "null"
              }
            ]
          },
          "bubble_text": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 60,
                "description": "Подсказка у кнопки. До 60 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "delay": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "maximum": 120,
                "description": "Задержка показа, секунды."
              },
              {
                "type": "null"
              }
            ]
          },
          "consent_text": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 600,
                "description": "Текст согласия перед первым сообщением. До 600 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "consent_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500,
                "description": "Ссылка на документ согласия: только https://."
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "description": "Правка: передайте хотя бы одно поле. Не переданное остаётся как было, null возвращает значение по умолчанию; неизвестные поля отбрасываются."
      },
      "CardButton": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "maxLength": 30,
            "description": "Подпись, до 30 знаков."
          },
          "url": {
            "type": "string",
            "maxLength": 2000,
            "description": "Адрес кнопки. Только https:// или путь вашего сайта, начинающийся с «/» (разворачивается по основному домену аккаунта)."
          }
        },
        "required": [
          "label",
          "url"
        ],
        "description": "Кнопка карточки."
      },
      "Card": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор товара."
          },
          "code": {
            "type": "string",
            "maxLength": 40,
            "description": "Код карточки, уникален в аккаунте: строчные латинские буквы, цифры, «_» и «-», до 40 знаков. ИИ-продажник ставит в ответ маркер [CARD:код]."
          },
          "name": {
            "type": "string",
            "maxLength": 120,
            "description": "Название. До 120 знаков."
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500,
                "description": "Описание. До 500 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000,
                "description": "Картинка: https:// или путь файла, загруженного в хранилище вашего аккаунта."
              },
              {
                "type": "null"
              }
            ]
          },
          "price_text": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Цена текстом; не задана — из цены и валюты товара; null — цены нет."
          },
          "badge": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 30,
                "description": "Плашка («Хит»). До 30 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "page_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000,
                "description": "Страница товара. Только https:// или путь вашего сайта, начинающийся с «/» (разворачивается по основному домену аккаунта)."
              },
              {
                "type": "null"
              }
            ]
          },
          "buttons": {
            "maxItems": 3,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CardButton"
            },
            "description": "До 3 кнопок. Пусто — одна кнопка «Подробнее» на page_url."
          },
          "ai_enabled": {
            "type": "boolean",
            "description": "Карточка доступна ИИ-продажнику: код, название и цена попадают в его каталог. Нужен код."
          },
          "sort": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Порядок в каталоге продажника и выборе оператора (по возрастанию)."
          },
          "active": {
            "type": "boolean",
            "description": "Товар активен; неактивную карточку нельзя отправить."
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 UTC."
          },
          "updated_at": {
            "type": "string",
            "description": "ISO 8601 UTC."
          }
        },
        "required": [
          "id",
          "code",
          "name",
          "description",
          "image_url",
          "price_text",
          "badge",
          "page_url",
          "buttons",
          "ai_enabled",
          "sort",
          "active",
          "created_at",
          "updated_at"
        ],
        "description": "Карточка товара для чата: картинка, название, цена и до трёх кнопок. Хранится на товаре аккаунта."
      },
      "CardCreate": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 40,
            "description": "Код карточки, уникален в аккаунте: строчные латинские буквы, цифры, «_» и «-», до 40 знаков. ИИ-продажник ставит в ответ маркер [CARD:код]."
          },
          "name": {
            "type": "string",
            "maxLength": 120,
            "description": "Название. До 120 знаков."
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500,
                "description": "Описание. До 500 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000,
                "description": "Картинка: https:// или путь файла, загруженного в хранилище вашего аккаунта."
              },
              {
                "type": "null"
              }
            ]
          },
          "page_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000,
                "description": "Страница товара. Только https:// или путь вашего сайта, начинающийся с «/» (разворачивается по основному домену аккаунта)."
              },
              {
                "type": "null"
              }
            ]
          },
          "badge": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 30,
                "description": "Плашка («Хит»). До 30 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "price_text": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 40,
                "description": "Цена текстом. До 40 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "buttons": {
            "maxItems": 3,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CardButton"
            },
            "description": "До 3 кнопок. Пусто — одна кнопка «Подробнее» на page_url."
          },
          "ai_enabled": {
            "type": "boolean",
            "description": "Карточка доступна ИИ-продажнику: код, название и цена попадают в его каталог. Нужен код."
          },
          "sort": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Порядок в каталоге продажника и выборе оператора (по возрастанию)."
          },
          "active": {
            "type": "boolean",
            "description": "Товар активен; неактивную карточку нельзя отправить."
          }
        },
        "required": [
          "code",
          "name"
        ],
        "description": "Тело создания карточки. Неизвестные поля — 422."
      },
      "CardUpdate": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 40,
            "description": "Код карточки, уникален в аккаунте: строчные латинские буквы, цифры, «_» и «-», до 40 знаков. ИИ-продажник ставит в ответ маркер [CARD:код]."
          },
          "name": {
            "type": "string",
            "maxLength": 120,
            "description": "Название. До 120 знаков."
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500,
                "description": "Описание. До 500 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000,
                "description": "Картинка: https:// или путь файла, загруженного в хранилище вашего аккаунта."
              },
              {
                "type": "null"
              }
            ]
          },
          "page_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000,
                "description": "Страница товара. Только https:// или путь вашего сайта, начинающийся с «/» (разворачивается по основному домену аккаунта)."
              },
              {
                "type": "null"
              }
            ]
          },
          "badge": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 30,
                "description": "Плашка («Хит»). До 30 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "price_text": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 40,
                "description": "Цена текстом. До 40 знаков."
              },
              {
                "type": "null"
              }
            ]
          },
          "buttons": {
            "maxItems": 3,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CardButton"
            },
            "description": "До 3 кнопок. Пусто — одна кнопка «Подробнее» на page_url."
          },
          "ai_enabled": {
            "type": "boolean",
            "description": "Карточка доступна ИИ-продажнику: код, название и цена попадают в его каталог. Нужен код."
          },
          "sort": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Порядок в каталоге продажника и выборе оператора (по возрастанию)."
          },
          "active": {
            "type": "boolean",
            "description": "Товар активен; неактивную карточку нельзя отправить."
          }
        },
        "description": "Тело правки: передайте хотя бы одно поле."
      },
      "CardPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Card"
            }
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Курсор следующей страницы; null — список закончился. Живёт 24 часа."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "description": "Страница списка."
      },
      "MessageCard": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 40,
            "description": "Код карточки, уникален в аккаунте: строчные латинские буквы, цифры, «_» и «-», до 40 знаков. ИИ-продажник ставит в ответ маркер [CARD:код]."
          },
          "name": {
            "type": "string",
            "maxLength": 120,
            "description": "Название. До 120 знаков."
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Полный https-адрес картинки."
          },
          "price_text": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "badge": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "page_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Полный https-адрес страницы; null — путь без домена аккаунта."
          },
          "buttons": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CardButton"
            }
          }
        },
        "required": [
          "code",
          "name",
          "description",
          "image_url",
          "price_text",
          "badge",
          "page_url",
          "buttons"
        ],
        "description": "Копия карточки в сообщении на момент отправки (адреса развёрнуты)."
      },
      "CardSend": {
        "type": "object",
        "properties": {
          "codes": {
            "minItems": 1,
            "maxItems": 3,
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Коды карточек, 1–3."
          },
          "comment": {
            "description": "Текст над карточками, до 1000 знаков.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 1000
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "codes"
        ],
        "description": "Тело отправки карточек в диалог."
      },
      "CardSendResult": {
        "type": "object",
        "properties": {
          "message_id": {
            "type": "string",
            "description": "Идентификатор сообщения с карточками."
          },
          "conversation_id": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 UTC."
          },
          "cards": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MessageCard"
            }
          },
          "delivery": {
            "type": "string",
            "enum": [
              "metadata",
              "native",
              "text"
            ],
            "description": "Как карточки доходят до клиента: metadata — виджет сайта и канал интеграции (событие message.created); native — Telegram, VK, Max своим форматом; text — строками «название — цена — ссылка»."
          },
          "status": {
            "type": "string",
            "enum": [
              "sent",
              "delivered",
              "failed"
            ],
            "description": "Состояние доставки в канал."
          }
        },
        "required": [
          "message_id",
          "conversation_id",
          "created_at",
          "cards",
          "delivery",
          "status"
        ],
        "description": "Ответ 201 на отправку карточек."
      },
      "Wallet": {
        "type": "object",
        "properties": {
          "balance": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Money"
              },
              {
                "type": "null"
              }
            ],
            "description": "Остаток кошелька в рублях (кошелёк ведётся в RUB на любой ячейке); null — состояние неизвестно или арендатор не тарифицируется."
          },
          "state": {
            "type": "string",
            "enum": [
              "ok",
              "low",
              "negative",
              "blocked",
              "unknown"
            ],
            "description": "ok — достаточно; low — мало средств (обмен идёт); negative — остаток ниже нуля; blocked — кошелёк заблокирован; unknown — состояние получить не удалось."
          },
          "exchange": {
            "type": "string",
            "enum": [
              "active",
              "suspended"
            ],
            "description": "suspended при negative и blocked: все маршруты, кроме /me и /wallet, отвечают 402 wallet_suspended, вебхуки откладываются. При unknown остаётся active: бесплатное чтение идёт с заголовком Wallet-State: unknown, платные операции закрыты (503)."
          },
          "topup_url": {
            "type": "string",
            "description": "Адрес кабинета, где пополняется кошелёк (нужен вход сотрудника с правом пополнения)."
          },
          "daily_spend": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "limit": {
                    "anyOf": [
                      {
                        "$ref": "#/components/schemas/Money"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Суточный предел трат интеграции; null — не задан."
                  },
                  "used": {
                    "description": "Списано с начала местных суток ячейки.",
                    "$ref": "#/components/schemas/Money"
                  }
                },
                "required": [
                  "limit",
                  "used"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Суточные траты интеграции: списания за её платные операции с начала местных суток ячейки; null — посчитать не удалось."
          }
        },
        "required": [
          "balance",
          "state",
          "exchange",
          "topup_url",
          "daily_spend"
        ],
        "description": "Состояние кошелька арендатора и обмена данными."
      },
      "TimeseriesItem": {
        "type": "object",
        "properties": {
          "metric": {
            "type": "string",
            "enum": [
              "sessions",
              "pageviews",
              "visitors",
              "bounce_rate",
              "impressions",
              "clicks",
              "ctr",
              "position",
              "ai_referrals",
              "bot_hits",
              "leads",
              "deals_won",
              "revenue"
            ]
          },
          "from": {
            "type": "string",
            "description": "Дата YYYY-MM-DD."
          },
          "to": {
            "type": "string",
            "description": "Дата YYYY-MM-DD."
          },
          "granularity": {
            "type": "string",
            "enum": [
              "day",
              "week"
            ]
          },
          "agg": {
            "type": "string",
            "enum": [
              "sum",
              "avg"
            ],
            "description": "Способ свёртки ряда за период."
          },
          "engine": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "google",
                  "yandex",
                  "bing"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Поисковик ряда; null у метрик, не привязанных к поиску."
          },
          "availability": {
            "type": "string",
            "enum": [
              "ok",
              "no_data",
              "no_source"
            ]
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Код причины, если availability не ok."
          },
          "series": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "date": {
                  "type": "string",
                  "description": "Дата YYYY-MM-DD."
                },
                "value": {
                  "anyOf": [
                    {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "$ref": "#/components/schemas/Money"
                        }
                      ]
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": [
                "date",
                "value"
              ]
            },
            "description": "Ряд значений; дни без данных заполнены нулями. При недельном шаге date — первый день недели."
          },
          "comparison": {
            "type": "object",
            "properties": {
              "current": {
                "anyOf": [
                  {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "$ref": "#/components/schemas/Money"
                      }
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "prev": {
                "anyOf": [
                  {
                    "anyOf": [
                      {
                        "type": "number"
                      },
                      {
                        "$ref": "#/components/schemas/Money"
                      }
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "delta_pct": {
                "anyOf": [
                  {
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Изменение в процентах; null, если сравнить не с чем или база равна нулю."
              },
              "data_through": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Последняя дата, по которую данные полны."
              }
            },
            "required": [
              "current",
              "prev",
              "delta_pct",
              "data_through"
            ]
          },
          "summary": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "total": {
                    "anyOf": [
                      {
                        "anyOf": [
                          {
                            "type": "number"
                          },
                          {
                            "$ref": "#/components/schemas/Money"
                          }
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "latest": {
                    "anyOf": [
                      {
                        "anyOf": [
                          {
                            "type": "number"
                          },
                          {
                            "$ref": "#/components/schemas/Money"
                          }
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "non_zero_days": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "total",
                  "latest",
                  "non_zero_days"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "cluster_applied": {
            "type": "boolean"
          },
          "data_as_of": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "string"
            },
            "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
          }
        },
        "required": [
          "metric",
          "from",
          "to",
          "granularity",
          "agg",
          "engine",
          "availability",
          "reason",
          "series",
          "comparison",
          "summary",
          "cluster_applied",
          "data_as_of"
        ],
        "description": "Один временной ряд."
      },
      "TimeseriesResponse": {
        "type": "object",
        "properties": {
          "data": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TimeseriesItem"
              },
              {
                "type": "object",
                "properties": {
                  "items": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/TimeseriesItem"
                    }
                  }
                },
                "required": [
                  "items"
                ]
              }
            ]
          }
        },
        "required": [
          "data"
        ],
        "description": "Один ряд (одна метрика) либо items в порядке запроса (несколько метрик)."
      },
      "TrafficSourceRow": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "google",
              "yandex",
              "bing",
              "chatgpt",
              "perplexity",
              "ai_other",
              "social",
              "ads",
              "direct",
              "other"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "search",
              "ai_assistant",
              "social",
              "ads",
              "direct",
              "other"
            ]
          },
          "sessions": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "visitors": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ],
            "description": "Уникальные посетители за день, просуммированные по периоду; null, когда посчитать нечем (маячок anonymous)."
          },
          "leads": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "series": {
            "description": "Только при include=series.",
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "date": {
                  "type": "string",
                  "description": "Дата YYYY-MM-DD."
                },
                "sessions": {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                "visitors": {
                  "anyOf": [
                    {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "leads": {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                }
              },
              "required": [
                "date",
                "sessions",
                "visitors",
                "leads"
              ]
            }
          }
        },
        "required": [
          "source",
          "kind",
          "sessions",
          "visitors",
          "leads"
        ],
        "description": "Источник первого визита за период."
      },
      "TrafficSourcesResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TrafficSourceRow"
            }
          },
          "data_as_of": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "string"
            },
            "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
          }
        },
        "required": [
          "data",
          "data_as_of"
        ],
        "description": "Источники трафика, больше сессий первыми."
      },
      "FunnelStep": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "enum": [
              "impressions",
              "clicks",
              "sessions",
              "leads",
              "deals_created",
              "deals_won",
              "revenue"
            ]
          },
          "availability": {
            "type": "string",
            "enum": [
              "ok",
              "no_data",
              "no_source"
            ]
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "unit": {
            "type": "string",
            "enum": [
              "count",
              "money"
            ]
          },
          "current": {
            "anyOf": [
              {
                "anyOf": [
                  {
                    "type": "number"
                  },
                  {
                    "$ref": "#/components/schemas/Money"
                  }
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "prev": {
            "anyOf": [
              {
                "anyOf": [
                  {
                    "type": "number"
                  },
                  {
                    "$ref": "#/components/schemas/Money"
                  }
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "delta_pct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          },
          "data_through": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "key",
          "availability",
          "sources",
          "unit",
          "current",
          "prev",
          "delta_pct",
          "data_through"
        ],
        "description": "Ступень воронки со своей доступностью и своей датой."
      },
      "FunnelResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "engine": {
                "type": "string",
                "enum": [
                  "yandex",
                  "google",
                  "both"
                ]
              },
              "from": {
                "type": "string",
                "description": "Дата YYYY-MM-DD."
              },
              "to": {
                "type": "string",
                "description": "Дата YYYY-MM-DD."
              },
              "steps": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/FunnelStep"
                }
              },
              "by_channel": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "channel": {
                      "type": "string"
                    },
                    "availability": {
                      "type": "string"
                    },
                    "sources": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "clicks": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "cost": {
                      "anyOf": [
                        {
                          "$ref": "#/components/schemas/Money"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "leads": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "channel",
                    "availability",
                    "sources",
                    "clicks",
                    "cost",
                    "leads"
                  ]
                }
              },
              "search_by_engine": {
                "description": "Только engine=both: движки раздельно.",
                "type": "array",
                "items": {
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              },
              "by_product": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "course_slug": {
                      "type": "string"
                    },
                    "name": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "sales_mode": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "leads": {
                      "type": "number"
                    },
                    "leads_prev": {
                      "type": "number"
                    },
                    "deals_won": {
                      "type": "number"
                    },
                    "deals_won_prev": {
                      "type": "number"
                    }
                  },
                  "required": [
                    "course_slug",
                    "name",
                    "sales_mode",
                    "leads",
                    "leads_prev",
                    "deals_won",
                    "deals_won_prev"
                  ]
                }
              },
              "crm": {
                "type": "object",
                "properties": {
                  "availability": {
                    "type": "string",
                    "enum": [
                      "ok",
                      "no_data"
                    ]
                  },
                  "reason": {
                    "type": "string"
                  }
                },
                "required": [
                  "availability"
                ]
              }
            },
            "required": [
              "engine",
              "from",
              "to",
              "steps",
              "by_channel",
              "by_product",
              "crm"
            ]
          },
          "data_as_of": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "string"
            },
            "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
          }
        },
        "required": [
          "data",
          "data_as_of"
        ],
        "description": "Воронка «показы → клики → сессии → лиды → сделки → выручка»."
      },
      "VisibilityResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "from": {
                "type": "string",
                "description": "Дата YYYY-MM-DD."
              },
              "to": {
                "type": "string",
                "description": "Дата YYYY-MM-DD."
              },
              "engine": {
                "type": "string",
                "enum": [
                  "yandex",
                  "google",
                  "both"
                ]
              },
              "share": {
                "type": "object",
                "properties": {
                  "availability": {
                    "type": "string"
                  },
                  "reason": {
                    "type": "string"
                  },
                  "source": {
                    "type": "string"
                  },
                  "data_as_of": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                  },
                  "data": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "required": [
                  "availability",
                  "source",
                  "data_as_of",
                  "data"
                ]
              },
              "distribution": {
                "type": "object",
                "properties": {
                  "availability": {
                    "type": "string"
                  },
                  "reason": {
                    "type": "string"
                  },
                  "source": {
                    "type": "string"
                  },
                  "data_as_of": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                  },
                  "data": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "required": [
                  "availability",
                  "source",
                  "data_as_of",
                  "data"
                ]
              },
              "sov": {
                "type": "object",
                "properties": {
                  "availability": {
                    "type": "string"
                  },
                  "reason": {
                    "type": "string"
                  },
                  "source": {
                    "type": "string"
                  },
                  "data_as_of": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                  },
                  "data": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "required": [
                  "availability",
                  "source",
                  "data_as_of",
                  "data"
                ]
              },
              "aeo": {
                "type": "object",
                "properties": {
                  "availability": {
                    "type": "string"
                  },
                  "reason": {
                    "type": "string"
                  },
                  "source": {
                    "type": "string"
                  },
                  "data_as_of": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                  },
                  "data": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "required": [
                  "availability",
                  "source",
                  "data_as_of",
                  "data"
                ]
              },
              "regions": {
                "type": "object",
                "properties": {
                  "availability": {
                    "type": "string"
                  },
                  "reason": {
                    "type": "string"
                  },
                  "source": {
                    "type": "string"
                  },
                  "data_as_of": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                  },
                  "data": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "required": [
                  "availability",
                  "source",
                  "data_as_of",
                  "data"
                ]
              }
            },
            "required": [
              "from",
              "to",
              "engine",
              "share",
              "distribution",
              "sov",
              "aeo",
              "regions"
            ]
          }
        },
        "required": [
          "data"
        ],
        "description": "Видимость: пять самостоятельных разделов."
      },
      "OverviewResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "from": {
                "type": "string",
                "description": "Дата YYYY-MM-DD."
              },
              "to": {
                "type": "string",
                "description": "Дата YYYY-MM-DD."
              },
              "blocks": {
                "type": "object",
                "properties": {
                  "strategist": {
                    "type": "object",
                    "properties": {
                      "availability": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "no_data",
                          "no_source",
                          "not_connected"
                        ]
                      },
                      "reason": {
                        "type": "string"
                      },
                      "data_as_of": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "type": "string"
                        },
                        "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                      }
                    },
                    "required": [
                      "availability",
                      "data_as_of"
                    ],
                    "additionalProperties": {}
                  },
                  "kpi": {
                    "type": "object",
                    "properties": {
                      "availability": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "no_data",
                          "no_source",
                          "not_connected"
                        ]
                      },
                      "reason": {
                        "type": "string"
                      },
                      "data_as_of": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "type": "string"
                        },
                        "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                      }
                    },
                    "required": [
                      "availability",
                      "data_as_of"
                    ],
                    "additionalProperties": {}
                  },
                  "funnel": {
                    "type": "object",
                    "properties": {
                      "availability": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "no_data",
                          "no_source",
                          "not_connected"
                        ]
                      },
                      "reason": {
                        "type": "string"
                      },
                      "data_as_of": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "type": "string"
                        },
                        "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                      }
                    },
                    "required": [
                      "availability",
                      "data_as_of"
                    ],
                    "additionalProperties": {}
                  },
                  "attention": {
                    "type": "object",
                    "properties": {
                      "availability": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "no_data",
                          "no_source",
                          "not_connected"
                        ]
                      },
                      "reason": {
                        "type": "string"
                      },
                      "data_as_of": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "type": "string"
                        },
                        "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                      }
                    },
                    "required": [
                      "availability",
                      "data_as_of"
                    ],
                    "additionalProperties": {}
                  },
                  "ads": {
                    "type": "object",
                    "properties": {
                      "availability": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "no_data",
                          "no_source",
                          "not_connected"
                        ]
                      },
                      "reason": {
                        "type": "string"
                      },
                      "data_as_of": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "type": "string"
                        },
                        "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                      }
                    },
                    "required": [
                      "availability",
                      "data_as_of"
                    ],
                    "additionalProperties": {}
                  },
                  "ai_assistants": {
                    "type": "object",
                    "properties": {
                      "availability": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "no_data",
                          "no_source",
                          "not_connected"
                        ]
                      },
                      "reason": {
                        "type": "string"
                      },
                      "data_as_of": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "type": "string"
                        },
                        "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                      }
                    },
                    "required": [
                      "availability",
                      "data_as_of"
                    ],
                    "additionalProperties": {}
                  },
                  "popular_pages": {
                    "type": "object",
                    "properties": {
                      "availability": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "no_data",
                          "no_source",
                          "not_connected"
                        ]
                      },
                      "reason": {
                        "type": "string"
                      },
                      "data_as_of": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "type": "string"
                        },
                        "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                      }
                    },
                    "required": [
                      "availability",
                      "data_as_of"
                    ],
                    "additionalProperties": {}
                  },
                  "clusters": {
                    "type": "object",
                    "properties": {
                      "availability": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "no_data",
                          "no_source",
                          "not_connected"
                        ]
                      },
                      "reason": {
                        "type": "string"
                      },
                      "data_as_of": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "type": "string"
                        },
                        "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                      }
                    },
                    "required": [
                      "availability",
                      "data_as_of"
                    ],
                    "additionalProperties": {}
                  },
                  "data_trust": {
                    "type": "object",
                    "properties": {
                      "availability": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "no_data",
                          "no_source",
                          "not_connected"
                        ]
                      },
                      "reason": {
                        "type": "string"
                      },
                      "data_as_of": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "type": "string"
                        },
                        "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                      }
                    },
                    "required": [
                      "availability",
                      "data_as_of"
                    ],
                    "additionalProperties": {}
                  },
                  "sitemap_health": {
                    "type": "object",
                    "properties": {
                      "availability": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "no_data",
                          "no_source",
                          "not_connected"
                        ]
                      },
                      "reason": {
                        "type": "string"
                      },
                      "data_as_of": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "type": "string"
                        },
                        "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                      }
                    },
                    "required": [
                      "availability",
                      "data_as_of"
                    ],
                    "additionalProperties": {}
                  },
                  "status": {
                    "type": "object",
                    "properties": {
                      "availability": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "no_data",
                          "no_source",
                          "not_connected"
                        ]
                      },
                      "reason": {
                        "type": "string"
                      },
                      "data_as_of": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "type": "string"
                        },
                        "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
                      }
                    },
                    "required": [
                      "availability",
                      "data_as_of"
                    ],
                    "additionalProperties": {}
                  }
                }
              }
            },
            "required": [
              "from",
              "to",
              "blocks"
            ]
          }
        },
        "required": [
          "data"
        ],
        "description": "Срез экрана «Обзор»: запрошенные блоки в порядке экрана."
      },
      "PulseAlert": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "topic_id": {
            "type": "string"
          },
          "topic_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "keyword": {
            "type": "string"
          },
          "horizon": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "episode_start": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "last_seen": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "score": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          },
          "volume": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          },
          "growth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "outcome": {
                  "type": "string"
                },
                "value": {
                  "anyOf": [
                    {
                      "type": "number"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "base": {
                  "anyOf": [
                    {
                      "type": "number"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": [
                "code",
                "outcome",
                "value",
                "base"
              ]
            }
          },
          "strategist_topic": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string"
                  }
                },
                "required": [
                  "id",
                  "status"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Связанная тема очереди стратега."
          }
        },
        "required": [
          "id",
          "topic_id",
          "topic_name",
          "keyword",
          "horizon",
          "status",
          "episode_start",
          "last_seen",
          "score",
          "volume",
          "growth",
          "sources",
          "strategist_topic"
        ],
        "description": "Находка «Пульса»: тема спроса, которая начала расти."
      },
      "PulseResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "period": {
                "type": "object",
                "properties": {
                  "from": {
                    "type": "string",
                    "description": "Дата YYYY-MM-DD."
                  },
                  "to": {
                    "type": "string",
                    "description": "Дата YYYY-MM-DD."
                  }
                },
                "required": [
                  "from",
                  "to"
                ]
              },
              "new_7d": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "truncated": {
                "type": "boolean"
              },
              "alerts": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PulseAlert"
                }
              },
              "data_as_of": {
                "type": "object",
                "propertyNames": {
                  "type": "string"
                },
                "additionalProperties": {
                  "type": "string"
                },
                "description": "Источник → дата, по которую его данные полны. Источник без данных в объект не попадает."
              }
            },
            "required": [
              "period",
              "new_7d",
              "truncated",
              "alerts",
              "data_as_of"
            ]
          }
        },
        "required": [
          "data"
        ],
        "description": "Срез экрана «Пульс»."
      },
      "ArticleSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор статьи."
          },
          "title": {
            "type": "string"
          },
          "slug": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "type": "string",
            "description": "draft — черновик; review — на проверке; approved — одобрена; published — опубликована; rejected — отклонена; transferred — передана в блог; external — внешняя."
          },
          "locale": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Язык статьи (ru, en, id)."
          },
          "keyword": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Главный запрос статьи."
          },
          "meta_title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "meta_description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "cover_image_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "word_count": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO 8601 UTC."
          },
          "updated_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO 8601 UTC."
          },
          "published_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO 8601 UTC."
          }
        },
        "required": [
          "id",
          "title",
          "slug",
          "status",
          "locale",
          "keyword",
          "meta_title",
          "meta_description",
          "cover_image_url",
          "word_count",
          "created_at",
          "updated_at",
          "published_at"
        ],
        "description": "Статья арендатора без содержимого (элемент списка)."
      },
      "ArticlePublication": {
        "type": "object",
        "properties": {
          "target": {
            "type": "string",
            "const": "connector",
            "description": "Куда выкладывается: модуль на вашем сайте."
          },
          "state": {
            "type": "string",
            "enum": [
              "queued",
              "applied",
              "skipped",
              "conflict",
              "failed"
            ],
            "description": "queued — в очереди или отдано модулю; applied — применено на сайте; skipped — пропущено; conflict — правка на сайте новее; failed — ошибка."
          },
          "published_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Адрес статьи на вашем сайте после применения."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Причина сбоя, до 200 знаков."
          }
        },
        "required": [
          "target",
          "state",
          "published_url",
          "error"
        ],
        "description": "Состояние последней выкладки статьи через модуль сайта."
      },
      "Article": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор статьи."
          },
          "title": {
            "type": "string"
          },
          "slug": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "type": "string",
            "description": "draft — черновик; review — на проверке; approved — одобрена; published — опубликована; rejected — отклонена; transferred — передана в блог; external — внешняя."
          },
          "locale": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Язык статьи (ru, en, id)."
          },
          "keyword": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Главный запрос статьи."
          },
          "meta_title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "meta_description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "cover_image_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "word_count": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO 8601 UTC."
          },
          "updated_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO 8601 UTC."
          },
          "published_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO 8601 UTC."
          },
          "content": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string"
                    },
                    "html": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "html"
                  ]
                }
              }
            ],
            "description": "Тело статьи в запрошенном формате: html и markdown — строка; blocks — массив блоков {type, html}. HTML очищен от скриптов, опасных ссылок и обработчиков событий. У статьи, чьё тело переехало в блог площадки, содержимое пустое."
          },
          "publication": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ArticlePublication"
              },
              {
                "type": "null"
              }
            ],
            "description": "null — статью ещё не выкладывали через модуль сайта."
          }
        },
        "required": [
          "id",
          "title",
          "slug",
          "status",
          "locale",
          "keyword",
          "meta_title",
          "meta_description",
          "cover_image_url",
          "word_count",
          "created_at",
          "updated_at",
          "published_at",
          "content",
          "publication"
        ],
        "description": "Статья арендатора с содержимым."
      },
      "ArticlePage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ArticleSummary"
            }
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Курсор следующей страницы; null — список закончился. Живёт 24 часа."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "description": "Страница списка."
      },
      "StrategistReportSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор отчёта."
          },
          "report_date": {
            "type": "string",
            "description": "Дата отчёта YYYY-MM-DD."
          },
          "report_type": {
            "type": "string",
            "enum": [
              "daily",
              "weekly"
            ],
            "description": "daily — ежедневный, weekly — недельный."
          },
          "summary_text": {
            "type": "string",
            "description": "Краткий вывод."
          },
          "actions_count": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Сколько действий рекомендовано."
          },
          "data_as_of": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "string"
            },
            "description": "Актуальность данных: по каждому показателю (ключ) дата последних данных YYYY-MM-DD; ключ snapshot — дата снимка аналитики, на котором построен отчёт. Пусто, если снимка нет."
          },
          "delivered_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Когда отчёт доставлен владельцу; null — ещё нет. ISO 8601 UTC."
          }
        },
        "required": [
          "id",
          "report_date",
          "report_type",
          "summary_text",
          "actions_count",
          "data_as_of",
          "delivered_at"
        ],
        "description": "Шапка отчёта стратега (элемент списка)."
      },
      "StrategistReportAction": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "priority": {
            "type": "string",
            "description": "Приоритет действия (high, medium, low)."
          },
          "rationale": {
            "type": "string",
            "description": "Обоснование. Названия конкурентов в нём скрыты."
          },
          "target_ref": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Ссылка на цель (статья, товар, кампания); null, если цели нет или это конкурент."
          },
          "expected_effect": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "metric": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "delta": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "horizon_days": {
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "metric",
                  "delta",
                  "horizon_days"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Ожидаемый эффект; null, если стратег его не назвал."
          },
          "check_after_days": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ],
            "description": "Через сколько дней проверить результат."
          },
          "basis": {
            "type": "string",
            "enum": [
              "observed_pattern",
              "own_measured",
              "research",
              "hypothesis"
            ],
            "description": "На чём стоит вывод: observed_pattern — наблюдали у других; own_measured — измерили у вас; research — исследование; hypothesis — гипотеза."
          }
        },
        "required": [
          "title",
          "priority",
          "rationale",
          "target_ref",
          "expected_effect",
          "check_after_days",
          "basis"
        ],
        "description": "Рекомендованное действие."
      },
      "StrategistEvidence": {
        "type": "object",
        "properties": {
          "actions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991,
                  "description": "Номер действия в actions (с нуля)."
                },
                "status": {
                  "type": "string",
                  "description": "supported — найдены подтверждающие источники; unsupported — нет."
                },
                "basis": {
                  "type": "string",
                  "enum": [
                    "observed_pattern",
                    "own_measured",
                    "research",
                    "hypothesis"
                  ],
                  "description": "На чём стоит вывод: observed_pattern — наблюдали у других; own_measured — измерили у вас; research — исследование; hypothesis — гипотеза."
                },
                "items": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "ref": {
                        "type": "string"
                      },
                      "kind": {
                        "type": "string"
                      },
                      "label": {
                        "type": "string",
                        "description": "Подпись источника; чужие домены заменены заглушкой."
                      },
                      "url": {
                        "type": "string"
                      },
                      "quote": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "ref",
                      "kind",
                      "label"
                    ]
                  }
                }
              },
              "required": [
                "index",
                "status",
                "basis",
                "items"
              ]
            }
          },
          "validation": {
            "description": "Итог проверки доказательств. relevance_checked всегда false: проверяются ссылки и цитаты, а не смысл.",
            "type": "object",
            "properties": {
              "refs_valid": {
                "type": "boolean"
              },
              "excerpts_valid": {
                "type": "boolean"
              },
              "relevance_checked": {
                "type": "boolean",
                "const": false
              },
              "limitations": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "required": [
              "refs_valid",
              "excerpts_valid",
              "relevance_checked",
              "limitations"
            ]
          }
        },
        "required": [
          "actions"
        ],
        "description": "Доказательства по действиям. Дословные формулировки конкурентов не отдаются."
      },
      "StrategistReport": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "report_date": {
            "type": "string"
          },
          "report_type": {
            "type": "string",
            "enum": [
              "daily",
              "weekly"
            ]
          },
          "summary_text": {
            "type": "string"
          },
          "data_as_of": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "string"
            },
            "description": "Актуальность данных: по каждому показателю (ключ) дата последних данных YYYY-MM-DD; ключ snapshot — дата снимка аналитики, на котором построен отчёт. Пусто, если снимка нет."
          },
          "highlights": {
            "type": "array",
            "items": {},
            "description": "Что идёт хорошо."
          },
          "concerns": {
            "type": "array",
            "items": {},
            "description": "Что беспокоит."
          },
          "actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StrategistReportAction"
            }
          },
          "evidence": {
            "$ref": "#/components/schemas/StrategistEvidence"
          }
        },
        "required": [
          "id",
          "report_date",
          "report_type",
          "summary_text",
          "data_as_of",
          "highlights",
          "concerns",
          "actions",
          "evidence"
        ],
        "description": "Отчёт стратега целиком. Снимок аналитики, модель и стоимость не отдаются."
      },
      "StrategistReportPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StrategistReportSummary"
            }
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Курсор следующей страницы; null — список закончился. Живёт 24 часа."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "description": "Страница списка."
      },
      "StrategistTopic": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "rationale": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Почему тема предложена. Для тем от конкурентов домены скрыты."
          },
          "trend_score": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Оценка тренда; null — не оценивалась."
          },
          "source": {
            "type": "string",
            "description": "Откуда тема: planner, competitors, chat и др."
          },
          "status": {
            "type": "string",
            "enum": [
              "proposed",
              "approved",
              "generating",
              "generated",
              "rejected",
              "duplicate",
              "expired"
            ],
            "description": "proposed — ждёт решения; approved — одобрена; generating — статья создаётся; generated — статья создана; rejected — отклонена; duplicate — дубль; expired — срок вышел."
          },
          "cluster_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "generated_article_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Идентификатор созданной статьи (GET /articles/{id})."
          },
          "proposed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO 8601 UTC."
          },
          "decided_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO 8601 UTC."
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO 8601 UTC."
          }
        },
        "required": [
          "id",
          "title",
          "rationale",
          "trend_score",
          "source",
          "status",
          "cluster_id",
          "generated_article_id",
          "proposed_at",
          "decided_at",
          "expires_at"
        ],
        "description": "Тема в очереди стратега."
      },
      "StrategistTopicPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StrategistTopic"
            }
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Курсор следующей страницы; null — список закончился. Живёт 24 часа."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "description": "Страница списка."
      },
      "StrategistAction": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Сессия разговора, в которой предложено действие."
          },
          "type": {
            "type": "string",
            "const": "propose_topic",
            "description": "Вид действия. В v1 — только propose_topic."
          },
          "title": {
            "type": "string",
            "description": "Заголовок предлагаемой темы."
          },
          "status": {
            "type": "string",
            "enum": [
              "proposed",
              "confirmed",
              "executed",
              "failed",
              "cancelled",
              "expired"
            ],
            "description": "proposed — ждёт подтверждения; confirmed — подтверждено, выполняется; executed — выполнено; failed — не удалось; cancelled — отменено; expired — срок вышел (7 суток)."
          },
          "result": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "topic_id": {
                    "type": "string"
                  }
                },
                "required": [
                  "topic_id"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Результат выполненного действия: созданная тема."
          },
          "error": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string"
                  },
                  "message": {
                    "type": "string"
                  }
                },
                "required": [
                  "code",
                  "message"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Причина сбоя при status = failed."
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO 8601 UTC."
          },
          "decided_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO 8601 UTC."
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Когда ожидание истекает: создание + 7 суток. ISO 8601 UTC."
          }
        },
        "required": [
          "id",
          "session_id",
          "type",
          "title",
          "status",
          "result",
          "error",
          "created_at",
          "decided_at",
          "expires_at"
        ],
        "description": "Действие стратега, предложенное в вашей сессии и ждущее решения."
      },
      "StrategistActionPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StrategistAction"
            }
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Курсор следующей страницы; null — список закончился. Живёт 24 часа."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "description": "Страница списка."
      },
      "Conversation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор диалога (uuid)."
          },
          "channel": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Тип канала: api, telegram, website …"
          },
          "contact_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Идентификатор контакта (клиента) на платформе."
          },
          "external_customer_id": {
            "description": "Идентификатор клиента в вашей системе. Только у канала api; у остальных каналов null (внешний идентификатор мессенджера не раскрывается). Персональные данные: в чтении приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "type": "string",
            "description": "Состояние диалога: open, handoff_pending, resolved, closed … Набор значений может расширяться — не считайте список закрытым."
          },
          "mode": {
            "type": "string",
            "enum": [
              "ai",
              "operator"
            ],
            "description": "Кто ведёт диалог: ai — отвечает ИИ (режимы auto и supervised), operator — отвечает человек (copilot и manual)."
          },
          "language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Язык диалога (ISO 639-1); null — не определён."
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Начало диалога, ISO 8601 UTC."
          },
          "updated_at": {
            "type": "string",
            "description": "Последнее изменение или сообщение, ISO 8601 UTC. По нему идёт обход. Счётчик непрочитанного его не меняет."
          },
          "_enc": {
            "description": "Только ячейки EN и ID, когда действует формат JWE: поля этого объекта, значения которых заменены строкой компактного JWE (открытый текст — JSON исходного значения).",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "id",
          "channel",
          "contact_id",
          "status",
          "mode",
          "language",
          "created_at",
          "updated_at"
        ],
        "description": "Диалог. Содержит персональные данные (external_customer_id)."
      },
      "MessageAttachment": {
        "type": "object",
        "properties": {
          "type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Вид содержимого: image, file, audio …"
          },
          "url": {
            "type": "string",
            "description": "Временная подписанная ссылка на файл (скачивание без ключа API). Не сохраняйте ссылку: запросите сообщение заново."
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Когда ссылка перестанет работать, ISO 8601 UTC (около часа); null — постоянный путь."
          },
          "name": {
            "description": "Имя файла (вложения, загруженные через виджет или оператором).",
            "type": "string"
          },
          "size": {
            "description": "Размер, байт.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "type",
          "url",
          "expires_at"
        ],
        "description": "Вложение сообщения."
      },
      "Message": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор сообщения (uuid)."
          },
          "conversation_id": {
            "type": "string",
            "description": "Диалог."
          },
          "sender": {
            "type": "string",
            "enum": [
              "customer",
              "ai",
              "operator",
              "system"
            ],
            "description": "Отправитель: customer — клиент, ai — ИИ, operator — оператор, system — служебное."
          },
          "content_type": {
            "type": "string",
            "description": "Вид содержимого: text, image, file …"
          },
          "content": {
            "description": "Текст; null — текста нет (только вложение) или сообщение удалено. Персональные данные: в чтении приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "attachments": {
            "description": "Вложения: до пяти файлов на сообщение. Персональные данные: в чтении приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/MessageAttachment"
                }
              },
              {
                "type": "string"
              }
            ]
          },
          "cards": {
            "description": "Карточки товаров сообщения (до трёх); поля нет — карточек нет. Персональных данных не содержат.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MessageCard"
            }
          },
          "deleted": {
            "type": "boolean",
            "description": "true — сообщение удалено (приходит только при include_deleted=true; текста и вложений нет)."
          },
          "created_at": {
            "type": "string",
            "description": "Время сообщения, ISO 8601 UTC."
          },
          "_enc": {
            "description": "Только ячейки EN и ID, когда действует формат JWE: поля этого объекта, значения которых заменены строкой компактного JWE (открытый текст — JSON исходного значения).",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "id",
          "conversation_id",
          "sender",
          "content_type",
          "deleted",
          "created_at"
        ],
        "description": "Сообщение диалога. Содержит персональные данные клиента (текст, вложения)."
      },
      "ConversationPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Conversation"
            }
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Курсор следующей страницы; null — список закончился. Живёт 24 часа."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "description": "Страница списка."
      },
      "MessagePage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Message"
            }
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Курсор следующей страницы; null — список закончился. Живёт 24 часа."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "description": "Страница списка."
      },
      "ConversationCreate": {
        "type": "object",
        "properties": {
          "external_customer_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "Стабильный идентификатор клиента в вашей системе (не телефон и не почта). По нему платформа находит или заводит контакт и диалог; идентификаторы разных интеграций не смешиваются."
          },
          "name": {
            "description": "Имя клиента. Пишется только в пустое поле контакта.",
            "type": "string",
            "maxLength": 120
          },
          "email": {
            "description": "Почта клиента. Пишется только в пустое поле контакта.",
            "type": "string",
            "maxLength": 254
          },
          "phone": {
            "description": "Телефон в международном формате (+…). Пишется только в пустое поле контакта.",
            "type": "string",
            "maxLength": 32
          },
          "language": {
            "description": "Язык нового диалога (ISO 639-1). Язык ответа ИИ ограничен языками ячейки.",
            "type": "string",
            "minLength": 2,
            "maxLength": 2
          }
        },
        "required": [
          "external_customer_id"
        ],
        "description": "Диалог клиента вашего канала. Неизвестные поля — 422."
      },
      "MessageCreate": {
        "type": "object",
        "properties": {
          "content": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4000,
            "description": "Текст реплики клиента, до 4000 знаков."
          },
          "ai_reply": {
            "default": "auto",
            "description": "auto — запросить ответ ИИ-продажника (нужна область ai_seller:invoke; без неё сообщение только сохраняется); none — только сохранить сообщение.",
            "type": "string",
            "enum": [
              "auto",
              "none"
            ]
          }
        },
        "required": [
          "content",
          "ai_reply"
        ],
        "description": "Сообщение клиента. Вложения в v1 не принимаются. Неизвестные поля — 422."
      },
      "AiReply": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "replied",
              "queued",
              "queued_for_review",
              "skipped"
            ],
            "description": "replied — ИИ ответил (ответ — отдельное сообщение диалога); queued — ответ готовится (операция); queued_for_review — ответ ИИ стал черновиком и ждёт оператора (режим надзора); skipped — ИИ не ответит, причина в reason."
          },
          "reason": {
            "description": "Только при skipped: operator_active, spam, flow_reply, ai_unavailable_handoff, no_agent, daily_limit, insufficient_funds, upstream_unavailable, quota_exceeded, not_requested. Список может расширяться.",
            "type": "string",
            "enum": [
              "operator_active",
              "spam",
              "flow_reply",
              "ai_unavailable_handoff",
              "no_agent",
              "daily_limit",
              "insufficient_funds",
              "upstream_unavailable",
              "quota_exceeded",
              "not_requested"
            ]
          }
        },
        "required": [
          "status"
        ],
        "description": "Что стало с ответом ИИ на сообщение клиента."
      },
      "MessageAccepted": {
        "type": "object",
        "properties": {
          "message_id": {
            "type": "string",
            "description": "Идентификатор записанного сообщения клиента."
          },
          "conversation_id": {
            "type": "string",
            "description": "Диалог."
          },
          "ai_reply": {
            "$ref": "#/components/schemas/AiReply"
          },
          "reply": {
            "description": "Только при replied: идентификатор ответа ИИ. Текста в ответе нет — прочитайте его GET /conversations/{id}/messages (выдача ПДн в журнале).",
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              }
            },
            "required": [
              "id"
            ]
          },
          "operation": {
            "description": "Операция conversation.ai_reply: при 202 — queued или running, при 200 — завершена (usage.cost — списано с кошелька в его валюте). Нет, если ответ ИИ не запрашивался.",
            "$ref": "#/components/schemas/Operation"
          }
        },
        "required": [
          "message_id",
          "conversation_id",
          "ai_reply"
        ],
        "description": "Сообщение клиента принято."
      },
      "LeadFlags": {
        "type": "object",
        "properties": {
          "buy_intent": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Намерение купить; null — модель не уверена."
          },
          "support": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Обращение в поддержку, а не покупка; null — не уверена."
          },
          "supplier": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Поставщик или рекламодатель, а не клиент; true уводит лид в архив (ai_not_client)."
          }
        },
        "required": [
          "buy_intent",
          "support",
          "supplier"
        ],
        "description": "Флаги ИИ по переписке. true/false ставятся только при уверенности модели."
      },
      "LeadScore": {
        "type": "object",
        "properties": {
          "score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Балл 0–100."
          },
          "grade": {
            "type": "string",
            "enum": [
              "A",
              "B",
              "C",
              "D"
            ],
            "description": "Класс: A — 75 и выше, B — 50–74, C — 25–49, D — ниже 25."
          },
          "reason": {
            "description": "Объяснение оценки; null, пока не записано. Персональные данные: приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "flags": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LeadFlags"
              },
              {
                "type": "null"
              }
            ]
          },
          "source": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "ai",
                  "external",
                  "manual"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Кто оценил: ai, external или manual; null — неизвестно."
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Модель, поставившая флаги; null, если оценка не ИИ."
          },
          "scored_at": {
            "anyOf": [
              {
                "type": "string",
                "description": "Когда выставлена оценка. ISO 8601 UTC."
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "score",
          "grade",
          "flags",
          "source",
          "model",
          "scored_at"
        ],
        "description": "Оценка лида. null у лида, которого ещё не оценивали."
      },
      "LeadContact": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор контакта."
          },
          "first_name": {
            "description": "Имя (contact.first_name). Персональные данные: приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "last_name": {
            "description": "Фамилия (contact.last_name). Персональные данные: приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "email": {
            "description": "Почта (contact.email). Персональные данные: приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "phone": {
            "description": "Телефон (contact.phone). Персональные данные: приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "geo_country": {
            "description": "Страна по IP, ISO 3166-1 alpha-2 (contact.geo_country). Персональные данные: приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "geo_city": {
            "description": "Город по IP (contact.geo_city). Персональные данные: приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "tags"
        ],
        "description": "Контакт лида. Поля с персональными данными приходят, только если названы в fields=; выдача пишется в журнал выдач."
      },
      "LeadAttribution": {
        "type": "object",
        "properties": {
          "utm_source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "utm_medium": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "utm_campaign": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "first_page": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Страница первого визита."
          },
          "referrer": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "utm_source",
          "utm_medium",
          "utm_campaign",
          "first_page",
          "referrer"
        ],
        "description": "Откуда пришёл лид (первое касание). null, если следов нет."
      },
      "Lead": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор лида."
          },
          "external_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Идентификатор во внешней CRM; null, пока внешняя CRM не подключена."
          },
          "external_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "version": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ],
            "description": "Версия для If-Match; null, пока в базе нет колонки версии — используйте etag."
          },
          "etag": {
            "type": "string",
            "description": "Метка версии (совпадает с заголовком ETag карточки)."
          },
          "status": {
            "type": "string",
            "enum": [
              "new",
              "qualified",
              "proposal",
              "negotiation",
              "won",
              "lost"
            ],
            "description": "Один из шести канонических статусов. Архив — флаг archived, не статус."
          },
          "archived": {
            "type": "boolean",
            "description": "Лид в архиве."
          },
          "archived_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Причина архива, например ai_not_client."
          },
          "owner": {
            "type": "string",
            "enum": [
              "internal",
              "external"
            ],
            "description": "Где живёт лид: internal — в нашей CRM."
          },
          "title": {
            "description": "Заголовок лида. Персональные данные: приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "assigned_to": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Идентификатор ответственного сотрудника."
          },
          "value": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Money"
              },
              {
                "type": "null"
              }
            ]
          },
          "product_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "course_slug": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "contact": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LeadContact"
              },
              {
                "type": "null"
              }
            ]
          },
          "conversation_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "attribution": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LeadAttribution"
              },
              {
                "type": "null"
              }
            ]
          },
          "score": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LeadScore"
              },
              {
                "type": "null"
              }
            ]
          },
          "flags": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LeadFlags"
              },
              {
                "type": "null"
              }
            ]
          },
          "intent": {
            "description": "Намерение клиента. Персональные данные: приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "ai_summary": {
            "description": "ИИ-сводка переписки. Персональные данные: приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "next_action": {
            "description": "Следующее действие. Персональные данные: приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "next_action_at": {
            "anyOf": [
              {
                "type": "string",
                "description": "ISO 8601 UTC."
              },
              {
                "type": "null"
              }
            ]
          },
          "lost_reason": {
            "description": "Причина проигрыша. Персональные данные: приходит, только если названо в fields=. На ячейках EN и ID в формате JWE — строка компактного JWE.",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "qualified_at": {
            "anyOf": [
              {
                "type": "string",
                "description": "ISO 8601 UTC."
              },
              {
                "type": "null"
              }
            ]
          },
          "won_at": {
            "anyOf": [
              {
                "type": "string",
                "description": "ISO 8601 UTC."
              },
              {
                "type": "null"
              }
            ]
          },
          "lost_at": {
            "anyOf": [
              {
                "type": "string",
                "description": "ISO 8601 UTC."
              },
              {
                "type": "null"
              }
            ]
          },
          "last_activity_at": {
            "anyOf": [
              {
                "type": "string",
                "description": "ISO 8601 UTC."
              },
              {
                "type": "null"
              }
            ]
          },
          "created_at": {
            "type": "string",
            "description": "Создан. ISO 8601 UTC."
          },
          "updated_at": {
            "type": "string",
            "description": "Изменён. ISO 8601 UTC."
          },
          "_enc": {
            "description": "Только ячейки EN и ID, когда действует формат JWE: пути полей этого объекта, значения которых заменены строкой компактного JWE (открытый текст — JSON исходного значения).",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "id",
          "external_id",
          "external_url",
          "version",
          "etag",
          "status",
          "archived",
          "archived_reason",
          "owner",
          "source",
          "assigned_to",
          "value",
          "product_id",
          "course_slug",
          "contact",
          "conversation_id",
          "attribution",
          "score",
          "flags",
          "next_action_at",
          "qualified_at",
          "won_at",
          "lost_at",
          "last_activity_at",
          "created_at",
          "updated_at"
        ],
        "description": "Лид арендатора. С fields= приходят только перечисленные поля (и id)."
      },
      "LeadPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Lead"
            }
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Курсор следующей страницы; null — список закончился. Живёт 24 часа."
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "description": "Страница списка."
      }
    }
  },
  "x-scopes": {
    "conversations:read": "Требует права владельца интеграции: conversations.view.",
    "conversations:write": "Требует права владельца интеграции: conversations.manage.",
    "ai_seller:invoke": "Требует права владельца интеграции: conversations.manage.",
    "leads:read": "Требует права владельца интеграции: crm.leads.view.",
    "leads:write": "Требует права владельца интеграции: crm.leads.edit.",
    "leads:score": "Требует права владельца интеграции: crm.leads.edit.",
    "analytics:read": "Требует права владельца интеграции: analytics.view или seo.view.",
    "analytics:write": "Требует права владельца интеграции: seo.manage.",
    "dashboards:read": "Требует права владельца интеграции: analytics.view или seo.view.",
    "articles:read": "Требует права владельца интеграции: seo.view.",
    "articles:write": "Требует права владельца интеграции: seo.manage.",
    "articles:generate": "Требует права владельца интеграции: seo.manage.",
    "strategist:read": "Требует права владельца интеграции: seo.view.",
    "strategist:write": "Требует права владельца интеграции: seo.manage.",
    "strategist:chat": "Требует права владельца интеграции: seo.manage.",
    "webhooks:manage": "Требует права владельца интеграции: settings.integrations.",
    "channels:read": "Требует права владельца интеграции: settings.channels.",
    "channels:write": "Требует права владельца интеграции: settings.channels.",
    "cards:read": "Требует права владельца интеграции: settings.products.",
    "cards:write": "Требует права владельца интеграции: settings.products."
  },
  "x-page-limit": {
    "default": 25,
    "max": 100
  },
  "x-error-catalog": [
    {
      "code": "bad_request",
      "status": 400,
      "title": "Bad request",
      "group": "request",
      "when": "Тело запроса не JSON либо неверный Content-Type или заголовок.",
      "action": "Исправьте запрос; повтор без изменений бессмыслен."
    },
    {
      "code": "idempotency_key_required",
      "status": 400,
      "title": "Idempotency-Key header is required",
      "group": "request",
      "when": "Для этого запроса обязателен заголовок Idempotency-Key.",
      "action": "Добавьте заголовок со значением, уникальным для операции."
    },
    {
      "code": "integration_inactive",
      "status": 401,
      "title": "Integration is not active",
      "group": "auth",
      "when": "Интеграция приостановлена или отозвана, либо её владелец потерял доступ. Ключ верный, дело не в нём.",
      "action": "Проверьте интеграцию в кабинете (Настройки → API)."
    },
    {
      "code": "invalid_api_key",
      "status": 401,
      "title": "Invalid API key",
      "group": "auth",
      "when": "Заголовка нет, ключ не найден, отозван или истёк. Ответ намеренно одинаков во всех случаях: платформа не подтверждает, что такой ключ существовал.",
      "action": "Проверьте ключ; срок действия виден в GET /me (key.expires_at). При необходимости выпустите новый. Автоматически не повторяйте."
    },
    {
      "code": "wrong_cell",
      "status": 401,
      "title": "Key belongs to another cell",
      "group": "auth",
      "when": "Ключ выпущен в другой ячейке. В ответе есть поле correct_base_url.",
      "action": "Используйте базовый адрес из correct_base_url."
    },
    {
      "code": "insufficient_funds",
      "status": 402,
      "title": "Insufficient funds",
      "group": "money",
      "when": "На кошельке недостаточно средств для платной операции.",
      "action": "Пополните кошелёк."
    },
    {
      "code": "spend_limit_reached",
      "status": 402,
      "title": "Spend limit reached",
      "group": "money",
      "when": "Достигнут суточный предел трат интеграции (сутки по часовому поясу ячейки) либо оценка стоимости операции выше максимума одной операции (по умолчанию 100 в валюте кошелька). Предел одновременных операций — отдельный код concurrency_limit (429).",
      "action": "Дождитесь следующих суток или повысьте предел; для максимума операции — выберите агенту модель дешевле или уменьшите max_tokens. Предел и траты — GET /me (wallet.daily_spend, limits.max_operation_cost)."
    },
    {
      "code": "wallet_suspended",
      "status": 402,
      "title": "Wallet is suspended",
      "group": "money",
      "when": "Обмен остановлен: баланс кошелька арендателя отрицателен или кошелёк заблокирован. Отвечают 402 все маршруты, кроме GET /me и GET /wallet; входящие данные (события, сообщения, лиды) не принимаются, исходящие вебхуки откладываются. В ответе есть topup_url и balance.",
      "action": "Пополните кошелёк по topup_url (нужен вход сотрудника с правом пополнения). Обмен возобновится сам в течение 30 секунд после зачисления; состояние видно в GET /wallet. События не теряются: вебхуки доставятся после пополнения."
    },
    {
      "code": "feature_not_in_plan",
      "status": 403,
      "title": "API is not included in the plan",
      "group": "auth",
      "when": "Лицензия или тариф не включают API (api_access) либо конкретную возможность.",
      "action": "Смените тариф или обратитесь в поддержку."
    },
    {
      "code": "ip_not_allowed",
      "status": 403,
      "title": "IP address is not allowed",
      "group": "auth",
      "when": "Запрос пришёл с адреса вне списка интеграции.",
      "action": "Добавьте адрес в список или вызывайте с разрешённого."
    },
    {
      "code": "pii_transfer_not_allowed",
      "status": 403,
      "title": "Personal data transfer is not allowed",
      "group": "auth",
      "when": "Ячейка RU: запрошена область с персональными данными, а список IP или страна размещения принимающей системы не разрешают передачу.",
      "action": "Разместите принимающую систему в РФ, задайте список IP либо не запрашивайте области с ПДн."
    },
    {
      "code": "scope_missing",
      "status": 403,
      "title": "Scope is missing",
      "group": "auth",
      "when": "Нет нужной области, либо она срезана ролью интеграции, правами владельца или тарифом.",
      "action": "Проверьте области в GET /me (key.scopes) и права владельца."
    },
    {
      "code": "tenant_inactive",
      "status": 403,
      "title": "Account is not active",
      "group": "auth",
      "when": "Учётная запись арендатора не активна.",
      "action": "Обратитесь в поддержку."
    },
    {
      "code": "not_found",
      "status": 404,
      "title": "Not found",
      "group": "request",
      "when": "Ресурса нет либо он принадлежит другому арендатору (для клиента это одно и то же).",
      "action": "Проверьте идентификатор."
    },
    {
      "code": "method_not_allowed",
      "status": 405,
      "title": "Method not allowed",
      "group": "request",
      "when": "Метод не поддерживается этим адресом.",
      "action": "Проверьте справочник."
    },
    {
      "code": "channel_not_configured",
      "status": 409,
      "title": "Integration channel is not configured",
      "group": "request",
      "when": "У интеграции нет канала api: заводить диалоги и принимать сообщения клиентов некуда. Канал подключается в кабинете (Настройки → API → «Подключить канал чата»).",
      "action": "Подключите канал в кабинете; channel_id виден в GET /me. Повтор без этого бессмыслен."
    },
    {
      "code": "encryption_key_required",
      "status": 409,
      "title": "Encryption key is required",
      "group": "request",
      "when": "Интеграция настроена выдавать поля с персональными данными только в формате JWE (режим required), а открытый ключ получателя не зарегистрирован. Бывает только на ячейках EN и ID.",
      "action": "Зарегистрируйте свой открытый ключ (PUT /me/encryption-key или кабинет) либо запросите поля без персональных данных через fields=."
    },
    {
      "code": "idempotency_conflict",
      "status": 409,
      "title": "Idempotency key was used with a different request",
      "group": "request",
      "when": "Idempotency-Key уже использован с другим телом запроса.",
      "action": "Для нового запроса используйте новый ключ либо повторите прежний запрос."
    },
    {
      "code": "invalid_state",
      "status": 409,
      "title": "Invalid state",
      "group": "request",
      "when": "Действие недопустимо в текущем состоянии ресурса.",
      "action": "Перечитайте ресурс и проверьте его состояние."
    },
    {
      "code": "operation_in_progress",
      "status": 409,
      "title": "Operation is in progress",
      "group": "request",
      "when": "Параллельный повтор: операция с этим Idempotency-Key ещё выполняется.",
      "action": "Подождите Retry-After либо опросите операцию."
    },
    {
      "code": "precondition_failed",
      "status": 412,
      "title": "Precondition failed",
      "group": "request",
      "when": "If-Match не совпал с текущей версией ресурса: его изменили.",
      "action": "Перечитайте ресурс и примените правку к актуальной версии."
    },
    {
      "code": "payload_too_large",
      "status": 413,
      "title": "Payload too large",
      "group": "request",
      "when": "Тело запроса больше 256 КБ.",
      "action": "Уменьшите тело."
    },
    {
      "code": "validation_failed",
      "status": 422,
      "title": "Validation failed",
      "group": "request",
      "when": "Параметры не прошли проверку; подробности в errors[].",
      "action": "Исправьте запрос по errors[]."
    },
    {
      "code": "precondition_required",
      "status": 428,
      "title": "Precondition required",
      "group": "request",
      "when": "Для изменения не передан If-Match.",
      "action": "Передайте версию из последнего чтения."
    },
    {
      "code": "concurrency_limit",
      "status": 429,
      "title": "Too many concurrent operations",
      "group": "money",
      "when": "У интеграции уже выполняется наибольшее число одновременных платных операций (по умолчанию 5, значение — GET /me, limits.paid_concurrency).",
      "action": "Подождите Retry-After или завершения текущих операций и повторите с тем же Idempotency-Key. Ставьте реплики в очередь у себя."
    },
    {
      "code": "rate_limited",
      "status": 429,
      "title": "Too many requests",
      "group": "money",
      "when": "Превышен предел частоты запросов.",
      "action": "Подождите Retry-After секунд и повторите с тем же Idempotency-Key."
    },
    {
      "code": "internal_error",
      "status": 500,
      "title": "Internal error",
      "group": "platform",
      "when": "Внутренняя ошибка платформы. Подробности в ответе не раскрываются.",
      "action": "Повторите с паузой; при повторении сообщите request_id в поддержку."
    },
    {
      "code": "service_unavailable",
      "status": 503,
      "title": "Service unavailable",
      "group": "platform",
      "when": "Хранилище пределов или база недоступны, либо API не включён на ячейке: безопасно принять запись нельзя.",
      "action": "Повторите с паузой и тем же Idempotency-Key."
    },
    {
      "code": "upstream_unavailable",
      "status": 503,
      "title": "Upstream service unavailable",
      "group": "platform",
      "when": "Недоступна внешняя зависимость, например языковая модель.",
      "action": "Повторите с паузой и тем же Idempotency-Key."
    }
  ]
}
