Счета (invoices)
Счёт — основная сущность API: сумма, номер заказа, ссылка на оплату и статус. Создаётся одним POST-запросом, живёт от нескольких минут до суток и завершается статусом paid, failed или expired.
API v1 · обновлено 2026-09-12
POST /invoices — создать счёт
Создаёт счёт и возвращает ссылку на страницу оплаты. Запрос — JSON, обязательны только amount и orderId.
Поля запроса
| Поле | Тип | Описание |
|---|---|---|
amount обяз. | string | number | Сумма в рублях: "1500.00". Примем и число, но в ответах сумма всегда строка с двумя знаками. Диапазон — из лимитов метода. |
orderId обяз. | string ≤ 128 | Ваш идентификатор заказа. Уникален в рамках проекта — обеспечивает идемпотентность (ниже). |
description | string ≤ 255 | Назначение платежа. Показывается покупателю на странице оплаты. |
method | sbp | card | Зафиксировать способ оплаты: покупатель минует выбор и по ссылке url сразу попадает на оплату этим способом. Так выбор способа можно сделать на своей стороне (свои кнопки «СБП» / «Картой» → два разных method). Не передан — покупатель выберет сам на странице оплаты. Значение crypto зарезервировано. |
customerFeePct | number | Сколько процентов от суммы платит покупатель сверху — от 0 до вашей ставки по методу (при ставке СБП 9 % — любое значение 0…9; больше ставки → 422 customer_fee_pct_too_high). Остаток ставки платите вы. Пример: ставка 9 %, customerFeePct: 4, счёт на 1 000 ₽ → покупатель платит 1 040 ₽, вы получаете 950 ₽. По умолчанию — ползунки «Кто платит комиссию» в настройках проекта (изначально вся ставка на покупателе). Если способ не задан, значение применяется к каждому методу с обрезкой до его ставки. |
customerFeeShare, feePayer устар. | integer 0…100 | merchant | customer | Старые способы задать то же самое: доля ставки в процентах (пересчитывается в customerFeePct по ставке метода) или customer = вся ставка на покупателе, merchant = 0. Учитываются, только если customerFeePct не передан. |
successUrl | URL | Куда вернуть покупателя после успешной оплаты. По умолчанию — из настроек проекта. |
failUrl | URL | Куда вернуть при отказе или истечении срока. По умолчанию — из настроек проекта. |
expire | integer, минуты | Срок жизни счёта. По умолчанию 60, максимум 1440 (сутки). По истечении — статус expired. |
customer | object | Данные покупателя: email, phone (E.164), userId (ваш id, строка), name. Все поля необязательны. Email подставляется на странице оплаты; остальное хранится для поиска в кабинете и возвращается в вебхуке. |
customFields | object | Произвольный JSON (до 2 КБ) — вернётся в вебхуке и в GET /invoices/{id} без изменений: корзина, метка источника, что угодно. |
payerEmail | string | Устаревший синоним customer.email; поддерживается для совместимости. |
Заголовок Idempotency-Key не требуется: идемпотентность обеспечивает orderId.
Ответ
| Поле | Описание |
|---|---|
id | UUID счёта. Сохраните вместе с заказом. |
url | Страница оплаты https://payrapay.net/pay/<id>. Перенаправьте покупателя (302) или откройте в новой вкладке. |
status | Статус на момент ответа — для нового счёта всегда created. |
amount | Сумма счёта строкой, как вы её передали. |
feePct | Ваша ставка по методу счёта (пока способ не выбран — наибольшая из ваших ставок). |
feeAmount | Комиссия Payra целиком: round(amount × feePct / 100, 2). |
customerFeePct | Процент на покупателе по выбранному методу; null, пока покупатель не выбрал способ (тогда ориентируйтесь на customerFeeAmount, посчитанный по худшему для покупателя методу). |
customerFeeAmount | Часть комиссии, которую покупатель платит сверху: round(amount × customerFeePct / 100, 2). |
payableAmount | Сколько заплатит покупатель: amount + customerFeeAmount. |
netAmount | Сколько зачислится вам: amount − (feeAmount − customerFeeAmount). |
feePayer, customerFeeShare | Устаревшие производные поля для совместимости: merchant при 0 % на покупателе, иначе customer; доля ставки в процентах. |
expiresAt | Момент истечения срока оплаты (ISO 8601, UTC, суффикс Z). |
Идемпотентность по orderId
Повторный POST /invoices с тем же orderId в рамках проекта не создаёт новый счёт: вы получите уже существующий с кодом 200 OK (а не 201). Это безопасно при таймаутах и ретраях — дублей не будет. Если повтор приходит с другой суммой, методом или customerFeePct, вернётся 409 order_id_conflict.
Нужно выставить новый счёт по тому же заказу (например, после истечения срока)? Используйте новый orderId — скажем, order-1042-2.
GET /invoices/{id} — получить счёт
Помимо полей из ответа на создание, объект содержит ваш orderId, выбранный способ, customer, customFields и метки времени. Тот же объект приходит в вебхуке в data.invoice. Поле method — null, пока покупатель не выбрал способ; paidAt — null, пока счёт не оплачен.
Лимит на опрос статуса
Опрашивать один счёт можно не чаще 1 раза в 3 секунды; иначе — 429 с заголовком Retry-After. Для узнавания об оплате предназначены вебхуки; GET используйте для сверки и при возврате покупателя на successUrl.
GET /invoices — список с фильтрами
| Параметр | Описание |
|---|---|
orderId | Точное совпадение с вашим номером заказа. Ответ — список из 0 или 1 элемента. |
status | Один из статусов: created, pending, paid, failed, expired, refunded, partially_refunded. |
from, to | Диапазон по времени создания, ISO 8601 (UTC). to — исключительно. |
limit | Размер страницы, по умолчанию 20, максимум 100. |
cursor | Значение nextCursor из предыдущего ответа. |
Сортировка — от новых к старым. Листайте, пока hasMore не станет false. Курсор устойчив к появлению новых счетов во время обхода.
Поиск по номеру заказа
Статусы
Кратко: created → pending → paid | failed | expired, затем paid → refunded | partially_refunded. Финальные статусы не откатываются. Полная таблица и диаграмма — в разделе Статусы счёта.
Комиссия и зачисление
Ставка берётся из вашего тарифа по способу оплаты (по умолчанию — общие тарифы; персональная ставка действует на все проекты). Кто её платит — задаёт customerFeePct: процент от суммы, который покупатель платит сверху, от 0 до ставки; остальное вычитается из вашего зачисления. Комиссия считается при создании счёта и пересчитывается по ставке выбранного метода, когда покупатель выбирает способ (значение на покупателе обрезается до ставки этого метода). Покупательская часть округляется до копеек, ваша — остаток, так что обе всегда дают ровно feeAmount. Пример для счёта на 1 000 ₽ при ставке СБП 9 % (комиссия 90 ₽):
| customerFeePct | Покупатель платит | Вам зачисляется | feePayer |
|---|---|---|---|
9 (вся ставка, по умолчанию) | 1 090 ₽ | 1 000 ₽ | customer |
4 | 1 040 ₽ | 950 ₽ | customer |
0 | 1 000 ₽ | 910 ₽ | merchant |
Ошибки
400 validation— некорректный JSON или тип поля;paramуказывает поле.422 amount_out_of_range— сумма вне лимитов метода;422 customer_fee_pct_too_high—customerFeePctбольше вашей ставки;422 method_unavailable— метод отключён для проекта или временно недоступен.409 order_id_conflict—orderIdзанят счётом с другими параметрами.403 project_not_active— боевые счета доступны только после модерации; тестовые — всегда.404 invoice_not_found— счёт с такимidне найден в этом проекте (или создан ключом другого режима).503 provider_unavailable— способ оплаты временно недоступен на стороне банков; повторите позже или создайте счёт безmethod.
Полный справочник — в разделе Ошибки.