# Сверка заявок

Метод [`GET /api/v1/payments`](api-reference.md#listPayments) отдаёт заявки вашего
проекта от новых к старым, страницами. Каждый элемент — тот же объект, что ответ
`GET /api/v1/payments/{id}`: статус, суммы, реквизиты и расчёт `merchant_information`.
Заявок других проектов в списке нет никогда.

!!! note "Тестовые заявки в списке"
    Тестовые заявки (песочница, тестовый режим проекта) идут в списке вместе с боевыми и
    помечены `is_test: true`; у боевых — `is_test: false`. Поле есть в каждом элементе.
    Для сверки денег берите `is_test=false` — только боевые заявки.

Для чего он нужен:

- **Сверка за период.** Раз в сутки (или чаще) пройдите все заявки за прошедший день и
  сравните статусы и суммы со своими заказами.
- **Восстановление после сбоя.** Ваш сервер не сохранил ответ на создание или пропустил
  callback-и — найдите заявку по своему номеру заказа или пройдите список за время сбоя.
- **Поиск по номеру заказа.** `merchant_payment_id` уникален в проекте: фильтр по нему
  отдаёт одну заявку, `id` знать не нужно.

Нужно право токена `payments:read`. Подпись — как у других запросов чтения: только если её
требует политика проекта.

## Запрос { #request }

```http
GET /api/v1/payments?status=completed,canceled&is_test=false&created_from=2026-10-01T00:00:00%2B03:00&created_to=2026-10-02T00:00:00%2B03:00&limit=100
Authorization: Bearer nl_test_...
```

| Параметр | Что значит |
| --- | --- |
| `status` | Только эти статусы, через запятую: `completed,canceled`. Параметр можно и повторить. Не передан — любой статус |
| `merchant_payment_id` | Только заявка с этим номером заказа, точное совпадение |
| `created_from` | Создана в этот момент или позже. RFC 3339 с часовым поясом |
| `created_to` | Создана раньше этого момента (не включая его). RFC 3339 с часовым поясом |
| `cursor` | `next_cursor` предыдущей страницы. Не передан — первая страница |
| `limit` | Заявок на странице, от 1 до 100. По умолчанию 50 |
| `is_test` | `true` — только тестовые заявки, `false` — только боевые. Не передан — все |

Все параметры необязательны и объединяются через И. Знак `+` часового пояса в адресе
передавайте как `%2B`, иначе он прочитается как пробел — или пишите время в UTC:
`2026-09-30T21:00:00Z`.

## Ответ { #response }

```json
{
  "items": [
    {
      "id": "3f1c2b9e-6a8d-4c4b-9a71-2c7f5d1e0a42",
      "merchant_payment_id": "order-42",
      "status": "completed",
      "amount": 3400,
      "currency": "RUB",
      "is_test": false,
      "...": "остальные поля — как у GET /api/v1/payments/{id}"
    }
  ],
  "next_cursor": "MTc5MDY3NDIwMDAwMDAwMDAwMHwzZjFjMmI5ZS02YThkLTRjNGItOWE3MS0yYzdmNWQxZTBhNDI"
}
```

- `items` — заявки страницы от новых к старым; пустой массив, если заявок нет.
- `next_cursor` — строка, если есть следующая страница, и `null` на последней. Курсор
  непрозрачный: не разбирайте и не составляйте его сами.

## Обход всех страниц { #pagination }

Запросите первую страницу, затем повторяйте тот же запрос с `cursor` из `next_cursor`,
пока `next_cursor` не станет `null`. Фильтры передавайте **те же** на каждой странице.

```python
params = {"created_from": "2026-10-01T00:00:00Z", "created_to": "2026-10-02T00:00:00Z", "is_test": "false", "limit": 100}
while True:
    page = get("/api/v1/payments", params)  # подпись — если её требует политика проекта
    for payment in page["items"]:
        reconcile(payment)  # сравнить статус и сумму со своим заказом
    if page["next_cursor"] is None:
        break
    params["cursor"] = page["next_cursor"]
```

- Заявки упорядочены по времени создания, затем по `id`. Обход не повторяет и не
  пропускает заявки, даже созданные в одно и то же мгновение.
- Заявки, созданные после начала обхода, в него не попадают. Чтобы увидеть их, начните
  новый обход — например, с `created_from` = времени начала прошлого.
- Статус заявки может измениться во время обхода: элемент показывает статус на момент
  чтения своей страницы. Для сверки закрытого периода берите заявки старше срока заявки
  проекта — их статус уже финальный (кроме проверки оплаты, см.
  [Смена статуса после закрытия](callbacks.md#status-changes)).
- У проекта общий [лимит запросов](idempotency.md#rate-limits): для больших периодов
  берите `limit=100` и не запускайте несколько обходов параллельно.

## Поиск по номеру заказа { #by-order }

```http
GET /api/v1/payments?merchant_payment_id=order-42
Authorization: Bearer nl_test_...
```

В ответе одна заявка или пустой `items`, если заявки с таким номером в проекте нет.
Номер — в том же формате, что при создании: 1–64 символа `A-Z a-z 0-9 . _ : -`.

## Ошибки { #errors }

Неверный параметр — `400`, ничего не прочитано:

| `error` | Когда |
| --- | --- |
| `invalid_status` | Статус не из [статусов заявки](statuses.md#statuses) |
| `invalid_merchant_payment_id` | `merchant_payment_id` не в формате номера заказа |
| `invalid_date_range` | `created_from` или `created_to` не RFC 3339 с часовым поясом, или `created_from` позже `created_to` |
| `invalid_cursor` | `cursor` — не `next_cursor` этого API |
| `invalid_limit` | `limit` — не целое число от 1 до 100 |
| `invalid_is_test` | `is_test` — не `true` и не `false` |

Нет права `payments:read` — `403 insufficient_scope`. Остальные ошибки — как у любого
запроса, см. [Статусы и ошибки](statuses.md#http-errors).