> ## Documentation Index
> Fetch the complete documentation index at: https://oblodai.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Три режима создания счёта

Метод [`POST /v1/payment`](/reference/payment-create) умеет создавать счёт тремя способами —
в зависимости от того, насколько заранее вы (или покупатель) определяете валюту и сеть оплаты.

<Note>
  **Главный сценарий: цена в фиате, монету выбирает покупатель.** У вас в магазине ценник в привычной
  валюте (`USD`, `EUR`, `RUB`…), а чем платить — USDT, BTC, TRX — и в какой сети решает сам покупатель
  на странице оплаты. Это **Режим 3**, и именно с него стоит начинать: он ничего не требует, кроме суммы
  и валюты цены, и даёт покупателю максимальный выбор (а значит, конверсию).

  Режимы 1 и 2 нужны, когда вы **сознательно** сужаете выбор — например, принимаете только USDT в
  дешёвой сети, чтобы не разгребать зоопарк монет на балансе.
</Note>

***

## Сначала: цена и расчёт — это разные валюты

Режимы касаются **валюты расчёта**, а не валюты цены. Не путайте два поля:

| Поле          | Роль                               | Что может быть                                                                            |
| ------------- | ---------------------------------- | ----------------------------------------------------------------------------------------- |
| `currency`    | **Цена**: сколько счёт стоит.      | Любой из **23 фиатов** (`USD`, `EUR`, `RUB`, …) **или** крипта (`USDT`, `BTC`, `TRX`, …). |
| `to_currency` | **Расчёт**: чем покупатель платит. | **Только крипта.** Фиат здесь невозможен.                                                 |

Шлюз сам пересчитает фиатную цену в крипту по курсу (округляя **вверх**, в пользу счёта):

<CodeGroup>
  ```python Python theme={null}
  call("/v1/payment", {"amount": "10", "currency": "USD", "order_id": "order-1",
                       "to_currency": "TRX", "network": "tron"})
  # → amount: "10.00" USD, payer_amount: "83.333334" TRX
  ```

  ```js Node.js theme={null}
  await call("/v1/payment", { amount: "10", currency: "USD", order_id: "order-1",
                              to_currency: "TRX", network: "tron" });
  // → amount: "10.00" USD, payer_amount: "83.333334" TRX
  ```
</CodeGroup>

Баланс, выплаты и возвраты при этом **всегда в крипте** — фиат шлюз не хранит. См.
[Форматы сумм и денег](/reference/basics-money).

***

## Цену можно назначать не только в долларах

Валюта цены — это **не обязательно `USD`**. Поддерживаются **23 фиатные валюты**:

|                            |                                                       |
| -------------------------- | ----------------------------------------------------- |
| **Европа**                 | `EUR` · `GBP` · `PLN` · `CZK` · `CHF`                 |
| **СНГ / Восточная Европа** | `RUB` · `UAH`                                         |
| **Америка**                | `USD` · `CAD` · `BRL` · `MXN`                         |
| **Азия**                   | `CNY` · `INR` · `JPY` · `KRW` · `IDR` · `THB` · `VND` |
| **Прочие**                 | `TRY` · `AED` · `ZAR` · `AUD` · `NGN`                 |

Работают ровно так же, как `USD`, — во всех трёх режимах:

<CodeGroup>
  ```python Python theme={null}
  call("/v1/payment", {"amount": "100", "currency": "EUR", "order_id": "order-8",
                       "to_currency": "USDT", "network": "tron"})
  # → 100.00 EUR ≈ 108.695653 USDT

  call("/v1/payment", {"amount": "5000", "currency": "RUB", "order_id": "order-2",
                       "to_currency": "USDT", "network": "tron"})
  # → 5000.00 RUB ≈ 54.347827 USDT

  call("/v1/payment", {"amount": "2000", "currency": "UAH", "order_id": "order-3"})
  # → валюто-агностичный счёт (is_multi: true), цена в гривне, монету выберет покупатель
  ```

  ```js Node.js theme={null}
  await call("/v1/payment", { amount: "100", currency: "EUR", order_id: "order-8",
                              to_currency: "USDT", network: "tron" });
  // → 100.00 EUR ≈ 108.695653 USDT

  await call("/v1/payment", { amount: "5000", currency: "RUB", order_id: "order-2",
                              to_currency: "USDT", network: "tron" });
  // → 5000.00 RUB ≈ 54.347827 USDT

  await call("/v1/payment", { amount: "2000", currency: "UAH", order_id: "order-3" });
  // → валюто-агностичный счёт (is_multi: true), цена в гривне, монету выберет покупатель
  ```
