# Получение инвойса

> Получайте инвойс по идентификатору, проверяйте состояние оплаты и подтверждения и надёжно сверяйте ответ со своим номером заказа.

`GET /v1/invoices/:invoice_id`

:::endpoint
GET /v1/invoices/:invoice_id
:::

**API-ключ:** `Payment`

Возвращает текущее состояние инвойса. Формат ответа — тот же, что и при создании инвойса; объект `payment` появляется после выбора токена и сети.

## Ответ (200 OK)

```json
{
  "invoice_id": "inv_5CcyDYmMUGtzYL10q0Iimr",
  "project_id": "prj_xFukZuAJZR06pLVBh3uwzv",
  "status": "paid",
  "is_final": true,
  "is_test": false,
  "payment_url": "https://checkout.paymos.io/invoice/inv_5CcyDYmMUGtzYL10q0Iimr",
  "order": {
    "external_id": "order-12345",
    "client_id": "customer-67890",
    "amount": "50.00",
    "currency": "USDT",
    "network": "TRC20"
  },
  "payment": {
    "currency": "USDT",
    "network": "TRC20",
    "chain_id": 728126428,
    "contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
    "expected": "50.00",
    "address": "TLfGqSVPbET2KFczh3xb12Ja2RKfMCBPgp",
    "exchange_rate": "1.000000",
    "paid": "50.00",
    "remaining": "0",
    "fee": "0.50",
    "net": "49.50",
    "transfers": [
      {
        "tx_hash": "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
        "amount": "50.00",
        "status": "confirmed",
        "created_at": 1739280712,
        "confirmed_at": 1739280912,
        "required_confirmations": 19,
        "estimated_confirmation_at": 1739280772,
        "explorer_url": "https://tronscan.org/#/transaction/abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
      }
    ]
  },
  "created_at": 1739280600,
  "updated_at": 1739280912,
  "expires_at": 1739284200,
  "completed_at": 1739280912
}
```

## Поля payment

Когда объект `payment` присутствует, он содержит:

| Поле | Тип | Описание |
|------|-----|----------|
| `payment.currency` | string | Символ криптоактива, выбранный для оплаты (например `USDT`, `USDC`) |
| `payment.network` | string | Код сети блокчейна (например `ERC20`, `TRC20`, `BEP20`, `POLYGON`, `BASE`, `TON`, `SOL`) |
| `payment.chain_id` | integer | Числовой идентификатор сети по правилам EIP-155, Tron или TON (например, `1` для основной сети Ethereum, `728126428` для Tron) |
| `payment.contract_address` | string? | Идентификатор токена в сети — адрес контракта в EVM и Tron, мастер-контракт жетона в TON, SPL-mint в Solana. Тип допускает пустое значение — у нативной монеты такого идентификатора не бывает. Но нативных монет среди принимаемых активов нет, поэтому на реальном инвойсе поле всегда заполнено. Для своего `contract_address` то же правило описывает `GET /v1/payment-channel-deposits/:id` |
| `payment.expected` | string | Ожидаемая сумма в токене, которую должен отправить клиент |
| `payment.address` | string? | Адрес, на который платит клиент. Пока инвойс в статусе `awaiting_client`, объекта `payment` в ответе нет целиком — то есть на неоплаченном инвойсе это поле не приходит как `null`, читать просто нечего |
| `payment.exchange_rate` | string? | Курс фиата к токену, по которому посчитан `expected` |
| `payment.paid` | string? | Сумма подтверждённых входящих переводов |
| `payment.remaining` | string? | Оставшаяся сумма к доплате (`expected - paid`, не бывает отрицательной). Появляется после первого подтверждённого перевода |
| `payment.fee` | string? | Платформенная комиссия, удерживаемая из `paid` |
| `payment.net` | string? | Сумма к зачислению мерчанту (`paid - fee`) |
| `payment.transfers` | array? | Детали по каждому переводу — присутствует, когда в блокчейне обнаружен хотя бы один перевод. См. ниже. |

## Поля перевода

Каждый элемент массива `payment.transfers[]`:

