---
slug: "paykeeper"
name: "PayKeeper"
vendor: "PayKeeper"
industry: "finance"
docsUrl: "https://docs.paykeeper.ru/dokumentatsiya-json-api/"
version: 2
updatedAt: "2026-10-24"
---

# PayKeeper

Отрасль: Платежи и финансы. Актуально на 2026-10-24.

Протокол для автоматического управления приёмом платежей через платёжную платформу PayKeeper: выставление счетов и получение ссылок на оплату, информация о платежах, возвраты, списание авторизованных средств, работа с чеками 54-ФЗ. Подходит для интеграции с биллингом, бухгалтерскими системами, мобильными приложениями и самописными CMS. О каждом принятом платеже PayKeeper может сообщать POST-оповещением на сайт предприятия.

## Сценарии

### Выставить счёт и получить ссылку на оплату

Ссылка на оплату для клиента — в письмо, мессенджер или на страницу заказа.

1. Все запросы — к адресу твоего сервера PayKeeper с заголовком Authorization: Basic (логин и пароль от личного кабинета в base64). Чтение — GET, изменения — POST в формате application/x-www-form-urlencoded.
2. Получи токен безопасности: GET /info/settings/token/. Он нужен в каждом POST-запросе и меняется раз в сутки.
3. Создай счёт: POST /change/invoice/preview/ с pay_amount, orderid, clientid, client_email, service_name и token. Срок действия счёта задаёт expiry.
4. В ответе invoice_id и invoice_url — ссылка для оплаты. Добавь к ней ?pstype=sbp_default, чтобы сразу показать QR-код СБП.
5. Чтобы PayKeeper сам отправил письмо со счётом, вызови POST /change/invoice/send/ с id счёта.

```bash
PK=https://<твой-сервер>.server.paykeeper.ru
AUTH='<логин>:<пароль>'
TOKEN=$(curl -s -u "$AUTH" "$PK/info/settings/token/" | jq -r .token)

curl -X POST "$PK/change/invoice/preview/" -u "$AUTH" \
  -d pay_amount=1500.00 -d orderid=1042 \
  --data-urlencode 'clientid=Иван Петров' -d client_email=ivan@example.ru \
  --data-urlencode 'service_name=Заказ №1042' \
  -d token=$TOKEN
```

### Принять оповещение об оплате

Узнать об оплате с сервера и отметить заказ оплаченным.

1. Укажи в личном кабинете адрес оповещений и секретное слово. О каждом платеже PayKeeper пришлёт POST с id, sum, clientid, orderid и key.
2. Проверь подпись: key должен совпасть с md5 от id + sum (ровно два знака после точки) + clientid + orderid + секретное слово.
3. Защитись от повторов: оповещение может прийти несколько раз — не зачисляй платёж с тем же id дважды.
4. Ответь строкой OK и md5 от id + секретное слово. Без правильного ответа PayKeeper повторяет оповещение каждую минуту (по умолчанию до 50 раз).
5. Если нужно перепроверить платёж, запроси его: GET /info/payments/byid/ с id.

```python
import hashlib

SECRET = "<секретное слово>"

def handle(form: dict) -> str:
    sum_str = f"{float(form['sum']):.2f}"
    expected = hashlib.md5(f"{form['id']}{sum_str}{form['clientid']}{form['orderid']}{SECRET}".encode()).hexdigest()
    if expected != form["key"]:
        return "Error! Hash mismatch"
    mark_paid_once(order_id=form["orderid"], payment_id=form["id"])  # идемпотентно по id платежа
    return "OK " + hashlib.md5(f"{form['id']}{SECRET}".encode()).hexdigest()
```

### Вернуть деньги покупателю

Полный или частичный возврат по платежу, в том числе с чеком возврата по 54-ФЗ.

1. Получи токен: GET /info/settings/token/.
2. Отправь возврат: POST /change/payment/reverse/ с id платежа, amount (разделитель — точка) и partial — строго true или false, значения 1 и 0 не принимаются. Для чека возврата передай refund_cart — JSON-строку с товарами.
3. Ответ success означает только постановку в очередь. Через несколько минут проверь результат: GET /info/refunds/bypaymentid/.
4. Возвраты доступны пользователям, у которых включена эта функция.

```bash
curl -X POST "$PK/change/payment/reverse/" -u "$AUTH" \
  -d id=<id платежа> -d amount=500.00 -d partial=true -d token=$TOKEN
```

### Списать заблокированные деньги

Двухстадийная оплата: деньги заблокированы на карте, списываются после сборки заказа.

1. Чтобы списать всю сумму сразу, не дожидаясь автосписания: POST /change/payment/capture/ с id платежа и token.
2. Чтобы списать только часть (часть товара закончилась), используй POST /change/payment/reverse/ с нужной суммой — частичное списание выбирается автоматически по состоянию платежа.
3. Если банк ответил status = queued, запрос лишь принят — проверь итог через несколько минут: GET /info/payments/byid/.

