{
  "openapi": "3.1.0",
  "info": {
    "title": "Публичный API Sapport",
    "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": "Вебхуки"
    }
  ],
  "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"
        ]
      }
    },
    "/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"
        ]
      }
    },
    "/conversations": {
      "get": {
        "operationId": "listConversations",
        "tags": [
          "conversations"
        ],
        "summary": "Список диалогов",
        "description": "Диалоги арендатора по возрастанию updated_at, постранично по курсору: чтобы забрать изменения, храните updated_at последнего увиденного и передавайте его в updated_after. Диалогов с мягким удалением нет, поэтому include_deleted сейчас ничего не добавляет. Ответ содержит персональные данные клиентов: каждая выдача записывается в журнал выдач, на RU нужны список разрешённых IP и страна получателя RU (иначе 403 pii_transfer_not_allowed). Диалоги личных ящиков и чаты кабинета ученика не отдаются.",
        "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"
            }
          }
        ],
        "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"
                }
              }
            }
          },
          "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"
        ]
      }
    },
    "/conversations/{id}": {
      "get": {
        "operationId": "getConversation",
        "tags": [
          "conversations"
        ],
        "summary": "Получить диалог",
        "description": "Один диалог. Чужой, несуществующий и недоступный публичному API диалог одинаково отвечает not_found. Ответ содержит персональные данные клиентов: каждая выдача записывается в журнал выдач, на RU нужны список разрешённых IP и страна получателя RU (иначе 403 pii_transfer_not_allowed). Диалоги личных ящиков и чаты кабинета ученика не отдаются.",
        "security": [
          {
            "bearerAuth": [
              "conversations:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор диалога (uuid)."
            }
          }
        ],
        "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"
                }
              }
            }
          },
          "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/{id}/messages": {
      "get": {
        "operationId": "listConversationMessages",
        "tags": [
          "conversations"
        ],
        "summary": "Сообщения диалога",
        "description": "Сообщения диалога от старых к новым, постранично по курсору (created_at, id). Внутренние заметки операторов не отдаются. Вложения — временные подписанные ссылки; внешние адреса файлов мессенджеров не раскрываются. Ответ содержит персональные данные клиентов: каждая выдача записывается в журнал выдач, на RU нужны список разрешённых IP и страна получателя RU (иначе 403 pii_transfer_not_allowed). Диалоги личных ящиков и чаты кабинета ученика не отдаются.",
        "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"
            }
          }
        ],
        "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"
                }
              }
            }
          },
          "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"
        ]
      }
    },
    "/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) не хранятся. Ответ содержит персональные данные контакта: каждая выдача записывается в журнал выдач, на RU нужны разрешённые адреса и страна получателя RU (иначе 403 pii_transfer_not_allowed).",
        "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"
            }
          }
        ],
        "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"
                }
              }
            }
          },
          "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"
        ]
      }
    },
    "/leads/{id}": {
      "get": {
        "operationId": "getLead",
        "tags": [
          "leads"
        ],
        "summary": "Получить лид",
        "description": "Карточка лида: контакт, атрибуция, оценка (балл, класс A–D, причина, флаги), версия. Заголовок ETag равен полю etag. Ответ содержит персональные данные контакта: каждая выдача записывается в журнал выдач, на RU нужны разрешённые адреса и страна получателя RU (иначе 403 pii_transfer_not_allowed).",
        "security": [
          {
            "bearerAuth": [
              "leads:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Идентификатор лида (uuid)."
            }
          }
        ],
        "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"
                }
              }
            }
          },
          "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"
        ]
      }
    },
    "/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": "Создаёт подписку на события. Секрет подписи показывается один раз, в этом ответе. Адрес проверяется защитой от 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/WebhookWithSecret"
                }
              }
            }
          },
          "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}/rotate-secret": {
      "post": {
        "operationId": "rotateWebhookSecret",
        "tags": [
          "webhooks"
        ],
        "summary": "Заменить секрет",
        "description": "Выпускает новый секрет (показывается один раз). 24 часа действуют оба секрета, каждая доставка подписана обоими.",
        "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": {
          "200": {
            "description": "Подписка с новым секретом.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookWithSecret"
                }
              }
            }
          },
          "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": "Возможные коды: 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",
          "idempotency_key_required",
          "idempotency_conflict",
          "operation_in_progress"
        ]
      }
    },
    "/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"
        ]
      }
    }
  },
  "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",
              "precondition_failed",
              "precondition_required",
              "payload_too_large",
              "validation_failed",
              "rate_limited",
              "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 на создающий запрос."
      },
      "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"
                  ]
                },
                "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": "Одновременных платных операций на арендатора."
              }
            },
            "required": [
              "read_per_min",
              "write_per_min",
              "paid_per_min",
              "paid_concurrency"
            ],
            "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": {
                "type": "object",
                "properties": {
                  "limit": {
                    "anyOf": [
                      {
                        "$ref": "#/components/schemas/Money"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Суточный предел трат интеграции; null — не задан."
                  },
                  "used": {
                    "$ref": "#/components/schemas/Money"
                  }
                },
                "required": [
                  "limit",
                  "used"
                ]
              }
            },
            "required": [
              "balance",
              "state",
              "exchange",
              "topup_url",
              "daily_spend"
            ],
            "description": "Кошелёк арендатора (ИИ-операции)."
          },
          "crm_mode": {
            "type": "string",
            "description": "Режим CRM арендатора: \"internal\" (наша CRM) или внешняя система."
          }
        },
        "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."
          },
          "secret_rotated_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Время последней ротации секрета; null — не менялся."
          },
          "previous_secret_expires_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Пока окно ротации открыто (24 часа) — когда прежний секрет перестанет действовать; иначе null."
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "include_pii",
          "description",
          "status",
          "created_at",
          "updated_at",
          "secret_rotated_at",
          "previous_secret_expires_at"
        ],
        "description": "Подписка на события. Секрет в таких ответах не возвращается."
      },
      "WebhookWithSecret": {
        "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."
          },
          "secret_rotated_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Время последней ротации секрета; null — не менялся."
          },
          "previous_secret_expires_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Пока окно ротации открыто (24 часа) — когда прежний секрет перестанет действовать; иначе null."
          },
          "secret": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Секрет подписи: показывается ОДИН раз, в ответе создания или ротации. При идемпотентном повторе запроса — null: сохраните секрет из первого ответа."
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "include_pii",
          "description",
          "status",
          "created_at",
          "updated_at",
          "secret_rotated_at",
          "previous_secret_expires_at",
          "secret"
        ],
        "description": "Подписка вместе с секретом: ответ создания и ротации."
      },
      "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": "Страница списка."
      },
      "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: бесплатное чтение идёт с заголовком Sapport-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": {
                    "$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": "Идентификатор контакта (клиента) в Sapport."
          },
          "external_customer_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Идентификатор клиента в вашей системе. Только у канала api; у остальных каналов 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. По нему идёт обход. Счётчик непрочитанного его не меняет."
          }
        },
        "required": [
          "id",
          "channel",
          "contact_id",
          "external_customer_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 — постоянный путь."
          }
        },
        "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": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Текст; null — текста нет (только вложение) или сообщение удалено."
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MessageAttachment"
            },
            "description": "Вложения (сейчас не больше одного)."
          },
          "deleted": {
            "type": "boolean",
            "description": "true — сообщение удалено (приходит только при include_deleted=true; текста и вложений нет)."
          },
          "created_at": {
            "type": "string",
            "description": "Время сообщения, ISO 8601 UTC."
          }
        },
        "required": [
          "id",
          "conversation_id",
          "sender",
          "content_type",
          "content",
          "attachments",
          "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": "Страница списка."
      },
      "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": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Объяснение оценки; 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",
          "reason",
          "flags",
          "source",
          "model",
          "scored_at"
        ],
        "description": "Оценка лида. null у лида, которого ещё не оценивали."
      },
      "LeadContact": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Идентификатор контакта."
          },
          "first_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "last_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ПДн."
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ПДн."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "geo_country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Страна по IP (ISO 3166-1 alpha-2)."
          },
          "geo_city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Город по IP."
          }
        },
        "required": [
          "id",
          "first_name",
          "last_name",
          "email",
          "phone",
          "tags",
          "geo_country",
          "geo_city"
        ],
        "description": "Контакт лида. Содержит персональные данные: выдача пишется в журнал выдач."
      },
      "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": {
            "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": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "ai_summary": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "next_action": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "next_action_at": {
            "anyOf": [
              {
                "type": "string",
                "description": "ISO 8601 UTC."
              },
              {
                "type": "null"
              }
            ]
          },
          "lost_reason": {
            "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."
          }
        },
        "required": [
          "id",
          "external_id",
          "external_url",
          "version",
          "etag",
          "status",
          "archived",
          "archived_reason",
          "owner",
          "title",
          "source",
          "assigned_to",
          "value",
          "product_id",
          "course_slug",
          "contact",
          "conversation_id",
          "attribution",
          "score",
          "flags",
          "intent",
          "ai_summary",
          "next_action",
          "next_action_at",
          "lost_reason",
          "qualified_at",
          "won_at",
          "lost_at",
          "last_activity_at",
          "created_at",
          "updated_at"
        ],
        "description": "Лид арендатора."
      },
      "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."
  },
  "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": "Достигнут предел трат (арендатор или интеграция), предел одновременных платных операций или максимум стоимости одной операции.",
      "action": "Дождитесь окна или повысьте предел в кабинете."
    },
    {
      "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": "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": "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."
    }
  ]
}
