Перейти к содержимому
Последнее обновление

Диспуты

Открывайте диспуты для разрешения спорных ситуаций с платежами.

Когда открывать диспут

  • Платёж отмечен как success, но получатель не получил средства
  • Платёж отмечен как failed, но средства были списаны
  • Некорректная сумма платежа
  • Другие спорные ситуации

Ограничения

Диспут можно открыть только для ордеров со статусом:

  • success
  • failed

Нельзя открыть диспут для:

  • created и in_progress — дождитесь завершения
  • disputed — диспут уже открыт

В этих случаях придёт 400 DISPUTE_NOT_ALLOWED.

Создание диспута

Нужно право orders.write.

curl -X POST 'https://b2b.lumowallet.io/orders/{orderId}/disputes' \
  -H 'X-API-Key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "reason": "Платёж отображается как успешный, но магазин не получил оплату"
  }'

Ответ:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "orderId": "660e8400-e29b-41d4-a716-446655440001",
  "status": "submitted",
  "resolution": null,
  "reason": "Платёж отображается как успешный, но магазин не получил оплату",
  "adminComment": null,
  "resolvedBy": null,
  "refundAmount": null,
  "resolvedAt": null,
  "createdAt": "2026-03-10T12:00:00Z",
  "updatedAt": "2026-03-10T12:00:00Z"
}

Ответ — 201. После создания диспута:

  • Ордер переходит в статус disputed. На этот переход может прийти вебхук order.status_changed — обрабатывайте его как обычно
  • Диспут отправляется на рассмотрение

По ордеру в статусе success платёжная сторона в ответ на ваш запрос иногда сама открывает спор — тогда в ответе вернётся он, и в reason будет служебный текст dispute_created:… вместо вашего.

Диспут, открытый платёжной стороной

Диспут может открыться и без вашего запроса — например, если исполнитель не подтвердил оплату вовремя. Тогда ордер переходит в disputed, вы получаете вебхук order.status_changed, а в списке диспутов появляется диспут с причиной от платёжной стороны. Дальше он рассматривается так же, как ваш.

Чем закончился диспут

:::warning Исход диспута — в resolution, а не в status

status отвечает только на вопрос «рассмотрен или ещё нет». И выигранный, и проигранный диспут одинаково получают status: resolved. Чтобы понять исход, смотрите resolution.

:::

resolutionЧто это значитЧто стало с ордером
refundВозврат. Диспут решён в вашу пользу, оплата отмененаfailed
partial_refundЧастичный возврат. Возвращена часть суммыfailed
confirmДиспут отклонён. Оплата признана состоявшейся, возврата нетsuccess

То есть resolution: confirm — это отказ по диспуту, несмотря на status: resolved.

Статусы диспута

СтатусОписание
submittedДиспут создан, ожидает рассмотрения
resolvedДиспут рассмотрен — исход смотрите в resolution
in_reviewЗарезервирован, сейчас не используется
rejectedЗарезервирован, сейчас не используется

:::note

Промежуточного статуса на практике не бывает: диспут переходит из submitted сразу в resolved. Значения in_review и rejected существуют в перечислении, но не выставляются — не стройте на них логику. Отказ по диспуту выражается как status: resolved + resolution: confirm.

:::

Сумма возврата

refundAmount заполняется при refund (полная сумма ордера) и при partial_refund (та часть, которую вернули). При confirm — всегда null.

:::warning refundAmount — это не «зачислено на баланс»

refundAmount показывает, какая часть ордера отменена, а не сколько денег пришло на баланс. Если к моменту решения средства ещё не были списаны (ордер держался в заморозке), возврат — это снятие заморозки: refundAmount заполнен, но баланс не растёт, освобождается замороженная сумма.

Реальное движение средств смотрите в истории баланса по referenceId = orderId. Решение администратора:

operationTypeЧто произошло
dispute_resolve_refundвозврат: уже списанная сумма вернулась на баланс, либо снята заморозка
dispute_resolve_partial_refundчастичный возврат: на баланс вернулась часть суммы
dispute_resolve_confirmдиспут отклонён: списание подтверждено, при необходимости сумма списана

Закрытие по финальному статусу от платёжной стороны:

operationTypeЧто произошло
order_failed_unfreezeснята заморозка — списания не было, баланс не меняется
order_failed_refund_after_successсредства уже были списаны и вернулись на баланс
order_success_settlement_after_disputeдиспут отклонён, списание подтверждено