</CodeGroup>

**Цена в евро так же надёжна, как в долларах.** Источник курсов отдаёт цену монеты **сразу в нужной
валюте**, одной таблицей — ничего не перемножается через доллар и второго провайдера в цепочке нет.
Так что выбирать `USD` «для надёжности» смысла не имеет: берите валюту, в которой у вас реальный ценник.

### У JPY и KRW — ноль знаков после запятой

Иена и вона не имеют дробной части. Сумма передаётся **целым числом**:

<CodeGroup>
  ```python Python theme={null}
  call("/v1/payment", {"amount": "10000", "currency": "JPY", "order_id": "order-4",
                       "to_currency": "USDT", "network": "tron"})
  # → 10000 JPY ≈ 66.666667 USDT      ✅ "10000", а НЕ "10000.00"
  ```

  ```js Node.js theme={null}
  await call("/v1/payment", { amount: "10000", currency: "JPY", order_id: "order-4",
                              to_currency: "USDT", network: "tron" });
  // → 10000 JPY ≈ 66.666667 USDT      ✅ "10000", а НЕ "10000.00"
  ```
</CodeGroup>

У остальных 21 фиатной валюты — 2 знака (`"10.00"`).

### Что НЕ поддерживается

**Тенге (`KZT`), сом (`KGS`) и сум (`UZS`) — не поддерживаются.** Попытка вернёт
`400 payment.unknown_currency`:

<CodeGroup>
  ```python Python theme={null}
  call("/v1/payment", {"amount": "5000", "currency": "KZT"})  # … остальные поля
  # → 400 payment.unknown_currency
  ```

  ```js Node.js theme={null}
  await call("/v1/payment", { amount: "5000", currency: "KZT", /* … */ });
  // → 400 payment.unknown_currency
  ```
</CodeGroup>

Причина: источник курсов не котирует крипту в этих валютах напрямую, а считать через доллар (два курса
подряд) мы не будем — это вторая точка отказа и второй источник расхождений в цене. Обходной путь:
назначайте цену в `USD` и пересчитывайте в тенге/сом/сум **у себя на витрине**.

Актуальный список валют цены всегда можно получить программно — в
[`GET /v1/currencies`](/reference/currencies) это блок **`pricing_currencies`** (монеты + фиаты,
у фиатов стоит `"fiat": true` и указан `decimals`). Не хардкодьте список — читайте его.

***

## Режим 1. Фиксированная валюта и сеть

Вы точно знаете, чем и в какой сети платит покупатель. Задаёте `to_currency` **и** `network`.

<CodeGroup>
  ```python Python theme={null}
  call("/v1/payment", {
      "amount": "10", "currency": "USD", "order_id": "order-5",
      "to_currency": "USDT", "network": "tron",
  })
  ```

  ```js Node.js theme={null}
  await call("/v1/payment", {
    amount: "10", currency: "USD", order_id: "order-5",
    to_currency: "USDT", network: "tron",
  });
  ```
</CodeGroup>

Результат: обычный одновалютный счёт с готовым адресом сразу.

**Когда использовать:** у вас на чекауте покупатель уже выбрал «USDT в сети Tron», и вы передаёте
конкретную пару.

***

## Режим 2. Авто‑нормализация сети

Вы задаёте валюту (`to_currency`/`currency`), но **не** задаёте `network`.

