# Payment API

> Створюйте та керуйте сесіями криптовалютних платежів за допомогою Payment API від 2328.io.

Payment API дозволяє створювати платіжні сесії, перенаправляти клієнтів на хостинговий checkout та відстежувати статус платежу.

## Створити платіж

Створює платіжну сесію та повертає URL, за яким клієнт здійснює оплату.

### Параметри запиту

| Поле | Тип | Обов'язкове | Опис | Значення |
|------|-----|-------------|------|----------|
| `amount` | decimal | так | Сума платежу у валюті, наприклад, `100.00` |  |
| `currency` | string | так | Фіатна валюта (USD, EUR, RUB, …) або криптовалюта (USDT, TRX, BTC, …) | `USD`, `EUR`, `RUB`, `KZT`, `UAH`, `UZS`, `USDT`, `USDC`, `BTC`, `ETH`, `GRAM`, `SOL`, `TRX`, `BNB`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `order_id` | string | так | Ваш ID замовлення, наприклад, `ORDER-12345` (до 128 символів) |  |
| `to_currency` | string | ні | Попередньо обрана криптовалюта | `USDT`, `USDC`, `BTC`, `ETH`, `GRAM`, `SOL`, `TRX`, `BNB`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `network` | string | ні\* | Код мережі (обов'язковий, якщо встановлено `to_currency` або `currency` є криптовалютою) | `TRX-TRC20`, `ETH-ERC20`, `BASE`, `BSC-BEP20`, `AVAX-C`, `POL-MATIC`, `TON`, `SOL`, `BTC`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `url_return` | string | ні | URL перенаправлення після оплати, наприклад, `https://your-site.com/return` |  |
| `url_success` | string | ні | Альтернатива `url_return` |  |
| `url_callback` | string | так | URL для webhook-сповіщень, наприклад, `https://your-site.com/webhook` |  |
| `invite_code` | string | ні | Код реферера |  |
| `fee_split` | decimal | ні | Частка мерчант-комісії, що передається платнику, 0–100 (%). 0 = мерчант сплачує повністю, 100 = платник сплачує повністю. Перевизначає налаштування рівня проєкту. **Приклад: `30`** (платник покриває 30% комісії). |  |
| `price_markup` | decimal | ні | Націнка або знижка на суму рахунку, від −99 до 100 (%). Перевизначає налаштування рівня проєкту. **Приклад: `5`** (+5%) або `-10` (знижка 10%). |  |
| `description` | string | ні | Необов'язковий опис рахунку (макс. 200 символів). Відображається платнику на сторінці оплати. **Приклад: `Premium plan — Order #12345`**. |  |
| `ttl_seconds` | int | ні | Час життя рахунку в секундах, від `300` (5 хвилин) до `86400` (24 годин). Після цього часу рахунок завершується й сплатити його більше не можна. За замовчуванням: `3600` (1 година). **Приклад: `3600`**. |  |

### Відповідь

```json
{
  "state": 0,
  "result": {
    "uuid": "abc123-def456-...",
    "order_id": "ORDER-12345",
    "amount": "100.00",
    "currency": "USD",
    "amount_usd": "100.00",
    "exchange_rate": null,
    "url": "https://2328.io/pay/abc123-def456-...",
    "tg_deeplink": "https://t.me/my2328bot?start=pay_abc123-def456-...",
    "expires_at": "2026-01-11T21:00:00Z",
    "created_at": "2026-01-11T20:00:00Z",
    "payer_currency": "USDT",
    "payer_amount": "100.50",
    "network": "TRX-TRC20",
    "address": "TXYZabc123...",
    "payment_status": "check",
    "txid": null,
    "payment_amount": null,
    "qr": "data:image/png;base64,iVBORw0..."
  }
}
```

- Перенаправте клієнта на `result.url` для завершення оплати.
- `tg_deeplink` — deeplink Telegram-бота для оплати через Telegram MiniApp.
- `qr` — QR-код депозитної адреси, закодований у base64 (data URI). Присутній, коли адресу вже призначено (коли `network` встановлено разом із `to_currency` або коли `currency` є криптовалютою); інакше `null`.
- `txid`, `payment_amount` — `null`, доки клієнт не оплатить. Заповнюються після виявлення транзакції у блокчейні. Слухайте webhook `payment_status: paid`, щоб дізнатися момент.
- `exchange_rate` — `null`, якщо конвертація ще не застосовна (наприклад, курс фіат → крипто ще не зафіксовано). Заповнюється після вибору валюти платника.

> Use your project UUID and the endpoint-appropriate API key from the merchant dashboard.

#### Interactive request: `POST /v1/payment`
  - `amount` (decimal, required)
  - `currency` (enum, required): USD,EUR,RUB,KZT,UAH,UZS,USDT,USDC,BTC,ETH,GRAM,SOL,TRX,BNB,POL,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `order_id` (string, required)
  - `to_currency` (enum): USDT,USDC,BTC,ETH,GRAM,SOL,TRX,BNB,POL,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `network` (enum): TRX-TRC20,ETH-ERC20,BASE,BSC-BEP20,AVAX-C,POL-MATIC,TON,SOL,BTC,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `url_return` (string)
  - `url_success` (string)
  - `url_callback` (string, required)
  - `invite_code` (string)
  - `fee_split` (decimal)
  - `price_markup` (decimal)
  - `description` (string)
  - `ttl_seconds` (integer)

## Розміщена каса, H2H та точні крипто-суми

Той самий кінцевий пункт підтримує три різних форми рахунків. Оберіть одну свідомо; не змішуйте їх семантику сум.

### Розміщена каса з вибором платника

Надішліть `amount`, `currency`, `order_id` та `url_callback`, але пропустіть `to_currency` та `network`. Відповідь містить `result.url`; `address`, `qr` та іноді поля платника залишаються `null`, поки платник не обере напрямок на розміщеній сторінці.

```json
{
  "amount": "125.00",
  "currency": "EUR",
  "order_id": "ORDER-2026-1042",
  "url_callback": "https://merchant.example/webhooks/2328",
  "url_return": "https://merchant.example/orders/ORDER-2026-1042"
}
```

### Прямий рахунок H2H

Надішліть обидва `to_currency` та `network`. 2328.io створює блокчейн-рахунок під час виклику API, тому успішну відповідь можна відобразити безпосередньо у вашому оформленні замовлення без перенаправлення клієнта.

```json
{
  "amount": "100.00",
  "currency": "USD",
  "to_currency": "USDT",
  "network": "TRX-TRC20",
  "order_id": "ORDER-2026-1043",
  "url_callback": "https://merchant.example/webhooks/2328"
}
```

Відображайте ці значення точно так, як вони повернуті:

- `payer_amount` та `payer_currency` — інструкція для оплати;
- `network` та `address` — єдина адреса для цього рахунку;
- `qr` — data URI для тієї ж адреси;
- `expires_at` — термін дії рахунку;
- `url` — корисний розміщений резервний варіант, коли кастомне оформлення замовлення не може бути завершене.

> **DANGER:** Ніколи не генеруйте та не замінюйте адресу, не використовуйте адресу з іншого рахунку-фактури та не обчислюйте `payer_amount` за публічною спотовою ціною. Відповідь API є авторитетною.

### Рахунок-фактура на точну суму криптовалюти

Помістіть криптовалюту в `currency`, коли сам рахунок-фактура номінований у криптовалюті:

```json
{
  "amount": "25.000000",
  "currency": "USDT",
  "network": "TRX-TRC20",
  "order_id": "ORDER-2026-1044",
  "url_callback": "https://merchant.example/webhooks/2328"
}
```

Запитувана вартість криптовалюти збережена в `payer_currency` / `payer_amount`. Сервіс також може підтримувати внутрішню оцінку в USD для обліку та полів курсу; не замінюйте точну інструкцію щодо криптовалюти на цю оцінку. Зберігайте повернені десяткові рядки, включаючи кінцеву точність.

Для криптовалюти з лише одною підтримуваною мережею мережу можна вибрати автоматично. Проте рекомендується явно вказувати `network` для детермінованої інтеграції. Для активів з багатьма мережами, таких як стейблкоїни, завжди слід його надсилати.

## Ідемпотентність та повторні спроби

`order_id` прив'язується до аутентифікованого проекту продавця та слугує ключем ідемпотентності створення. Якщо платіж вже існує, API повертає ту сесію з `state: 0`.

> **WARNING:** Повторна спроба з тим самим `order_id` не **not** означає «оновити цей рахунок». Змінені сума, валюта, зворотний виклик, націнка, TTL або поля напрямку можуть бути проігноровані, оскільки повертається існуюча сесія. Збережіть перший запит і відхиляйте конфліктні повторні спроби у вашому власному застосунку.

Рекомендований алгоритм створення:

1. Вставте вашу локальну спробу оплати та унікальний `order_id` в одну транзакцію бази даних.
2. Надішліть підписаний API-запит.
3. Збережіть повернутий `uuid` та повну відповідь.
4. Якщо HTTP-результат втрачено, повторіть ідентичний запит або виконайте запит `/v1/payment/info` за допомогою `order_id`.
5. Ніколи не створюйте друге локальне замовлення тільки через те, що запит до зворотного сервера вичерпав час очікування.

## Крайні випадки оплати

| Ситуація | Правильне оброблення |
|-----------|------------------|
| `address` / `qr` є `null` | Напрямок платника не був ініціалізований. Перенаправте до `url` або створіть новий правильно вказаний рахунок H2H з новим `order_id`. |
| Помилка перевірки HTTP `400` | Прочитайте поле на рівні `errors`; не повторюйте спробу з незмінним введенням. |
| HTTP `429` | Спробуйте знову з експоненційним відступом з джитером і залиште той самий `order_id`. |
| HTTP `503` / `direction_disabled` | Оновіть `/v1/directions`; тимчасово приховайте напрямок або спробуйте пізніше. |
| Час очікування запиту клієнта минув | Вважайте результат невідомим. Запитайте за `order_id` перед створенням чогось іншого. |
| `underpaid_check` | Зберігайте часткову подію та очікуйте поповнення або пізнішого статусу. Не нараховуйте двічі, коли надходять додаткові txids. |
| `underpaid` | Остаточний стан недоплати. Застосовуйте налаштовану політику виконання/ручного перегляду до фактично нарахованої суми. |
| `overpaid` | Успішна оплата з надлишком коштів. Виконуйте ідемпотентно та зберігайте фактичні суми для політики звірки/повернення. |
| `aml_lock` | Не здійснюйте автоматичне виконання або випуск коштів; направте до робочого процесу відповідності/підтримки. |
| `cancel` | Рахунок прострочено або скасовано. Не робіть висновків, що пізній он-чейн переказ неможливий; звіряйте будь-яку пізнішу подію з підтримкою. |

URL-адреса повернення браузера використовується лише для навігації. Клієнт може відкрити її без оплати, закрити після оплати або переграти пізніше. Лише підтверджений стан API/webhook може завершити замовлення торговця.

## Інформація про платіж

Отримати поточний статус платежу за `uuid` або `order_id`.

### Параметри запиту

| Поле | Тип | Обов'язкове | Опис | Значення |
|------|-----|-------------|------|----------|
| `uuid` | string | так\* | UUID платежу (з `result.uuid` під час створення) |  |
| `order_id` | string | так\* | Ваш ID замовлення |  |

> **INFO:** Принаймні одне з полів `uuid` або `order_id` є обов'язковим.

#### Interactive request: `POST /v1/payment/info`
  - `uuid` (string)
  - `order_id` (string)

## Список платежів

Отримати список усіх платежів із фільтрацією та пагінацією.

### Параметри запиту

| Поле | Тип | Обов'язкове | Опис | Значення |
|------|-----|-------------|------|----------|
| `status` | string | ні | Фільтрувати за статусом платежу (див. [References](/docs/references)) | `pending`, `check`, `paid`, `underpaid_check`, `underpaid`, `overpaid`, `cancel` |
| `date_from` | date | ні | Початкова дата (YYYY-MM-DD), наприклад, `2026-01-01` |  |
| `date_to` | date | ні | Кінцева дата (YYYY-MM-DD), наприклад, `2026-01-31` |  |
| `page` | int | ні | Номер сторінки, за замовчуванням `1` |  |
| `per_page` | int | ні | Елементів на сторінці, за замовчуванням `15`, максимум `5000` |  |

#### Interactive request: `POST /v1/payment/list`
  - `status` (enum): pending,check,paid,underpaid_check,underpaid,overpaid,cancel
  - `date_from` (string)
  - `date_to` (string)
  - `page` (integer)
  - `per_page` (integer)