Все

Документация

Gotapay API

Общая логика

  • Base URL: https://gotapay.io/api/v1
  • Платежи создаются автоматически через API либо вручную в кабинете мерчанта и администратором. Все способы создают одинаковый платёж Gotapay.
  • Мерчант создает проект в личном кабинете.
  • После одобрения проекта мерчант указывает Webhook URL.
  • Мерчант выпускает API key и secret в настройках.
  • Платеж создается через API с обязательным project_id.
  • После финального статуса Gotapay отправляет callback на webhook проекта.

Аутентификация

  • API key передается в заголовке Authorization как Bearer token.
  • Тело запроса подписывается API secret через HMAC-SHA256.
  • Подписывается строка timestamp + "." + raw_body.
  • У запросов без тела (GET) вместо raw_body подписывается путь вместе с query-строкой, например /api/v1/payments?limit=50.
  • Timestamp передается в X-Gotapay-Timestamp.
  • Подпись передается в X-Gotapay-Signature.
  • Timestamp указывается в Unix time и должен отличаться от времени сервера не более чем на 5 минут.
  • Повторная отправка того же подписанного запроса отклоняется с HTTP 409.
Authorization: Bearer gtp_test_...
X-Gotapay-Timestamp: 1710000000
X-Gotapay-Signature: hmac_sha256(timestamp.raw_body)
Content-Type: application/json

Ключи и окружения

  • Ключи выпускаются в кабинете, в разделе Настройки. Пара состоит из API key и API secret: key передается в Authorization, secret нигде не передается и используется только для подписи.
  • Secret показывается один раз при выпуске. Восстановить его нельзя - если он потерян, выпустите новый ключ и отзовите старый.
  • У ключа одно окружение: test или live. Оно и определяет, с какими данными работает запрос, - отдельного параметра для этого нет.
  • Боевой ключ не видит sandbox-платежи и подписки, sandbox-ключ не видит боевые. Это относится и к чтению статусов, и к возвратам.
  • Ключей может быть несколько одновременно: так безопаснее менять их без простоя - выпустите новый, переключите интеграцию, отзовите старый.
  • Отозванный ключ перестает работать сразу. Платежи, созданные им, остаются как есть.
  • Ключ действует, пока активен его владелец: заблокированный аккаунт делает все свои ключи нерабочими.

Лимиты запросов

  • Ограничение: 60 запросов в минуту на ключ. Значение задается на стороне Gotapay и может быть увеличено по запросу.
  • Лимит считается по ключу, а не по IP: шумная интеграция одного мерчанта не расходует лимит другого, даже если они выходят с одного адреса.
  • При превышении возвращается 429. Заголовок Retry-After указывает, через сколько секунд повторять.
  • Повторяйте с нарастающей задержкой, а не сразу: непрерывные повторы после 429 только удерживают лимит израсходованным.
  • Опрос статусов лучше вести списком с курсором, а не запросом по каждому платежу отдельно: один запрос вместо сотни укладывается в лимит с запасом.

Создание платежа

  • Endpoint создает платежную сессию и возвращает checkout_url.
  • callback_url в запросе запрещен: webhook берется из проекта.
  • project_id обязателен и должен принадлежать владельцу API key.
  • Проект должен быть одобрен и иметь настроенный webhook. Исключение - тестовый режим: там одобрение не требуется.
  • Idempotency-Key можно использовать для защиты от дублей.
  • merchant_order_id не повторяется в пределах проекта и режима (боевой или тестовый), пока по нему есть неоплаченный или оплаченный платеж. Повторный запрос с тем же номером вернет HTTP 409 и payment_id существующего платежа. Использовать номер снова можно после того, как прежний платеж истек, отклонен или отменен.
  • Необязательные поля: currency (по умолчанию RUB), merchant_order_id, success_url, fail_url, metadata и expires_in_minutes.
  • Сейчас поддерживается только валюта RUB. URL должны использовать HTTPS и не вести на частные или зарезервированные адреса.
  • Idempotency-Key передается в заголовке и может содержать не более 128 символов.
  • Допустимая сумма: от 100 до 100 000 RUB. Стандартный срок действия — 30 минут.
POST /api/v1/payments

{
  "project_id": 1,
  "amount": 1000.00,
  "currency": "RUB",
  "merchant_order_id": "order-1001",
  "success_url": "https://example.com/success",
  "fail_url": "https://example.com/fail",
  "expires_in_minutes": 30,
  "metadata": {"customer_id": "42"}
}