```bash
curl -X POST "$PK/change/payment/capture/" -u "$AUTH" -d id=<id платежа> -d token=$TOKEN
```

### Сверить платежи за период

Ежедневная сверка с учётной системой: какие платежи прошли, отменены или возвращены.

1. Запроси реестр: GET /info/payments/bydate/ с start и end (YYYY-MM-DD), status[] (например, success, canceled, refunded), payment_system_id[], from и limit — все параметры обязательны.
2. Листай через from, пока не получишь меньше limit записей.
3. Для счетов есть отдельная история: GET /info/invoice/list/ с status[] и датами, а данные одного счёта — GET /info/invoice/byid/.

```bash
curl -G -u "$AUTH" "$PK/info/payments/bydate/" \
  -d start=2026-10-01 -d end=2026-10-24 \
  -d 'status[]=success' -d 'status[]=refunded' \
  -d 'payment_system_id[]=<id платёжной системы>' \
  -d from=0 -d limit=100
```

## Базовые URL

- Боевой: `https://<адрес вашего сервера PayKeeper>`

## Авторизация

Тип: Basic Auth

Каждый запрос отправляется с заголовком `Authorization: Basic` — логин и пароль от личного кабинета PayKeeper в base64. Запросы на чтение выполняются GET, изменения — POST с заголовком `Content-Type: application/x-www-form-urlencoded`. Каждый POST-запрос дополнительно должен содержать параметр `token` — токен безопасности, полученный методом `/info/settings/token/`.

## Методы

### GET /info/settings/token/ — Получить токен безопасности

Токен нужен для всех POST-запросов (защита от CSRF). Меняется раз в 24 часа.

Пример ответа:

```json
{
    "token" : "fd50e47596cff6c63c7ea0a633c0d2a8"
}
```

### POST /change/invoice/preview/ — Подготовка счёта

Создаёт счёт по параметрам оплаты и возвращает его номер, полный URL для оплаты и HTML-предпросмотр письма. Созданный счёт получает служебный статус `created` и не попадает в историю счетов.

| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
| `pay_amount` | body | string | да | Сумма заказа к оплате |
| `clientid` | body | string | нет | Идентификатор клиента |
| `orderid` | body | string | нет | Номер заказа |
| `service_name` | body | string | нет | Наименование услуги; можно передать JSON-объект с корзиной cart и доп. атрибутами |
| `client_email` | body | string | нет | E-mail клиента |
| `client_phone` | body | string | нет | Телефон клиента |
| `expiry` | body | string | нет | Срок действия счёта: YYYY-MM-DD или YYYY-MM-DD H:i:s (не включительно) |
| `token` | body | string | да | Токен безопасности |

Пример ответа:

```json
{
  "invoice_id" : "20120229133742255",
  "invoice_url" : "https://pay.example.com/bill/20120229133742255",
  "invoice"    : "&lt;HTML&gt;&lt;HEAD&gt;&lt;META http-equiv=Content-Type ..."
}
```

### POST /change/invoice/send/ — Отправить счёт клиенту

Отправляет клиенту письмо, созданное методом preview.

| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
| `id` | body | string | да | Идентификатор созданного счёта |
| `token` | body | string | да | Токен безопасности |

Пример ответа:

```json
{
  "result" : "success"
}
```

### POST /change/invoice/revoke/ — Отменить счёт

| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
| `id` | body | string | да | Идентификатор счёта |
| `token` | body | string | да | Токен безопасности |

### POST /change/invoice/accept-cash/ — Отметить счёт оплаченным наличными

| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
| `invoice_id` | body | string | да | Идентификатор счёта |
| `client_phone` | body | string | нет | Телефон плательщика |
| `token` | body | string | да | Токен безопасности |

### GET /info/invoice/byid/ — Данные счёта

Статусы счёта: `created`, `sent`, `paid`, `expired`.

| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
| `id` | query | string | да | Номер счёта |

Пример ответа:

```json
[
      {
      "id"                : "20110115085347329",
      "clientid"          : "Ivanov Ivan Ivanovich",
       "orderid"          : "1337",
       "paymentid"        : "7331",
       "service_name"     : "Document delivery",
       "client_email"     : "ivanov@ivan.ivanovich.com",
       "client_phone"     : "+79254973590",
       "created_datetime" : "2011-01-15 08:53:47",
       "paid_datetime"    : "2011-01-16 14:12:00",
       "expiry_datetime"  : "2011-01-19 00:00:00",
       "pay_amount"       : "1205.98",
       "status"           : "paid",
       "user_id"           : 9
       }
]
```

### GET /info/invoice/list/ — История счетов за период

Счета выводятся от новых к старым.

| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
| `status[]` | query | string | нет | Статусы: sent, paid, expired |
| `start_date` | query | string | нет | Счета, выставленные после даты YYYY-MM-DD |
| `end_date` | query | string | нет | Счета, выставленные до даты YYYY-MM-DD |
| `from` | query | integer | нет | Пропустить N результатов |
| `limit` | query | integer | нет | Не более N результатов |