:::

Комиссия отдельно не удерживается: она заложена в курс ордера, поэтому полный возврат отменяет её вместе с суммой.

Список диспутов

curl -X GET 'https://b2b.lumowallet.io/disputes' \
  -H 'X-API-Key: YOUR_API_KEY'

Ответ содержит и сам диспут, и ордер, к которому он относится — отдельный запрос за ордером не нужен. Суммы в этом ответе приходят строками:

[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "orderId": "660e8400-e29b-41d4-a716-446655440001",
    "status": "resolved",
    "resolution": "refund",
    "reason": "Магазин не получил оплату",
    "adminComment": "Подтверждено: платёж не дошёл до получателя",
    "resolvedBy": "[email protected]",
    "refundAmount": "52.63000000",
    "resolvedAt": "2026-03-10T14:00:00Z",
    "createdAt": "2026-03-10T12:00:00Z",
    "updatedAt": "2026-03-10T14:00:00Z",
    "order": {
      "id": "660e8400-e29b-41d4-a716-446655440001",
      "externalOrderId": "ORD-2026-8891",
      "status": "failed",
      "amountUsdt": "52.63000000",
      "amountRub": "5000.00",
      "rate": "95.01000000",
      "nspkBrandName": "Пятёрочка",
      "createdAt": "2026-03-10T11:40:00Z"
    }
  }
]

order.externalOrderId — ваш идентификатор, переданный при создании ордера; по нему удобно сводить диспуты со своей системой.

В order могут присутствовать и другие поля — они служебные и не входят в контракт, полагайтесь только на перечисленные выше.

Поиск и фильтры

# по вашему номеру заказа — достаточно части
curl 'https://b2b.lumowallet.io/disputes?search=387057' -H 'X-API-Key: ...'

# только возвраты
curl 'https://b2b.lumowallet.io/disputes?resolution=refund' -H 'X-API-Key: ...'
ПараметрОписание
searchПоиск по ордеру диспута: ваш externalOrderId (в том числе по части) или наш id ордера
statussubmitted / resolved
resolutionИсход: refund / partial_refund / confirm
limit / offsetПостраничная выдача, limit — 1–200

Без limit эндпоинт возвращает всю историю диспутов одним массивом — как и раньше. Общее число совпадений приходит в заголовке X-Total-Count. Нужно право orders.read.

Повторный запрос

Пока по ордеру открыт диспут, ордер находится в статусе disputed, и повторный запрос вернёт 400 DISPUTE_NOT_ALLOWED — второй диспут не создаётся. Если ответ на первый запрос потерялся, найдите диспут через GET /disputes?search={orderId}.

Ошибки

HTTPerrorCodeОписание
400DISPUTE_NOT_ALLOWEDСпор можно открыть только по завершённому ордеру — ордер не в success/failed, в том числе уже disputed
400DISPUTE_NOT_ALLOWEDНевозможно открыть спор: отсутствует walletOrderId — ордер не дошёл до платёжной стороны
400VALIDATION_ERRORПустой reason
403PERMISSION_DENIEDУ ключа нет права orders.write
404ORDER_NOT_FOUNDОрдер не найден
502WALLET_BACKEND_ERRORПлатёжная сторона не приняла диспут. Статус ордера не изменился — запрос можно повторить

Процесс рассмотрения

  1. submitted — диспут создан
  2. resolved — решение принято, исход в resolution

Время рассмотрения: обычно 1-3 рабочих дня.

Часть диспутов закрывается автоматически, без участия администратора: если по ордеру приходит финальный статус от платёжной стороны, диспут закрывается согласованно с ним (resolvedBy: wallet_callback).

Если платёжная сторона решает спор частичным возвратом, на баланс приходит операция order_partial_refund, а ордер при этом может остаться в статусе disputed, и диспут — в submitted. Сверяйтесь с историей баланса.

Рекомендации

  1. Описывайте подробно — чем больше деталей в reason, тем быстрее решение
  2. Прикладывайте доказательства — скриншоты, логи (через поддержку)
  3. Не дублируйте — один диспут на ордер
  4. Отслеживайте статус — проверяйте список диспутов

Поддержка

Для ускорения рассмотрения свяжитесь с поддержкой:

  • Telegram: @lumo_support_bot
  • Укажите ID диспута и детали ситуации