HTTP 201
{
  "payment_id": "pay_...",
  "checkout_url": "https://gotapay2026.xyz/pay/pay_...",
  "status": "created",
  "amount": "1000.00",
  "currency": "RUB",
  "expires_at": "2026-08-12T12:30:00+00:00"
}

Готовые примеры создания платежа

  • В примерах API_KEY, API_SECRET, timestamp и signature необходимо заменить своими значениями.
  • Подпись — HMAC-SHA256 от timestamp + "." + неизменённого JSON-тела.

cURL

curl -X POST https://gotapay.io/api/v1/payments \
  -H "Authorization: Bearer API_KEY" \
  -H "X-Gotapay-Timestamp: TIMESTAMP" \
  -H "X-Gotapay-Signature: SIGNATURE" \
  -H "Content-Type: application/json" \
  -d '{"project_id":1,"amount":1000,"currency":"RUB"}'

PHP

$body = json_encode(["project_id" => 1, "amount" => 1000, "currency" => "RUB"]);
$timestamp = time();
$signature = hash_hmac("sha256", $timestamp.".".$body, "API_SECRET");
// POST https://gotapay.io/api/v1/payments with Bearer API_KEY and signature headers

Python

body = json.dumps({"project_id": 1, "amount": 1000, "currency": "RUB"}, separators=(",", ":"))
timestamp = str(int(time.time()))
signature = hmac.new(b"API_SECRET", f"{timestamp}.{body}".encode(), hashlib.sha256).hexdigest()
requests.post("https://gotapay.io/api/v1/payments", data=body, headers=headers)

JavaScript

const body = JSON.stringify({ project_id: 1, amount: 1000, currency: "RUB" });
// Создайте HMAC-SHA256 на сервере: секрет нельзя передавать в браузер.
await fetch("https://gotapay.io/api/v1/payments", { method: "POST", headers, body });

Способы оплаты и комиссии

  • СБП — отдельный способ оплаты, комиссия 2%.
  • Банковская карта — отдельный способ оплаты, комиссия 3%.
  • Криптовалюта — отдельный способ оплаты, комиссия 1%.
  • P2P отделён от банковской карты, но пока недоступен и не возвращается клиенту до подключения интеграции.
  • Комиссия делится между мерчантом и покупателем в любой пропорции. Деление задается в настройках терминала отдельно для каждого способа оплаты.
  • Доля покупателя добавляется к сумме платежа, доля мерчанта удерживается из зачисления. Сумма долей всегда равна ставке способа.
  • Пример при ставке 2% и цене 1000: доли 0/2 - покупатель платит 1000, мерчанту 980; доли 2/0 - покупатель платит 1020, мерчанту 1000; доли 1/1 - покупатель платит 1010, мерчанту 990. Gotapay во всех случаях получает 20.
  • Деление фиксируется в платеже в момент выбора способа оплаты и дальше не меняется, даже если настройки терминала изменят.
  • Ставка зависит от способа оплаты, поэтому в режиме «платит покупатель» итоговая сумма становится известна после выбора способа на странице оплаты.
  • amount в ответах и колбэках всегда остаётся суммой, которую задал мерчант. Сколько списано с покупателя, показывает charged_amount (chargedAmount в колбэке).
  • Если для нового метода тариф не указан, применяется комиссия 1%.

Статусы платежа

  • created - платеж создан, но еще не начат: покупатель не открывал страницу оплаты.
  • pending - платеж ожидает обработки или подтверждения.
  • processing - платеж передан провайдеру и находится в процессе обработки.
  • paid - платеж успешно оплачен.
  • failed - платеж отклонен или завершился ошибкой.
  • expired - срок оплаты истек. В expired уходят created, pending и processing.
  • canceled - платеж отменен мерчантом до оплаты.
  • refunded - выполнен полный возврат средств.
  • refund_pending - возврат создан и ожидает обработки.
  • refund_processing - возврат находится в процессе обработки.
  • refund_failed - возврат завершился ошибкой; доступная сумма возврата при этом не уменьшается.

Отмена платежа

  • POST /api/v1/payments/{payment_id}/cancel отменяет платеж, который еще не оплачен: created, pending или processing.
  • Оплаченный платеж отменить нельзя — для него доступен только возврат. Попытка отдает 422.
  • reason необязателен и может содержать до 512 символов.
POST /api/v1/payments/pay_.../cancel

{
  "reason": "Клиент передумал"
}

