{
  "x-generator": "NSwag v14.6.3.0 (NJsonSchema v11.5.2.0 (Newtonsoft.Json v13.0.0.0))",
  "openapi": "3.0.0",
  "info": {
    "title": "Verificahub API",
    "description": "Внешний API подтверждения номеров для интеграторов.",
    "version": "v1"
  },
  "servers": [
    {
      "url": "https://api.verificahub.ru",
      "description": "Продакшен"
    }
  ],
  "paths": {
    "/v1/verify/check": {
      "post": {
        "tags": [
          "V1"
        ],
        "summary": "Отправить код подтверждения.",
        "description": "Для методов, где пользователь вводит код: telegram_otp, а также mts_id, если SIM-push не прошёл и сработал резерв по SMS. Метод reverse_flash_call подтверждается автоматически, код для него не нужен. Для mts_id код передаётся оператору, а результат приходит асинхронно, поэтому в ответе статус остаётся «sent» — итог запрашивайте через GET /v1/verify/{request_id}.",
        "operationId": "CheckVerificationCode",
        "requestBody": {
          "x-name": "CheckCodeRequest",
          "description": "",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckCodeRequest"
              },
              "example": {
                "request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "code": "1234"
              }
            }
          },
          "required": true,
          "x-position": 1
        },
        "responses": {
          "200": {
            "description": "Успешно",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckCodeResponse"
                },
                "example": {
                  "request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                  "status": "verified",
                  "phone_number": "+79991234567"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный запрос",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Доступ запрещён"
          },
          "404": {
            "description": "Не найдено",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ExternalBasic": []
          }
        ]
      }
    },
    "/v1/balance": {
      "get": {
        "tags": [
          "V1"
        ],
        "summary": "Текущий баланс аккаунта, кредитный лимит и доступный остаток.",
        "operationId": "GetBalance",
        "responses": {
          "200": {
            "description": "Успешно",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetBalanceResponse"
                },
                "example": {
                  "balance": {
                    "amount": 1500,
                    "currency": "RUB"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Доступ запрещён"
          }
        },
        "security": [
          {
            "ExternalBasic": []
          }
        ]
      }
    },
    "/v1/prices": {
      "get": {
        "tags": [
          "V1"
        ],
        "summary": "Действующие цены на подтверждения и проверку номера в валюте вашего аккаунта.",
        "description": "Два списка: цены на методы подтверждения и на услуги проверки номера. Тарифицируются они по-разному — подтверждение в свою контрольную точку, проверка номера по факту ответа.",
        "operationId": "GetPrices",
        "responses": {
          "200": {
            "description": "Успешно",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetPricesResponse"
                },
                "example": {
                  "prices": [
                    {
                      "method": "reverse_flash_call",
                      "price": {
                        "amount": 0.25,
                        "currency": "RUB"
                      }
                    },
                    {
                      "method": "telegram_otp",
                      "price": {
                        "amount": 0.9,
                        "currency": "RUB"
                      }
                    },
                    {
                      "method": "mts_id",
                      "price": {
                        "amount": 2,
                        "currency": "RUB"
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Доступ запрещён"
          }
        },
        "security": [
          {
            "ExternalBasic": []
          }
        ]
      }
    },
    "/v1/usage": {
      "get": {
        "tags": [
          "V1"
        ],
        "summary": "Сводное потребление подтверждений и проверок номера за период.",
        "description": "Подтверждения составляют поля верхнего уровня; проверки номера считаются отдельно, в lookups, потому что это другая услуга на другой основе тарификации.",
        "operationId": "GetUsage",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "description": "Начало периода, включительно.",
            "schema": {
              "type": "string",
              "format": "date",
              "nullable": true
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "Конец периода, включительно.",
            "schema": {
              "type": "string",
              "format": "date",
              "nullable": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Успешно",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetUsageResponse"
                },
                "example": {
                  "from": "2026-06-01",
                  "to": "2026-06-17",
                  "total_verifications": 1280,
                  "successful": 1205,
                  "success_rate": 0.9414,
                  "total_cost": {
                    "amount": 320,
                    "currency": "RUB"
                  },
                  "by_method": {
                    "reverse_flash_call": 1280
                  },
                  "by_status": {
                    "verified": 1205,
                    "expired": 60,
                    "failed": 15
                  },
                  "daily": [
                    {
                      "date": "2026-06-16",
                      "total": 95,
                      "verified": 90
                    },
                    {
                      "date": "2026-06-17",
                      "total": 60,
                      "verified": 57
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Доступ запрещён"
          }
        },
        "security": [
          {
            "ExternalBasic": []
          }
        ]
      }
    },
    "/v1/verify/{request_id}": {
      "get": {
        "tags": [
          "V1"
        ],
        "summary": "Текущий статус подтверждения.",
        "operationId": "GetVerificationStatus",
        "parameters": [
          {
            "name": "request_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "guid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Успешно",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetVerificationStatusResponse"
                },
                "example": {
                  "request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                  "phone_number": "+79991234567",
                  "method": "reverse_flash_call",
                  "status": "verified",
                  "awaiting_code": false,
                  "cost": {
                    "amount": 0.25,
                    "currency": "RUB"
                  },
                  "created_at": "2026-06-17T12:30:00Z",
                  "verified_at": "2026-06-17T12:30:42Z",
                  "expires_at": "2026-06-17T12:35:00Z"
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Доступ запрещён"
          },
          "404": {
            "description": "Не найдено",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ExternalBasic": []
          }
        ]
      }
    },
    "/v1/verify": {
      "post": {
        "tags": [
          "V1"
        ],
        "summary": "Инициировать подтверждение номера.",
        "description": "Запускает подтверждение выбранным методом (reverse_flash_call, telegram_otp или mts_id). Структура ответа 201 определяется значением поля method; код подтверждения в ответе не возвращается никогда.",
        "operationId": "InitiateVerification",
        "requestBody": {
          "x-name": "InitiateVerificationRequest",
          "description": "",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InitiateVerificationRequest"
              },
              "example": {
                "phone_number": "+79991234567",
                "method": "reverse_flash_call",
                "expiry_seconds": 300
              }
            }
          },
          "required": true,
          "x-position": 1
        },
        "responses": {
          "201": {
            "description": "Создано",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InitiateVerificationResponse"
                },
                "example": {
                  "request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                  "phone_number": "+79991234567",
                  "method": "reverse_flash_call",
                  "status": "sent",
                  "cost": {
                    "amount": 0.25,
                    "currency": "RUB"
                  },
                  "expires_at": "2026-06-17T12:35:00Z",
                  "number_to_call": "+79090000000",
                  "code_length": 4
                }
              }
            }
          },
          "400": {
            "description": "Некорректный запрос",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "402": {
            "description": "",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Доступ запрещён"
          }
        },
        "security": [
          {
            "ExternalBasic": []
          }
        ]
      }
    },
    "/v1/lookup/activity": {
      "post": {
        "tags": [
          "V1"
        ],
        "summary": "Оценить, насколько номер активен в сети (0…1).",
        "description": "Для очистки базы перед рассылкой. Работает по всем российским операторам. Ничего не говорит о том, кто владеет номером, — для этого существует подтверждение.",
        "operationId": "LookupActivity",
        "requestBody": {
          "x-name": "LookupRequest",
          "description": "",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LookupRequest"
              }
            }
          },
          "required": true,
          "x-position": 1
        },
        "responses": {
          "200": {
            "description": "Успешно",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LookupResponse"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный запрос",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "402": {
            "description": "",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Доступ запрещён"
          },
          "503": {
            "description": "",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ExternalBasic": []
          }
        ]
      }
    },
    "/v1/lookup/number-info": {
      "post": {
        "tags": [
          "V1"
        ],
        "summary": "Узнать оператора, регион и факт переноса номера.",
        "description": "Работает по всем российским операторам. Это единственный надёжный способ узнать настоящего оператора номера: таблица префиксов врёт для любого номера, который переносили.",
        "operationId": "LookupNumberInfo",
        "requestBody": {
          "x-name": "LookupRequest",
          "description": "",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LookupRequest"
              }
            }
          },
          "required": true,
          "x-position": 1
        },
        "responses": {
          "200": {
            "description": "Успешно",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LookupResponse"
                }
              }
            }
          },
          "400": {
            "description": "Некорректный запрос",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Не авторизован",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "402": {
            "description": "",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Доступ запрещён"
          },
          "503": {
            "description": "",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ExternalBasic": []
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "ProblemDetails": {
        "type": "object",
        "additionalProperties": {
          "nullable": true
        },
        "properties": {
          "type": {
            "type": "string",
            "nullable": true
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "detail": {
            "type": "string",
            "nullable": true
          },
          "instance": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "CheckCodeResponse": {
        "type": "object",
        "description": "Ответ на проверку кода.",
        "additionalProperties": false,
        "properties": {
          "request_id": {
            "type": "string",
            "description": "Идентификатор сессии.",
            "format": "guid"
          },
          "status": {
            "description": "Итоговый статус.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/VerificationStatus"
              }
            ]
          },
          "phone_number": {
            "type": "string",
            "description": "Подтверждённый номер, приведённый к формату E.164."
          }
        }
      },
      "VerificationStatus": {
        "type": "string",
        "description": "",
        "x-enumNames": [
          "sent",
          "delivered",
          "verified",
          "expired",
          "failed"
        ],
        "enum": [
          "sent",
          "delivered",
          "verified",
          "expired",
          "failed"
        ]
      },
      "CheckCodeRequest": {
        "type": "object",
        "description": "Тело запроса POST /v1/verify/check.",
        "additionalProperties": false,
        "properties": {
          "request_id": {
            "type": "string",
            "description": "Идентификатор сессии, для которой проверяется код.",
            "format": "guid"
          },
          "code": {
            "type": "string",
            "description": "Код, переданный интегратором."
          }
        }
      },
      "GetBalanceResponse": {
        "type": "object",
        "description": "Ответ на GET /v1/balance.",
        "additionalProperties": false,
        "properties": {
          "balance": {
            "description": "Текущий баланс аккаунта. Отрицательный, если аккаунт расходует средства в рамках согласованного `credit_limit`.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/MoneyResponse"
              }
            ]
          },
          "credit_limit": {
            "description": "Насколько ниже нуля может уйти баланс, или `null`, если не может, — это значение по умолчанию при предоплате, когда обслуживание останавливается на нуле. Устанавливается нами по договору, из кабинета не меняется.",
            "nullable": true,
            "oneOf": [
              {
                "$ref": "#/components/schemas/MoneyResponse"
              }
            ]
          },
          "available": {
            "description": "Сколько фактически осталось потратить: `balance` плюс `credit_limit`. Именно по этому значению проверяются запросы на подтверждение, поэтому ориентироваться нужно на него — запрос дороже доступного остатка отклоняется с `insufficient_balance` (402).",
            "oneOf": [
              {
                "$ref": "#/components/schemas/MoneyResponse"
              }
            ]
          }
        }
      },
      "MoneyResponse": {
        "type": "object",
        "description": "Денежная сумма в ответах API.",
        "additionalProperties": false,
        "properties": {
          "amount": {
            "type": "number",
            "description": "Сумма.",
            "format": "decimal"
          },
          "currency": {
            "description": "Валюта по ISO-4217.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/Currency"
              }
            ]
          }
        }
      },
      "Currency": {
        "type": "string",
        "description": "",
        "x-enumNames": [
          "RUB"
        ],
        "enum": [
          "RUB"
        ]
      },
      "GetPricesResponse": {
        "type": "object",
        "description": "Действующие цены по методам подтверждения в валюте аккаунта. Общий ответ для внешнего API (GET /v1/prices) и личного кабинета (GET /dashboard/prices).",
        "additionalProperties": false,
        "properties": {
          "prices": {
            "type": "array",
            "description": "Действующие цены: по одной строке на каждый доступный метод, у которого задана цена, в порядке отображения.",
            "items": {
              "$ref": "#/components/schemas/MethodPriceResponse"
            }
          },
          "lookups": {
            "type": "array",
            "description": "Действующие цены на услуги проверки номера, в порядке отображения.",
            "items": {
              "$ref": "#/components/schemas/LookupPriceResponse"
            }
          }
        }
      },
      "MethodPriceResponse": {
        "type": "object",
        "description": "Цена одного метода подтверждения.",
        "additionalProperties": false,
        "properties": {
          "method": {
            "description": "Метод подтверждения.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/VerificationMethod"
              }
            ]
          },
          "price": {
            "description": "Сумма, списываемая за одно подтверждение этим методом.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/MoneyResponse"
              }
            ]
          },
          "available": {
            "type": "boolean",
            "description": "Может ли этот аккаунт действительно запросить метод."
          }
        }
      },
      "VerificationMethod": {
        "type": "string",
        "description": "",
        "x-enumNames": [
          "reverse_flash_call",
          "flash_call",
          "pass_call",
          "sms",
          "telegram_otp",
          "mts_id",
          "mts_id_sms_otp",
          "max_bot",
          "max_otp"
        ],
        "enum": [
          "reverse_flash_call",
          "flash_call",
          "pass_call",
          "sms",
          "telegram_otp",
          "mts_id",
          "mts_id_sms_otp",
          "max_bot",
          "max_otp"
        ]
      },
      "LookupPriceResponse": {
        "type": "object",
        "description": "Цена одной услуги проверки номера.",
        "additionalProperties": false,
        "properties": {
          "method": {
            "description": "Какая проверка.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/LookupMethod"
              }
            ]
          },
          "price": {
            "description": "Сумма, списываемая за один отвеченный запрос по этой услуге.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/MoneyResponse"
              }
            ]
          }
        }
      },
      "LookupMethod": {
        "type": "string",
        "description": "",
        "x-enumNames": [
          "number_info",
          "activity_score",
          "sim_status"
        ],
        "enum": [
          "number_info",
          "activity_score",
          "sim_status"
        ]
      },
      "GetUsageResponse": {
        "type": "object",
        "description": "Сводка по использованию.",
        "additionalProperties": false,
        "properties": {
          "from": {
            "type": "string",
            "description": "Начало отчётного периода.",
            "format": "date"
          },
          "to": {
            "type": "string",
            "description": "Конец отчётного периода.",
            "format": "date"
          },
          "total_verifications": {
            "type": "integer",
            "description": "Всего подтверждений инициировано за период.",
            "format": "int32"
          },
          "successful": {
            "type": "integer",
            "description": "Сколько из них дошло до статуса verified.",
            "format": "int32"
          },
          "success_rate": {
            "type": "number",
            "description": "Доля успешных: успешные, делённые на общее число, с округлением до 4 знаков.",
            "format": "double"
          },
          "total_cost": {
            "description": "Сумма, фактически списанная за период (по тарифицированным подтверждениям, без учёта нетарифицируемых истёкших и неуспешных, а также возвратов).",
            "oneOf": [
              {
                "$ref": "#/components/schemas/MoneyResponse"
              }
            ]
          },
          "by_method": {
            "type": "object",
            "description": "Количество подтверждений в разбивке по методам.",
            "x-dictionaryKey": {
              "$ref": "#/components/schemas/VerificationMethod"
            },
            "additionalProperties": {
              "type": "integer",
              "format": "int32"
            }
          },
          "by_status": {
            "type": "object",
            "description": "Количество подтверждений в разбивке по статусам — та самая разбивка неуспешных (истёкшие против неуспешных), по которой интеграторы разбирают потери.",
            "x-dictionaryKey": {
              "$ref": "#/components/schemas/VerificationStatus"
            },
            "additionalProperties": {
              "type": "integer",
              "format": "int32"
            }
          },
          "daily": {
            "type": "array",
            "description": "Количество по дням за период, по возрастанию даты — для графиков. Дни без активности пропускаются.",
            "items": {
              "$ref": "#/components/schemas/UsageDayResponse"
            }
          },
          "lookups": {
            "description": "Потребление проверок номера за тот же период, отдельно от подтверждений.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/LookupUsageResponse"
              }
            ]
          }
        }
      },
      "UsageDayResponse": {
        "type": "object",
        "description": "Показатели за один день в отчёте об использовании.",
        "additionalProperties": false,
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "total": {
            "type": "integer",
            "format": "int32"
          },
          "verified": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "LookupUsageResponse": {
        "type": "object",
        "description": "Потребление проверок номера в отчёте.",
        "additionalProperties": false,
        "properties": {
          "total": {
            "type": "integer",
            "description": "Сколько проверок запрошено за период — отвеченных и нет.",
            "format": "int32"
          },
          "billable": {
            "type": "integer",
            "description": "Сколько из них было тарифицировано.",
            "format": "int32"
          },
          "total_cost": {
            "description": "Во сколько обошлись проверки суммарно.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/MoneyResponse"
              }
            ]
          },
          "by_method": {
            "type": "object",
            "description": "Количество по услугам проверки.",
            "x-dictionaryKey": {
              "$ref": "#/components/schemas/LookupMethod"
            },
            "additionalProperties": {
              "type": "integer",
              "format": "int32"
            }
          },
          "by_status": {
            "type": "object",
            "description": "Количество по исходам — именно здесь видна доля «нет данных».",
            "x-dictionaryKey": {
              "$ref": "#/components/schemas/LookupStatus"
            },
            "additionalProperties": {
              "type": "integer",
              "format": "int32"
            }
          }
        }
      },
      "LookupStatus": {
        "type": "string",
        "description": "",
        "x-enumNames": [
          "ok",
          "no_data",
          "out_of_coverage"
        ],
        "enum": [
          "ok",
          "no_data",
          "out_of_coverage"
        ]
      },
      "GetUsageRequest": {
        "type": "object",
        "description": "Параметры запроса GET /v1/usage.",
        "additionalProperties": false
      },
      "GetVerificationStatusResponse": {
        "type": "object",
        "description": "Ответ со статусом подтверждения.",
        "additionalProperties": false,
        "properties": {
          "request_id": {
            "type": "string",
            "description": "Идентификатор сессии.",
            "format": "guid"
          },
          "phone_number": {
            "type": "string",
            "description": "Подтверждённый номер, приведённый к формату E.164."
          },
          "method": {
            "description": "Метод подтверждения.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/VerificationMethod"
              }
            ]
          },
          "status": {
            "description": "Текущий статус.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/VerificationStatus"
              }
            ]
          },
          "awaiting_code": {
            "type": "boolean",
            "description": "Ожидается ли сейчас ввод кода пользователем через POST /v1/verify/check. Для методов, не требующих ввода кода (reverse_flash_call), всегда false. Для mts_id становится true только после того, как SIM-push не прошёл и сработал резерв по SMS (то же событие, что и вебхук verification.code_required); пока push ещё выполняется, остаётся false. Интеграторы опрашивают это поле, чтобы понять, когда показать пользователю ввод кода."
          },
          "cost": {
            "description": "Цена этого подтверждения (та, что объявлена клиенту). Для незавершённого, истёкшего или неуспешного подтверждения это цена, которая была бы применена, — не обязательно фактически списанная сумма.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/MoneyResponse"
              }
            ]
          },
          "created_at": {
            "type": "string",
            "description": "Когда сессия создана (UTC).",
            "format": "date-time"
          },
          "verified_at": {
            "type": "string",
            "description": "Когда подтверждение прошло успешно (UTC), если прошло.",
            "format": "date-time",
            "nullable": true
          },
          "expires_at": {
            "type": "string",
            "description": "Когда истекает сессия (UTC).",
            "format": "date-time"
          },
          "failure_reason": {
            "description": "Почему подтверждение не состоялось; null, пока сессия активна или если она завершилась успешно.",
            "nullable": true,
            "oneOf": [
              {
                "$ref": "#/components/schemas/VerificationFailureReason"
              }
            ]
          }
        }
      },
      "VerificationFailureReason": {
        "type": "string",
        "description": "",
        "x-enumNames": [
          "no_response",
          "declined",
          "wrong_code",
          "not_delivered",
          "unreachable",
          "unknown"
        ],
        "enum": [
          "no_response",
          "declined",
          "wrong_code",
          "not_delivered",
          "unreachable",
          "unknown"
        ]
      },
      "GetVerificationStatusRequest": {
        "type": "object",
        "description": "Параметры пути для GET /v1/verify/{request_id}.",
        "additionalProperties": false
      },
      "InitiateVerificationResponse": {
        "type": "object",
        "discriminator": {
          "propertyName": "method",
          "mapping": {
            "reverse_flash_call": "#/components/schemas/ReverseFlashCallInitiateResponse",
            "sms": "#/components/schemas/SmsInitiateResponse",
            "flash_call": "#/components/schemas/FlashCallInitiateResponse",
            "telegram_otp": "#/components/schemas/TelegramInitiateResponse",
            "mts_id": "#/components/schemas/MtsIdInitiateResponse",
            "max_bot": "#/components/schemas/MaxBotInitiateResponse",
            "max_otp": "#/components/schemas/MaxOtpInitiateResponse",
            "pass_call": "#/components/schemas/PassCallInitiateResponse"
          }
        },
        "description": "Ответ на POST /v1/verify: поля, общие для всех методов.",
        "x-abstract": true,
        "additionalProperties": false,
        "required": [
          "method"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "description": "Идентификатор созданной сессии.",
            "format": "guid"
          },
          "phone_number": {
            "type": "string",
            "description": "Подтверждённый номер, приведённый к формату E.164."
          },
          "status": {
            "description": "Текущий статус.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/VerificationStatus"
              }
            ]
          },
          "cost": {
            "description": "Цена этого подтверждения (та, что объявлена клиенту); списывается, когда подтверждение достигает своей точки тарификации.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/MoneyResponse"
              }
            ]
          },
          "expires_at": {
            "type": "string",
            "description": "Когда истекает сессия (UTC), если подтверждение не состоится.",
            "format": "date-time"
          },
          "code_length": {
            "type": "integer",
            "description": "Сколько цифр в коде, который пользователь получает или считывает и передаёт через POST /v1/verify/check.",
            "format": "int32"
          },
          "method": {
            "type": "string"
          }
        }
      },
      "ReverseFlashCallInitiateResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/InitiateVerificationResponse"
          },
          {
            "type": "object",
            "description": "Ответ для подтверждения методом reverse_flash_call.",
            "additionalProperties": false,
            "properties": {
              "number_to_call": {
                "type": "string",
                "description": "Номер шлюзовой SIM-карты, который нужно показать пользователю: «Позвоните на этот номер»."
              }
            }
          }
        ]
      },
      "SmsInitiateResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/InitiateVerificationResponse"
          },
          {
            "type": "object",
            "description": "Ответ для подтверждения методом sms — код приходит в SMS-сообщении.",
            "additionalProperties": false
          }
        ]
      },
      "FlashCallInitiateResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/InitiateVerificationResponse"
          },
          {
            "type": "object",
            "description": "Ответ для подтверждения методом flash_call — кодом служат последние цифры номера, с которого поступает входящий вызов.",
            "additionalProperties": false
          }
        ]
      },
      "TelegramInitiateResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/InitiateVerificationResponse"
          },
          {
            "type": "object",
            "description": "Ответ для подтверждения методом telegram_otp — Telegram доставляет код в аккаунт пользователя.",
            "additionalProperties": false
          }
        ]
      },
      "MtsIdInitiateResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/InitiateVerificationResponse"
          },
          {
            "type": "object",
            "description": "Ответ для подтверждения методом mts_id — МТС отправляет подтверждение на SIM-карту пользователя; на этом этапе ничего вводить не нужно, а результат приходит асинхронно на наш вебхук (статус начинается с sent). Если сработал резерв по SMS, пользователь вводит код, а интегратор передаёт его через POST /v1/verify/check.",
            "additionalProperties": false
          }
        ]
      },
      "MaxBotInitiateResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/InitiateVerificationResponse"
          },
          {
            "type": "object",
            "description": "Ответ для подтверждения методом max_bot — пользователь открывает бота MAX по ссылке deep_link, делится своим номером, и бот доставляет код в MAX. Затем пользователь вводит код, а интегратор проверяет его через POST /v1/verify/check. Статус начинается с sent и переходит в delivered, когда код доставлен пользователю.",
            "additionalProperties": false,
            "properties": {
              "deep_link": {
                "type": "string",
                "description": "Ссылка для открытия бота MAX: https://max.ru/<bot>?start=… (покажите ссылкой или QR-кодом)."
              }
            }
          }
        ]
      },
      "MaxOtpInitiateResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/InitiateVerificationResponse"
          },
          {
            "type": "object",
            "description": "max_otp — код отправлен прямо в аккаунт MAX пользователя.",
            "additionalProperties": false
          }
        ]
      },
      "PassCallInitiateResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/InitiateVerificationResponse"
          },
          {
            "type": "object",
            "description": "Ответ на подтверждение методом pass_call: робот звонит на номер и диктует код, который пользователь вводит в /v1/verify/check.",
            "additionalProperties": false
          }
        ]
      },
      "InitiateVerificationRequest": {
        "type": "object",
        "description": "Тело запроса POST /v1/verify.",
        "additionalProperties": false,
        "properties": {
          "phone_number": {
            "type": "string",
            "description": "Номер пользователя в формате E.164."
          },
          "method": {
            "description": "Метод подтверждения.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/VerificationMethod"
              }
            ]
          },
          "expiry_seconds": {
            "type": "integer",
            "description": "Запрашиваемое время жизни сессии в секундах.",
            "format": "int32",
            "nullable": true
          }
        }
      },
      "LookupResponse": {
        "type": "object",
        "description": "Результат проверки номера.",
        "additionalProperties": false,
        "properties": {
          "request_id": {
            "type": "string",
            "description": "Идентификатор этой проверки — для поддержки и сверки.",
            "format": "guid"
          },
          "phone_number": {
            "type": "string",
            "description": "Номер, в маскированном виде."
          },
          "method": {
            "description": "Какая проверка была выполнена.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/LookupMethod"
              }
            ]
          },
          "status": {
            "description": "Были ли данные, не было их, или номер вне зоны покрытия услуги.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/LookupStatus"
              }
            ]
          },
          "operator": {
            "description": "Оператор абонента, если он пришёл в ответе.",
            "nullable": true,
            "oneOf": [
              {
                "$ref": "#/components/schemas/MobileOperator"
              }
            ]
          },
          "region_code": {
            "type": "integer",
            "description": "Регион, в котором продана SIM, если он пришёл в ответе.",
            "format": "int32",
            "nullable": true
          },
          "score": {
            "type": "number",
            "description": "Оценка активности от 0 (наименее активен) до 1 (наиболее) — для проверки активности.",
            "format": "decimal",
            "nullable": true
          },
          "ported": {
            "type": "boolean",
            "description": "Переносился ли номер к другому оператору — для проверки сведений о номере.",
            "nullable": true
          },
          "cost": {
            "description": "Во сколько обошлась эта проверка. Ноль, если ответ не тарифицировался.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/MoneyResponse"
              }
            ]
          },
          "checked_at": {
            "type": "string",
            "description": "Когда проверка выполнена (UTC).",
            "format": "date-time"
          }
        }
      },
      "MobileOperator": {
        "type": "string",
        "description": "",
        "x-enumNames": [
          "mts",
          "megafon",
          "beeline",
          "tele2",
          "other"
        ],
        "enum": [
          "mts",
          "megafon",
          "beeline",
          "tele2",
          "other"
        ]
      },
      "LookupRequest": {
        "type": "object",
        "description": "Тело запроса эндпоинтов POST /v1/lookup/*.",
        "additionalProperties": false,
        "properties": {
          "phone_number": {
            "type": "string",
            "description": "Номер, который нужно проверить."
          }
        }
      }
    },
    "securitySchemes": {
      "JWTBearerAuth": {
        "type": "http",
        "description": "Введите JWT-токен для авторизации запросов…",
        "scheme": "Bearer",
        "bearerFormat": "JWT"
      },
      "ExternalBasic": {
        "type": "http",
        "description": "HTTP Basic: api_key:api_secret.",
        "scheme": "basic"
      }
    }
  }
}