<CodeGroup>
  ```python Python theme={null}
  call("/v1/payment", {
      "amount": "10", "currency": "USD", "order_id": "order-6",
      "to_currency": "BTC",   # network не указан
  })
  ```

  ```js Node.js theme={null}
  await call("/v1/payment", {
    amount: "10", currency: "USD", order_id: "order-6",
    to_currency: "BTC",   // network не указан
  });
  ```
</CodeGroup>

* Если у валюты **ровно одна** сеть (как у `BTC` → `bitcoin`), она подставится автоматически.
* Если у валюты **несколько** сетей (как у `USDT`), вернётся ошибка `payment.network_required` — сеть
  нужно указать явно.

**Когда использовать:** для «односетевых» валют, чтобы не писать сеть руками.

***

## Режим 3. Валюто‑агностичный (deferred) счёт

Это и есть **главный сценарий** из начала страницы: ценник в фиате, монету и сеть выбирает покупатель.

Валюто‑агностичный (deferred) счёт — это счёт без заранее выбранной валюты и сети: их выбирает не вы,
а сам покупатель, уже на странице оплаты.

Вы **не** задаёте ни `to_currency`, ни `network` — оба пустые. Валюту и сеть выбирает **покупатель** на
hosted‑странице (страница оплаты на стороне Oblodai, куда вы редиректите покупателя по ссылке `url`).

<CodeGroup>
  ```python Python theme={null}
  inv = call("/v1/payment", {
      "amount": "10", "currency": "USD", "order_id": "order-7",
      # to_currency и network НЕ переданы
  })["result"]

  assert inv["is_multi"] is True              # признак агностичного счёта
  assert inv["payment_status"] == "select"   # статус «монета ещё не выбрана»
  # payer_currency — ПУСТАЯ строка; address, payer_amount, address_qr_code тоже пусты,
  # пока покупатель не выбрал монету (валюты расчёта у счёта ещё нет).
  # А amount/currency — уже есть: "10" USD.
  ```

  ```js Node.js theme={null}
  const inv = (await call("/v1/payment", {
    amount: "10", currency: "USD", order_id: "order-7",
    // to_currency и network НЕ переданы
  })).result;

  console.assert(inv.is_multi === true);             // признак агностичного счёта
  console.assert(inv.payment_status === "select");   // статус «монета ещё не выбрана»
  // payer_currency — ПУСТАЯ строка; address, payer_amount, address_qr_code тоже пусты,
  // пока покупатель не выбрал монету (валюты расчёта у счёта ещё нет).
  // А amount/currency — уже есть: "10" USD.
  ```
</CodeGroup>

<Note>
  **Пустой `address` и пустой `payer_currency` — это не баг.** Пока счёт в статусе `select`, валюты
  расчёта у него просто нет, а значит, неоткуда взяться ни адресу, ни сумме в крипте. По той же причине
  [возврат](/guides/refunds) такого счёта вернёт `refund.nothing_to_refund` — возвращать нечего.
</Note>

Поле `is_multi` в ответе — это флаг «мультивалютности»: `true` означает, что счёт агностичный и валюту
ещё предстоит выбрать покупателю, `false` — валюта и сеть уже зафиксированы (Режимы 1 и 2).

Дальше на странице оплаты покупатель вызывает
[`POST /v1/pay/{id}/select`](/reference/pay-select) с выбранной парой — тогда фиксируется курс и
выделяется адрес.

**Когда использовать:** вы хотите дать покупателю выбор монеты прямо на странице оплаты, не спрашивая
заранее.

### Чем ограничить выбор

По умолчанию покупателю доступен весь каталог. Чтобы сузить список принимаемых валют, задайте набор
через [`POST /v1/payment/accepted/set`](/reference/payment-accepted):

<CodeGroup>
  ```python Python theme={null}
  call("/v1/payment/accepted/set", {"accepted": [
      {"currency": "USDT", "network": "tron"},
      {"currency": "USDC", "network": "polygon"},
  ]})
  ```

  ```js Node.js theme={null}
  await call("/v1/payment/accepted/set", { accepted: [
    { currency: "USDT", network: "tron" },
    { currency: "USDC", network: "polygon" },
  ]});
  ```