### GET /info/payments/bydate/ — Реестр платежей за период

| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
| `start` | query | string | да | Начало периода YYYY-MM-DD |
| `end` | query | string | да | Конец периода YYYY-MM-DD |
| `payment_system_id[]` | query | integer | да | Идентификатор платёжной системы |
| `status[]` | query | string | да | Статусы: pending, obtained, canceled, success, failed, stuck, refunded, refunding, partially_refunded |
| `from` | query | integer | да | Пропустить первые N значений |
| `limit` | query | integer | да | Количество возвращаемых значений |

Пример запроса:

```
/info/payments/bydate/?limit=100&from=0&start=2016-04-14&end=2017-03-14&status[]=success&status[]=canceled&status[]=failed&payment_system_id[]=9&payment_system_id[]=1
```

### GET /info/payments/byid/ — Платёж по идентификатору

| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
| `id` | query | string | да | Идентификатор платежа в PayKeeper |
| `advanced` | query | string | нет | true — вернуть дополнительные опции платежа |

### GET /info/refunds/bypaymentid/ — Возвраты по платежу

Информация по возвратам для платежа.

### POST /change/payment/reverse/ — Возврат платежа

Полный возврат, отмена авторизации, частичный возврат или частичное списание — выбирается автоматически по состоянию платежа. Доступно пользователям с включённой функцией возврата.

| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
| `id` | body | string | да | Идентификатор платежа в PayKeeper |
| `amount` | body | string | да | Возвращаемая сумма, разделитель точка |
| `partial` | body | string | да | Частичный возврат: только true или false |
| `refund_cart` | body | string | нет | JSON-строка товаров к возврату (для чека 54-ФЗ) |
| `token` | body | string | да | Токен безопасности |

Пример ответа:

```json
{
    "result" : "success"
}
```

### POST /change/payment/capture/ — Списание по авторизации

Списывает средства по ранее авторизованному платежу, не дожидаясь автосписания. Для частичного списания используют `/change/payment/reverse/`.

| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
| `id` | body | string | да | Номер платежа к списанию |
| `token` | body | string | да | Токен безопасности |

## Нюансы

- Параметр `token` обязателен в каждом POST-запросе, хотя в описании методов его часто не упоминают; токен меняется раз в 24 часа.
- В `partial` передавайте именно `true`/`false` — значения 1/0 система не воспринимает.
- Возврат выполняется асинхронно: успешный ответ означает только постановку в очередь. Результат проверяют через `/info/refunds/bypaymentid/` или реестр платежей со статусом `refunding`, обычно через несколько минут.
- При ответе `status = queued` на capture (Промсвязьбанк) запрос лишь принят банком; итог проверяют через несколько минут.
- POST-оповещение о платеже содержит `id`, `sum`, `clientid`, `orderid`, `key` и доп. поля. `key` — md5 от конкатенации id, sum (2 знака после точки), clientid, orderid и секретного слова из личного кабинета.
- На оповещение нужно ответить строкой `OK <md5(id + секретное слово)>`. Без корректного ответа PayKeeper повторяет запрос каждую минуту, по умолчанию до 50 раз, после чего платёж получает статус «Совершён без оповещения».
- Оповещение может прийти несколько раз — обработчик должен защищаться от повторного зачисления по `id` платежа.
- К ссылке счёта можно добавить `?pstype=sbp_default`, чтобы показать QR-код СБП, и `&returnFormat=json`, чтобы получить содержимое QR-кода.

## Примеры кода

### Проверка POST-оповещения на PHP

```php
<?php
  $secret_seed = "verysecretseed";
  $id = $_POST['id'];
  $sum = $_POST['sum'];
  $clientid = $_POST['clientid'];
  $orderid = $_POST['orderid'];
  $key = $_POST['key'];

  if ($key != md5 ($id.number_format($sum, 2, ".", "")
                   .$clientid.$orderid.$secret_seed))
  {
      echo "Error! Hash mismatch";
      exit;
  }

  echo "OK ".md5($id.$secret_seed);
?>
```

## Источники

- [JSON API](https://docs.paykeeper.ru/dokumentatsiya-json-api/)
- [Безопасность и авторизация](https://docs.paykeeper.ru/dokumentatsiya-json-api/token-bezopasnosti/)
- [Счета](https://docs.paykeeper.ru/dokumentatsiya-json-api/scheta/)
- [Платежи](https://docs.paykeeper.ru/dokumentatsiya-json-api/platezhi/)
- [Приём POST-оповещений](https://docs.paykeeper.ru/metody-integratsii/priyom-post-opoveshhenij/)

---

Если этого недостаточно — официальная документация: https://docs.paykeeper.ru/dokumentatsiya-json-api/
JSON: https://mcp-everything.ru/api/integrations/paykeeper. MCP: https://mcp-everything.ru/mcp
