--- title: "Изменения и новости API" url: "https://docs.x-hub.online/reference/changelog/" description: "Что меняется в API X-Hub: анонсы и история изменений контракта." relatedDocuments: - "https://docs.x-hub.online/payments/" - "https://docs.x-hub.online/exchange-terminal/" - "https://docs.x-hub.online/webhooks/" - "https://docs.x-hub.online/payments/refunds/" - "https://docs.x-hub.online/shops/" - "https://docs.x-hub.online/reference/errors/" - "https://docs.x-hub.online/subscriptions/api/" --- # Изменения и новости API { #changelog } Формат строки: дата · тип · что изменилось · кого касается · что сделать. ## Анонсы { #announcements } | Дата | Тип | Что изменилось | Кого касается | Что сделать | |---|---|---|---|---| | с выкаткой | изменение | Параметр `ttl_minutes` в `POST /api/v1/payments` (срок жизни ссылки на оплату, минуты) теперь применяется на тех способах оплаты, которые поддерживают свой срок: `expires_at` в ответе равен моменту создания плюс запрошенный срок. На остальных способах параметр, как и раньше, не меняет срок — ссылка живёт стандартное время способа. Выше максимума аккаунта по-прежнему `422 VALIDATION_ERROR`. Не передаёшь `ttl_minutes` — срок прежний | Мерчанты, передающие `ttl_minutes` | Брать срок из `expires_at` ответа, а не из переданного значения; не считать платёж `pending` короткоживущим, если ты запрашивал длинный срок | | с выкаткой | изменение | Поля `exchange_amount_usdt` и `exchange_rate` больше не возвращаются: ни в объекте платежа (`POST /api/v1/payments`, `GET /api/v1/payments/:id`), ни в уведомлениях `payment.status_changed`, ни в одном статусе платежа. Запрос `GET /api/v1/payment-methods/:method_id/exchange-rate` больше не возвращает курс: на любой способ оплаты он отвечает `404 EXCHANGE_RATE_NOT_SUPPORTED`. Остальные поля платежа и `amount_usdt` — без изменений | Мерчанты, читавшие эти поля или запрашивавшие курс по способу оплаты | Не читать эти поля и не запрашивать курс; если схема разбора вебхука объявляла эти поля, убрать их. Сумму зачисления брать из `amount_usdt` после расчёта | | с выкаткой | изменение | Окно оплаты X-Hub по `payment_url` после успешной оплаты (`paid`, `settled`) или отказа (`failed`, `cancelled`) доступно 1 минуту, затем ссылка отвечает `404`, как несуществующая. Заменяет срок в 5 минут из соседнего анонса. Остальные статусы — без изменений | Мерчанты, чьи плательщики платят через окно оплаты X-Hub | Не использовать `payment_url` как страницу чека или статуса; статус брать из `GET /api/v1/payments/:id` или вебхука. См. [Платежи](../payments/index.md) | | с выкаткой | изменение | Окно оплаты X-Hub по `payment_url` после успешной оплаты (`paid`, `settled`) доступно 5 минут, затем ссылка отвечает `404`, как несуществующая. Остальные статусы — без изменений | Мерчанты, чьи плательщики платят через окно оплаты X-Hub | Не использовать `payment_url` как постоянную страницу чека; статус брать из `GET /api/v1/payments/:id` или вебхука. См. [Платежи](../payments/index.md) | ## История изменений { #history } | Дата | Тип | Что изменилось | Кого касается | Что сделать | |---|---|---|---|---| | 6 октября 2026 | новое | Новый объект `payer` в `POST /api/v1/payments` — данные плательщика, которые мерчант собрал при проверке своего клиента: `full_name` и `document_number` обязательны внутри объекта, `kyc_reference` и `kyc_completed_at` необязательны. В список `required_fields` (`GET /api/v1/payment-methods`) добавлено значение `payer`. Если у терминала в `required_fields` указаны `client_phone` и `payer`, они обязательны в каждом платеже: без них — `422 PAYER_DATA_REQUIRED`, в `details.missing_fields` — недостающие поля, платёж не создаётся. Объект неверной формы — `400 VALIDATION_ERROR`, значения не по правилам (знаки, длина, дата) — `422 VALIDATION_ERROR`; `422` не запирает `Idempotency-Key` | Аккаунты, у терминала которых в `required_fields` есть `payer` | Читать `required_fields` своего терминала в `GET /api/v1/payment-methods` и передавать все перечисленные поля в каждом платеже. См. [Платежи](../payments/index.md#payer-object) и [Обменный терминал](../exchange-terminal/index.md#step-create) | | 6 октября 2026 | новое | Новое событие вебхука `payment.delivery_proof_reminder`: напоминание, что по оплаченному платежу терминала с обменом при оплате не передан хэш перевода клиенту. Приходит через 24, 48 и 72 часа после оплаты, не больше трёх раз на платёж, пока хэш не передан или последний переданный отклонён. Тело — `payment_id`, `external_id`, `paid_at`, `reminder` (`1`, `2` или `3`), `status` (`waiting` или `rejected`), у `rejected` поле `reason`, `timestamp`, `shop_id`, `shop_name`. Хэш подтверждает, что клиент получил перевод, и используется, если по платежу возникает спор; платёж, расчёт и выплата от него не зависят. Включено по умолчанию, отключается в «Разработчикам → Вебхуки». В `payment.status_changed` ничего не добавлено | Аккаунты с включённым обменом при оплате; остальных не касается | Ничего; чтобы передавать хэш автоматически, принять событие и ответить запросом `POST /api/v1/payments/:id/delivery-proof`. Если настраивал набор событий вручную — отметить новое. См. [Уведомления](../webhooks/index.md#webhook-delivery-proof-reminder) и [Обменный терминал](../exchange-terminal/index.md#step-delivery-proof) | | 5 октября 2026 | новое | Новые запросы `POST /api/v1/payments/:id/delivery-proof` и `GET /api/v1/payments/:id/delivery-proof`: передать хэш перевода USDT клиенту (`network` — `TRC20`, `ERC20` или `BEP20`, и `tx_hash`) и прочитать его состояние. Хэш подтверждает, что клиент получил перевод, и используется, если по платежу возникает спор; платёж, расчёт и выплата от него не зависят. Ответ — `network`, `tx_hash`, `status` (`waiting`, `accepted`, `in_review`, `awaiting_confirmations`, `confirmed`, `confirmed_amount_differs`, `rejected`) и у `rejected` поле `reason`. Новые коды: `409 DELIVERY_PROOF_LOCKED`, `409 DELIVERY_PROOF_CONFLICT`. Работает по платежам терминала с обменом при оплате в статусе `paid` или `settled` | Аккаунты с включённым обменом при оплате; остальных не касается | Ничего; передавать хэш можно по желанию. См. [Обменный терминал](../exchange-terminal/index.md#step-delivery-proof) и [Платежи](../payments/index.md#delivery-proof) | | 5 октября 2026 | новое | Новая страница [«Обменный терминал»](../exchange-terminal/index.md): приём рублей по СБП с обменом при оплате — список терминалов, курс до создания платежа, сделка в ответе и уведомлении, границы суммы, коды ошибок, чек-лист. Контракт API не меняется: новых полей, кодов и поведения нет | Аккаунты с включённым обменом при оплате; остальных не касается | Ничего; страница собирает существующее поведение в одном месте | | 5 октября 2026 | новое | Новый запрос `GET /api/v1/payment-methods/:method_id/exchange-rate`: ориентировочный курс терминала с обменом при оплате до создания платежа, рублей за 1 USDT. Ответ — `method_id`, `exchange_rate`, `fetched_at`. Курс сделки по-прежнему фиксируется при создании платежа и приходит в его ответе. Ошибки: `400 METHOD_NOT_AVAILABLE`, `404 EXCHANGE_RATE_NOT_SUPPORTED`, `503 EXCHANGE_RATE_UNAVAILABLE` | Аккаунты с включённым обменом при оплате и выбором терминала; остальных не касается | Ничего | | 5 октября 2026 | новое | Поле `payer_name` (строка) — имя плательщика, как его сообщил банк, — в объекте платежа (`POST /api/v1/payments`, `GET /api/v1/payments/:id`) и в уведомлениях `payment.status_changed` этого платежа. Приходит только на аккаунтах, для которых имя плательщика предоставляется, и не у каждого платежа: когда имени нет, поля нет вовсе (не `null`). Когда имя есть, оно появляется вместе со статусом `paid` или позже; если в уведомлении `paid` поля не было, платёж можно перечитать запросом `GET /api/v1/payments/:id`. Значение отдаётся как получено от банка | Аккаунты, для которых имя плательщика предоставляется; остальных не касается | Ничего. Если тело вебхука проверяется строгой схемой — добавить одно необязательное строковое поле. См. [Платежи](../payments/index.md#payer-name) и [Вебхуки](../webhooks/index.md#webhook-payer-name) | | 30 сентября 2026 | изменение | Снят лимит в 20 одновременно открытых заявок на возврат: ошибка `LIMIT_OPEN` (`409`) больше не возвращается. Лимит в 10 заявок на один платёж (`LIMIT_PER_PAYMENT`) остаётся | Кто создаёт возвраты | Ничего; обработку `LIMIT_OPEN` можно убрать. См. [Возвраты](../payments/refunds.md#refund-amounts) | | 29 сентября 2026 | изменение | Адрес вебхука и секрет подписи — одни на аккаунт, своих у магазина нет. Уведомления всех магазинов уходят на адрес из «Разработчикам → Вебхуки» (или на `webhook_url`, переданный в платеже) и подписываются секретом аккаунта. Поля `shop_id` и `shop_name` в `payment.status_changed` и `refund.*` — как раньше | Аккаунты с несколькими магазинами | Ничего; события разных магазинов различать по `shop_id`. См. [Магазин в теле события](../webhooks/index.md#webhook-shop) | | 28 сентября 2026 | изменение | Ключ `payerContactMasked` в `metadata` платежа (маска телефона плательщика: `***` и последние 4 цифры) заполняется у большего числа СБП-платежей, в том числе у отклонённых (`failed`); у части уже прошедших платежей — задним числом. Возвращается в `GET /api/v1/payments/:id` и в кабинете (поле «Контакт»); в вебхуках — в событиях после оплаты (например, `settled`), в самом событии `paid` или `failed` ключа ещё нет | Мерчанты, читающие `metadata` платежа | Ничего; ваши ключи `metadata` не меняются. Если сверяете `metadata` с отправленным при создании — не считайте `payerContactMasked` расхождением | | 25 сентября 2026 | новое | Необязательное поле `client_info` (JSON-объект до 4096 байт) в `POST /api/v1/payments` — данные плательщика для антифрода X-Hub: рекомендуемые ключи `ip`, `user_agent`, `page_url`, необязательные `accept_language`, `timezone`. Не объект или больше 4096 байт — `400 VALIDATION_ERROR`. В банк не передаётся, в ответах API, вебхуках и кабинете не возвращается | Мерчанты, которые отдают плательщику ссылку банка напрямую, без окна оплаты X-Hub | Передавать `client_info` с `ip` плательщика (не своего сервера) в каждом платеже. См. [Платежи](../payments/index.md#client-info) | | 24 сентября 2026 | новое | Необязательный `auto_return` (boolean) в `POST /api/v1/payments`: `true` — окно оплаты после успеха считает 5 секунд и само возвращает плательщика в магазин, `false` — только кнопка возврата. Не передан — настройка аккаунта, по умолчанию `true` (как сейчас) | Кто передаёт адрес возврата | Ничего; чтобы отключить автопереход, передавать `auto_return: false`. См. [Платежи](../payments/index.md) | | 24 сентября 2026 | изменение | Частичный возврат доступен сразу после оплаты (`paid`), до ежедневного расчёта. Расчёт начисляет USDT с остатка. `400 PARTIAL_BEFORE_SETTLEMENT` остаётся только для способов оплаты, где начисление идёт по фактическому поступлению | Кто делает возвраты | Ничего; частичный по `paid` больше не нужно откладывать до `settled`. См. [Возвраты](../payments/refunds.md#refund-amounts) | | 24 сентября 2026 | новое | Необязательный `shop_id` в `POST /api/v1/payments` и `POST /api/v1/subscriptions`, фильтр `shop_id` в `GET /api/v1/payments`, поле `shop_id` в объекте платежа. Новые коды `SHOP_NOT_FOUND`, `SHOP_DISABLED`. Без `shop_id` поведение прежнее | Аккаунты с несколькими магазинами | Передавать `shop_id` магазина. См. [Платежи](../payments/index.md#shop-refusals) и [Магазины](../shops/index.md) | | 24 сентября 2026 | изменение | Для части способов оплаты мерчант без включённого разрешения «прямые ссылки» получает в `payment_url` (в API и в кабинете) только платёжное окно X-Hub, а `GET /payments/:id/sbp-link` отвечает `403 DIRECT_LINK_NOT_ALLOWED`. С разрешением прямая ссылка выдаётся как раньше | Мерчанты, рисующие свой QR по прямой ссылке | Если нужен свой QR — запросить включение прямых ссылок у поддержки. См. [СБП-ссылка](../payments/index.md#sbp-link) | | 24 сентября 2026 | новое | Данные плательщика в `POST /api/v1/payments`: новое необязательное поле `client_email` (до 254 символов), `client_phone` теперь проверяется на формат E.164 (`+` и 10–15 цифр; кривой формат — `422 VALIDATION_ERROR`). У части терминалов эти поля и `description` **обязательны** на каждом платеже (список — `GET /api/v1/payment-methods`, поле `required_fields`); отсутствие — `422 PAYER_DATA_REQUIRED` с `details.missing_fields`, платёж не создаётся. `422` не запирает `Idempotency-Key`: повтор с тем же ключом и добавленными полями создаёт платёж | Мерчанты на терминалах, требующих данные плательщика (узнаете по `required_fields`) | Передавать `client_phone`, `client_email`, `description`, когда терминал их требует. См. [Платежи](../payments/index.md#body) | | 24 сентября 2026 | изменение | Публичный `GET /health` отдаёт только `status`, `timestamp` и `core`. Внутренние блоки из ответа убраны. HTTP-коды прежние: `200` — `ok`, `503` — `degraded` | Кто опрашивает `/health` | Читать только `status` и HTTP-код | | 24 сентября 2026 | изменение | Служебные ключи X-Hub в `metadata` при создании платежа отбрасываются: `bindingNoCharge`, `provider_data`, `terminalCode`, `methodId`, `tariffCoreReview`, `payerNameMasked`, `payerContactMasked`, `payerCardMasked`, `nameMatch`, `charge_recovery`. Остальные ключи возвращаются как раньше | Кто кладёт в `metadata` ключи с такими именами | Переименовать свои ключи, см. [Платежи](../payments/index.md) | | 24 сентября 2026 | новое | Тело запроса больше 100 КБ — `413 PAYLOAD_TOO_LARGE` в обычном формате ошибки. Проверка тела идёт до авторизации | Все интеграции | Уменьшить тело, например `metadata`. См. [Ошибки](errors.md) | | 24 сентября 2026 | исправление | Несуществующий путь под `/api/v1` отвечает `404` с JSON `{"error":{"code":"NOT_FOUND","message":"Endpoint not found"}}`, а не HTML-страницей. У `KYC_NOT_REQUIRED` появилось поле `message` | Все интеграции | Ничего, если ошибки разбираются по `error.code` | | 24 сентября 2026 | изменение | `success_url` в `POST /api/v1/subscriptions` принимает только схемы `http` и `https`, иначе `400 VALIDATION_ERROR` | Кто создаёт подписки с `success_url` | Передавать адрес `http(s)://…`. См. [Подписки](../subscriptions/api.md) | | 24 сентября 2026 | исправление | `actual_amount_rub` в `payment.status_changed` равен сохранённому значению платежа, тому же, что отдаёт `GET /api/v1/payments/:id`. Если денег не было (`failed`, `cancelled`, `expired`), там `null` | Мерчанты, использующие вебхуки | Сверять сумму оплаты по `actual_amount_rub` события `paid` | | 24 сентября 2026 | исправление | Отказ банка по карточному платежу всегда приходит как `failed` с `failure_reason: declined_by_bank`. Раньше иногда приходил `cancelled` без причины | Кто принимает карты | Обрабатывать `failed` + `declined_by_bank` как окончательный отказ | | 24 сентября 2026 | исправление | `amount_rub` в событиях `refund.*` всегда с двумя знаками после точки: `"1500.00"`, не `"1500"` | Мерчанты, использующие вебхуки возвратов | Ничего, если сумма разбирается как число | | 24 сентября 2026 | изменение | Заявка на возврат без суммы, когда весь остаток уже покрыт другими заявками, получает `400 OVER_REMAINING` | Кто создаёт возвраты | См. [Возвраты](../payments/refunds.md) | | 24 сентября 2026 | изменение | Событие `subscription.charge_exhausted` приходит всегда: в настройках событий кабинета оно не отключается | Мерчанты с подписками | Принимать событие на вебхук-адресе |