Чтение статуса платежа

  • Callback доставляется с повторами, но гарантией считать его нельзя: сеть, простой вашего сервера или сбой на нашей стороне могут его потерять.
  • Поэтому опрос статуса обязателен как запасной путь. Источником истины считайте ответ этих endpoint, а не факт получения callback.
  • GET /api/v1/payments/{payment_id} возвращает один платеж. Чужой платеж и платеж другого окружения отдают 404.
  • GET /api/v1/payments возвращает ленту платежей по возрастанию updated_at. Параметры: updated_since, cursor, status, limit (по умолчанию 50, максимум 200).
  • status принимает список через запятую, например status=paid,failed. Допустимы все статусы платежа.
  • Для догона пропущенного используйте cursor, а не updated_since: у платежей с одинаковым updated_at сдвиг по времени теряет часть записей.
  • Сохраняйте next_cursor после каждой выборки и передавайте его в следующий запрос. Он возвращается и когда has_more равен false.
  • Рекомендуемый режим: опрос раз в минуту с сохраненным курсором плюс точечный запрос по платежу, если callback не пришел в течение ожидаемого времени.
GET /api/v1/payments?status=paid,failed&limit=50

HTTP 200
{
  "data": [
    {
      "payment_id": "pay_...",
      "checkout_url": "https://gotapay2026.xyz/pay/pay_...",
      "status": "paid",
      "amount": "1000.00",
      "currency": "RUB",
      "expires_at": "2026-08-14T12:30:00+03:00",
      "merchant_order_id": "order-1001",
      "project_id": 1,
      "is_test": false,
      "selected_method": "sbp",
      "paid_at": "2026-08-14T12:15:00+03:00",
      "failed_at": null,
      "failure_reason": null,
      "created_at": "2026-08-14T12:00:00+03:00",
      "updated_at": "2026-08-14T12:15:00+03:00"
    }
  ],
  "has_more": false,
  "next_cursor": "MjAyNi0wOC0xNCAxMjoxNTowMHwx"
}

Требования к webhook URL

  • Адрес указывается в настройках терминала и должен работать по https. Обычный http отклоняется при сохранении.
  • Имя хоста должно разрешаться в публичный адрес. Локальные и внутренние адреса отклоняются: иначе через настройку терминала можно было бы заставить Gotapay стучаться во внутреннюю сеть.
  • Проверка выполняется и при сохранении адреса, и перед каждой отправкой: адрес мог начать указывать на внутреннюю сеть уже после сохранения.
  • Endpoint должен отвечать кодом 2xx. Любой другой код считается неудачей, и событие уходит в повтор.
  • Отвечайте быстро и не выполняйте тяжелую работу до ответа: медленный ответ считается неудачей по таймауту.
  • Для локальной разработки используйте туннель с публичным https-адресом - принять callback на localhost Gotapay не сможет.

Webhook клиента

  • Gotapay отправляет callback на webhook проекта после перехода платежа в paid или failed. Для expired callback сейчас не отправляется.
  • Callback подписывается так же, как API-запросы: HMAC-SHA256.
  • Подписывает секрет того ключа, которым создан платёж. У платежа, созданного не через API - из кабинета или администратором, - такого ключа нет, и подписью служит текущий активный ключ того же окружения: боевой для боевого платежа, тестовый для sandbox.
  • Мерчант должен отвечать HTTP 2xx, чтобы callback считался доставленным.
  • Callback доставляется best-effort: после исчерпания повторов он больше не отправляется. Пропущенное догоняйте через GET /api/v1/payments.
  • В callback передаются eventId, transactionType, kind, transactionId, providerTransactionId, transactionStatus, errorCode, errorDescription, amount, currency, orderId, projectId, paymentTime и metadata.
  • Для платежного callback kind равен Payment: статус paid передается как Paid, failed — как Declined.
POST https://merchant.example/webhooks/gotapay

{
  "eventId": "evt_pay_..._paid",
  "transactionType": "CardCrypto",
  "kind": "Payment",
  "transactionId": "pay_...",
  "providerTransactionId": null,
  "transactionStatus": "Paid",
  "errorCode": null,
  "errorDescription": null,
  "amount": "1000.00",
  "currency": "RUB",
  "orderId": "order-1001",
  "projectId": 1,
  "paymentTime": "2026-08-12T12:15:00Z",
  "metadata": {"customer_id": "42"}
}