</CodeGroup>

Выбор покупателя валидируется против этого набора (или полного каталога, если набор пуст).

***

## Сравнение

|                             | Режим 1               | Режим 2            | **Режим 3**              |
| --------------------------- | --------------------- | ------------------ | ------------------------ |
| `to_currency`               | задан                 | задан              | пусто                    |
| `network`                   | задан                 | пусто              | пусто                    |
| `currency` (цена)           | фиат или крипта       | фиат или крипта    | фиат или крипта          |
| Адрес в ответе              | сразу                 | сразу              | после выбора покупателем |
| `is_multi`                  | `false`               | `false`            | `true`                   |
| Статус сразу после создания | `check`               | `check`            | **`select`**             |
| Кто выбирает валюту         | вы                    | вы (сеть авто)     | **покупатель**           |
| Когда брать                 | Принимаете один актив | Односетевая монета | **По умолчанию**         |

***

## Частая ошибка: цена в фиате и сеть без монеты

Если цена задана **в фиате** (`USD`, `EUR`, `RUB` — любом), и вы задали `network`, но **не** задали
`to_currency`, шлюз вернёт `400 payment.to_currency_required`:

<CodeGroup>
  ```python Python theme={null}
  call("/v1/payment", {"amount": "10", "currency": "USD", "network": "tron"})
  # → 400 payment.to_currency_required

  call("/v1/payment", {"amount": "100", "currency": "EUR", "network": "tron"})
  # → 400 payment.to_currency_required  — правило то же для ЛЮБОГО фиата
  ```

  ```js Node.js theme={null}
  await call("/v1/payment", { amount: "10", currency: "USD", network: "tron" });
  // → 400 payment.to_currency_required

  await call("/v1/payment", { amount: "100", currency: "EUR", network: "tron" });
  // → 400 payment.to_currency_required  — правило то же для ЛЮБОГО фиата
  ```
</CodeGroup>

Из фиатной цены монету расчёта вывести нельзя: в сети `tron` это может быть и USDT, и TRX, и USDC.
Два выхода:

* **укажите монету** — `"to_currency": "USDT"` (Режим 1);
* **уберите и `network`** — тогда монету и сеть выберет покупатель (Режим 3).

Умолчание «`to_currency` = `currency`» срабатывает, только когда цена задана **в крипте**: для
`{"currency": "USDT", "network": "tron"}` расчёт пойдёт в `USDT`. С фиатом такого умолчания нет и быть
не может — фиатом в блокчейне не платят.

***

## Полезные детали

* **Комиссия** фиксируется уже при создании во всех трёх режимах. В агностичном режиме курс и адрес
  фиксируются в момент выбора, а комиссия — сразу.
* **`is_refresh`** оживляет просроченный счёт по `order_id` вместо создания нового — работает во всех
  режимах. См. [`POST /v1/payment`](/reference/payment-create).

***

## Связанные страницы

<CardGroup cols={2}>
  <Card title="POST /v1/payment" href="/reference/payment-create" icon="arrow-right" horizontal />

  <Card title="POST /v1/pay/{id}/select" href="/reference/pay-select" icon="arrow-right" horizontal />

  <Card title="POST /v1/payment/accepted/list · /set" href="/reference/payment-accepted" icon="arrow-right" horizontal />

  <Card title="Форматы сумм и денег" href="/reference/basics-money" icon="arrow-right" horizontal />

  <Card title="GET /v1/currencies" href="/reference/currencies" icon="arrow-right" horizontal />

  <Card title="Приём первого платежа" href="/guides/accept-first-payment" icon="arrow-right" horizontal />

  <Card title="Платёжные ссылки" href="/guides/payment-links" icon="arrow-right" horizontal>
    те же режимы суммы и валюты, но без бэкенда.
  </Card>

  <Card title="Массовые операции" href="/guides/batch-operations" icon="arrow-right" horizontal>
    до 5000 счетов одним запросом.
  </Card>
</CardGroup>