| Поле | Тип | Описание |
|------|-----|----------|
| `tx_hash` | string | Хеш транзакции в блокчейне (формат зависит от сети) |
| `amount` | string | Сумма перевода в токене |
| `status` | string | `confirming` (ждём подтверждений) или `confirmed` |
| `created_at` | unix timestamp | Когда наш обработчик блоков впервые увидел перевод в обработанном блоке. Это **время по часам нашего сервера**, а не время блока в сети — они расходятся, если обработчик отставал. Используйте именно это поле (а не `created_at` инвойса верхнего уровня) в формуле «осталось секунд» ниже. |
| `confirmed_at` | unix timestamp? | Когда перевод достиг требуемого числа подтверждений. `null`, пока перевод ещё не подтверждён |
| `required_confirmations` | integer? | Сколько подтверждений нужно этому переводу, чтобы перейти в `confirmed` — зависит от USD-уровня его суммы. `null` на любой сети, которая закрывается собственным флагом `finalized`, а не счётчиком блоков: сегодня это BNB Smart Chain, Polygon, Solana, Avalanche и Plasma. Ветвитесь по самому `null`, а не по списку сетей — состав списка операционный и может измениться |
| `estimated_confirmation_at` | unix timestamp? | Когда перевод предположительно дойдёт до расчёта. На сетях со счётчиком блоков считается в момент обнаружения как `transfer.created_at + required_confirmations × network_block_time`; на сетях с флагом финальности, где считать нечего, это `transfer.created_at` плюс типичная для этой сети финальность — так ожидание всё равно можно нарисовать. Значение **фиксированное** — не меняется от запроса к запросу и остаётся прежним при каждом опросе, пока перевод не перейдёт в `confirmed` (или пока не сменится USD-уровень его суммы). Чтобы получить «осталось секунд», считайте на стороне клиента: `max(0, estimated_confirmation_at − now)`. |
| `explorer_url` | string? | Прямая ссылка на эту транзакцию в обозревателе блоков сети (Tronscan / Etherscan / Tonviewer и т. п.). `null`, если для сети не настроен публичный обозреватель. Можно выводить как кликабельную ссылку без изменений — преобразовывать её не нужно. |

## Статусы инвойса

У каждого инвойса есть поле `status`. Одно и то же значение приходит в ответе API, в потоке SSE на странице оплаты и в вебхуке — источник один. Таблица ниже — справочник по статусам: когда статус наступает, терминальный он или нет и при каком условии возникает. Схему переходов и оба потока создания смотрите в разделе [Платёжный процесс](/ru/docs/payment-flow.md).

**Терминальный** статус — конечный: инвойс на нём закрывается и больше не меняется. Терминальных пять — `paid`, `paid_over`, `underpaid`, `expired`, `cancelled`.

| Статус | Терминальный | Описание |
|--------|-------------|----------|
| `awaiting_client` | Нет | Стартовый статус любого инвойса. Клиент ещё не выбрал токен/сеть, поэтому адрес для оплаты не назначен. Отменить инвойс можно только в этом статусе |
| `awaiting_payment` | Нет | Адрес назначен, ожидает входящий перевод |
| `confirming` | Нет | Перевод виден в блокчейне и набирает число подтверждений, положенное его сумме |
| `underpaid_waiting` | Нет | Получена частичная оплата, ожидает остаток (только при `allow_multiple_payments` = true) |
| `paid` | Да | Ожидаемая сумма получена полностью — либо в пределах допуска по недоплате, заданного в проекте |
| `paid_over` | Да | Полученная сумма превышает ожидаемую (зачисляется полностью) |
| `underpaid` | Да | Инвойс закрылся с недоплатой: либо истёк, не добрав до ожидаемой суммы, либо единственный платёж не покрыл её при `allow_multiple_payments` = false |
| `expired` | Да | Срок инвойса вышел: платежа не было либо токен и сеть так и не выбрали |
| `cancelled` | Да | Инвойс отменён мерчантом (только из статуса `awaiting_client`) |

## Ошибки

См. [Коды ошибок](/ru/docs/errors/codes.md) — полный каталог. URI в поле `type` каждой ошибки ведёт сразу на нужную строку.