Подписки

  • POST /api/v1/subscriptions создает подписку: project_id, amount, interval и необязательные description, customer_email, starts_at, metadata.
  • interval принимает day, week, month, quarter, year. Любое другое значение отдает 422.
  • Созданная подписка получает статус pending: списаний по ней еще не было. После первого успешного списания она переходит в active.
  • Статусы подписки: pending - ожидает первого списания, active - списания идут, canceled - остановлена, failed - списание не прошло и подписка снята с расписания.
  • starts_at задает дату первого списания. Без него подписка считается начатой сразу.
  • GET /api/v1/subscriptions отдает список с курсорной постраничностью: limit, cursor, updated_since и фильтр status - те же правила, что у списка платежей.
  • GET /api/v1/subscriptions/{subscription_id} отдает одну подписку, POST /api/v1/subscriptions/{subscription_id}/cancel останавливает ее.
  • Отмена не трогает уже проведенные списания: это состоявшиеся платежи, и вернуть их можно только возвратом.
  • Повторная отмена отдает 422: подписка уже неактивна.
  • Каждое списание - обычный платеж со ссылкой на подписку. Отдельного эндпоинта истории нет: списания приходят в /api/v1/payments, у них заполнен subscription_id.
  • Ключ определяет окружение: боевой ключ не видит sandbox-подписки, и наоборот.

Возврат платежа

  • Endpoint создает возврат по payment_id (checkoutId). Возврат всегда полный: возвращается вся сумма платежа.
  • Частичные возвраты не поддерживаются.
  • API-ключ должен принадлежать владельцу платежа и соответствовать его окружению: test или live.
  • Возврат доступен только для оплаченного платежа.
  • Запрос возврата боевого платежа принимается не раньше чем через 24 часа после оплаты. В sandbox ожидание отключено.
  • Gotapay обрабатывает принятый запрос до 24 часов. Фактическое зачисление покупателю может занять до 10 рабочих дней и зависит от банка и способа оплаты.
  • Покупателю возвращается всё, что он заплатил, включая комиссию, если платил её он.
  • С мерчанта списывается только ранее зачисленная ему сумма; свою комиссию Gotapay возвращает в обоих режимах.
  • amount необязателен. Если он передан, он должен быть равен сумме платежа - любое другое значение отдает 422. Без amount возвращается вся сумма.
  • reason необязателен и может содержать до 512 символов.
  • Пока идет возврат (refund_pending, refund_processing), новый возврат по платежу не принимается.
  • По платежу принимается один возврат. Исключение - возврат, завершившийся ошибкой: из refund_failed попытку можно повторить.
  • После успешного возврата платеж переходит в refunded.
  • Текущий остаток виден в полях refunded_amount и refundable_amount ответа GET /api/v1/payments/{payment_id}.
  • После успешного возврата на webhook проекта отправляется callback с kind Refund и transactionStatus Refunded.
POST /api/v1/payments/pay_.../refunds

{
  "reason": "Возврат заказа"
}

HTTP 201
{
  "refund_id": 123,
  "payment_id": "pay_...",
  "status": "succeeded",
  "amount": "250.00",
  "currency": "RUB",
  "created_at": "2026-08-12T12:20:00+00:00"
}

Webhook возврата

  • Webhook возврата подписывается тем же API secret и использует заголовки X-Gotapay-Timestamp и X-Gotapay-Signature.
  • В metadata дополнительно передается refund_id.
  • Получатель должен вернуть HTTP 2xx. Уведомление о возврате отправляется в режиме best effort без цепочки повторных попыток.
{
  "eventId": "evt_pay_..._refund_123",
  "transactionType": "CardCrypto",
  "kind": "Refund",
  "transactionId": "pay_...",
  "transactionStatus": "Refunded",
  "amount": "250.00",
  "currency": "RUB",
  "orderId": "order-1001",
  "projectId": 1,
  "metadata": {"refund_id": 123}
}

Тестовый режим (sandbox)

  • Окружение определяется API-ключом, а не отдельным доменом: ключ gtp_test_... создает тестовые платежи, gtp_live_... - боевые. Endpoint, формат запроса и подпись одинаковые.
  • Тестовый режим не требует одобрения проекта - интеграцию можно закончить, пока проект еще на проверке. Webhook URL терминала задать все равно нужно: именно на него придет callback.
  • Тестовые платежи не попадают в боевой баланс, KPI, экспорт и антифрод-статистику. В кабинете они видны через переключатель «Тест / Прод» в шапке и помечены бейджем test.
  • Реальные деньги в тестовом режиме не двигаются - ни при платеже, ни при возврате, ни при выводе.

Тестовые триггеры

  • Исход тестового платежа задается заранее - ждать реального события не нужно.
  • По сумме: копейки .01 - paid, .02 - failed, .03 - expired, .04 - высокий risk-флаг.
  • По merchant_order_id: суффикс -sandbox-paid, -sandbox-failed, -sandbox-expired, -sandbox-high_risk. Суффикс имеет приоритет над суммой.
  • Исход срабатывает в момент, когда плательщик выбрал метод оплаты на checkout-странице.
  • Сумма без совпадающего триггера ведет себя как обычный платеж и остается в pending.
  • На боевых ключах триггеры не работают вообще.
POST /api/v1/payments
Authorization: Bearer gtp_test_...

{
  "project_id": 1,
  "amount": 1000.01,           // -> paid
  "currency": "RUB",
  "merchant_order_id": "order-1001-sandbox-failed"  // -> failed
}

Полный цикл в sandbox

  • 1. Выпустите тестовый ключ в Настройках (environment: test) и задайте Webhook URL терминала.
  • 2. Создайте платеж на сумму с копейками .01 - тем же запросом, что и в проде, но с тестовым ключом.
  • 3. Откройте checkout_url из ответа и выберите любой метод оплаты.
  • 4. Платеж сразу перейдет в paid, и на Webhook URL терминала придет подписанный callback.
  • 5. Проверьте подпись тем же кодом, что пойдет в прод: HMAC-SHA256 от timestamp + "." + raw_body, ключ - ваш API secret.
  • Не дожидаясь платежа, отдельный callback можно отправить кнопкой «Тестовый вебхук» в Настройках (paid / failed / refund).
  • Тестовые callback-и ретраятся по укороченной цепочке, чтобы не долбить webhook, который вы прямо сейчас отлаживаете.

Тестовый вывод средств

  • Заявка на вывод, созданная в тестовом режиме, не уходит администратору.
  • Она автоматически переходит из pending в paid через симулированную задержку.
  • Реальный USDT при этом не отправляется - это только проверка цикла заявки.
  • Доступная к выводу сумма в тестовом режиме считается по тестовым платежам, а не по боевому балансу.

Ошибки и ответы

  • 401 - не передан или неверен API key/signature.
  • 404 - платеж для возврата не найден или принадлежит другому окружению.
  • 409 - повторный подписанный запрос или конфликт idempotency key.
  • 422 - ошибка валидации payload, проекта, URL, валюты или суммы возврата.
  • 429 - превышен лимит запросов.
  • 500 - внутренняя ошибка сервера.

Словарь терминов

Термин Описание
Эквайринг Технология приема онлайн-платежей банковскими картами и другими платежными методами.
Мерчант Клиент платежной системы, который продает товары или услуги и принимает оплату онлайн.
Транзакция Запись о платеже: кто оплатил, какая сумма прошла, когда это произошло и каким был итоговый статус.
UUID транзакции Уникальный идентификатор конкретной транзакции в платежной системе.
Статус транзакции Текущее состояние платежа: создан, в обработке, успешно оплачен или отклонен.
Код ошибки Идентификатор причины неуспешной операции вместе с описанием проблемы.
Терминал Точка приема платежей мерчанта для конкретного проекта, сайта или вида деятельности.
Шлюз Канал подключения к банку или платежному сервису, через который обрабатываются транзакции.
H2H интеграция Host-to-Host интеграция через API, при которой мерчант управляет платежным процессом со своей стороны.
Комиссия Процент или фиксированная надбавка, взимаемая за обработку платежей.
Оборот Сумма успешных транзакций за выбранный период.
Доход Сумма, остающаяся после учета комиссий и других удержаний.
Баланс Накопленная сумма средств до вывода или автоматической выплаты.
Платежная форма Интерфейс, через который плательщик выбирает метод оплаты и завершает платеж.
Платежная ссылка Уникальная ссылка на оплату, которую мерчант может передать клиенту.
Платежный метод Способ оплаты: карта, СБП, T-Pay, SberPay или другой доступный метод.
T+N Схема выплаты, где T означает дату транзакции, а N - количество рабочих дней до перечисления средств.
Порог вывода Минимальная сумма на балансе, после достижения которой может выполняться выплата.
Webhook Автоматическое уведомление на сервер мерчанта при изменении статуса платежа.
Webhook URL HTTPS-адрес, на который отправляются уведомления о платежах.
Success page Страница, куда пользователь возвращается после успешной оплаты.
Fail page Страница, куда пользователь возвращается после неуспешной оплаты.
Платежное API Набор методов для создания платежей, проверки статусов и интеграции платежной формы.
Access token Ключ доступа, который используется для авторизации API-запросов.
Secret Key Секретный ключ, используемый для подписи и проверки запросов.
Chargeback Оспаривание платежа покупателем через банк с возможным возвратом средств.
Refund Возврат средств покупателю по инициативе мерчанта.
Rolling резерв Часть поступлений, временно удерживаемая для покрытия возможных рисков, возвратов или комиссий.