Быстрый старт
Эта страница проводит через весь путь: от ключей до проверки оплаты. Примеры — на cURL, Python, Node.js и PHP: выберите язык в любом блоке кода, и он запомнится на всех страницах. Все поля и ошибки — в справочнике API.
Тестового режима нет: каждый оплаченный платёж — настоящий. Как проверить интеграцию без денег — на странице Проверка интеграции.
Шаг 1. Получите ключи и включите уведомления
- Войдите в личный кабинет.
- Откройте Ещё → Разработчикам → API-ключ (открыть сразу). На телефоне вместо «Ещё» — «Меню».
- Скопируйте ID магазина из блока «Авторизация запросов». Это число, например
33661. Там же — адрес API:https://api.avantpay.io/v3. - Нажмите Создать ключ. Ключ показывается целиком только один раз. Скопируйте его и сохраните в настройках своего сервера.
- Проверьте блок «Права ключа»: право «Платежи» должно быть включено. Если оно выключено, напишите в поддержку: [email protected]. Включить его в личном кабинете нельзя.
Если раздела «Разработчикам» нет, попросите владельца магазина добавить вас в разделе «Пользователи» с ролью «Разработчик».
Сохраните ID магазина и ключ в переменные окружения. Все примеры ниже берут их оттуда:
export AVANTPAY_SHOP_ID="33661"
export AVANTPAY_SECRET_KEY="<секретный ключ>"
Проверьте ключи. Этот запрос возвращает последний платёж магазина и ничего не меняет:
curl "https://api.avantpay.io/v3/payments?limit=1" \
-u "$AVANTPAY_SHOP_ID:$AVANTPAY_SECRET_KEY"
Ответ с кодом 200 — ключи верные. У нового магазина список пустой:
{
"type": "list",
"items": []
}
Ответ с кодом 401 и "code": "invalid_credentials" — неверный ID магазина или ключ. Проверьте, что скопировали их без пробелов.
Сразу включите уведомления — до первого платежа. Адрес уведомлений задаётся только в личном кабинете и запоминается в платеже при создании: платежи, созданные без адреса, уведомлений не получат.
- Откройте в личном кабинете Ещё → Разработчикам → HTTP-уведомления (открыть сразу).
- Нажмите Изменить настройки. Укажите адрес своего сервера, например
https://example.com/avantpay/webhook. Адрес должен начинаться сhttps://. - Отметьте события «Платёж оплачен» (
payment.succeeded) и «Платёж отменён» (payment.canceled). Сохраните.
Обработчик уведомлений можно написать позже, на шаге 4.
Шаг 2. Создайте платёж
Передайте его в metadata.email. Покупатель из Telegram — <id или username>@telegram.org, например [email protected].
Отправьте запрос POST /v3/payments:
- cURL
- Python
- Node.js
- PHP
curl https://api.avantpay.io/v3/payments \
-X POST \
-u "$AVANTPAY_SHOP_ID:$AVANTPAY_SECRET_KEY" \
-H "Idempotence-Key: 7f1c9a52-3d4b-4e8f-a1b2-c3d4e5f6a7b8" \
-H "Content-Type: application/json" \
-d '{
"amount": {
"value": "100.00",
"currency": "RUB"
},
"capture": true,
"confirmation": {
"type": "redirect",
"return_url": "https://example.com/orders/1"
},
"description": "Заказ №1",
"metadata": {
"email": "[email protected]",
"order_id": "1"
}
}'
import os
import requests
SHOP_ID = os.environ["AVANTPAY_SHOP_ID"]
SECRET_KEY = os.environ["AVANTPAY_SECRET_KEY"]
def create_payment(order_id: str, email: str, amount: str, return_url: str, idempotence_key: str) -> dict:
response = requests.post(
"https://api.avantpay.io/v3/payments",
auth=(SHOP_ID, SECRET_KEY),
headers={"Idempotence-Key": idempotence_key},
json={
"amount": {"value": amount, "currency": "RUB"},
"capture": True,
"confirmation": {"type": "redirect", "return_url": return_url},
"description": f"Заказ №{order_id}",
# email покупателя обязателен; покупатель из Telegram — f"{telegram_id}@telegram.org"
"metadata": {"email": email, "order_id": order_id},
},
timeout=30,
)
if response.status_code != 200:
raise RuntimeError(f"AvantPay: HTTP {response.status_code}: {response.text}")
payment = response.json()
# Повтор с тем же ключом может вернуть платёж, который не создался до конца (canceled, без ссылки):
# тогда создайте новый платёж с новым ключом идемпотентности
if payment["status"] != "pending" or "confirmation_url" not in payment.get("confirmation", {}):
raise RuntimeError(f"AvantPay: платёж {payment['id']} в статусе {payment['status']}, ссылки на оплату нет")
return payment # покупателя — на ["confirmation"]["confirmation_url"]
const AUTH =
"Basic " +
Buffer.from(`${process.env.AVANTPAY_SHOP_ID}:${process.env.AVANTPAY_SECRET_KEY}`).toString("base64");
export async function createPayment({ orderId, email, amount, returnUrl, idempotenceKey }) {
const response = await fetch("https://api.avantpay.io/v3/payments", {
method: "POST",
headers: {
Authorization: AUTH,
"Idempotence-Key": idempotenceKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount: { value: amount, currency: "RUB" },
capture: true,
confirmation: { type: "redirect", return_url: returnUrl },
description: `Заказ №${orderId}`,
// email покупателя обязателен; покупатель из Telegram — `${telegramId}@telegram.org`
metadata: { email, order_id: orderId },
}),
signal: AbortSignal.timeout(30000),
});
const text = await response.text();
if (response.status !== 200) {
throw new Error(`AvantPay: HTTP ${response.status}: ${text}`);
}
const payment = JSON.parse(text);
// Повтор с тем же ключом может вернуть платёж, который не создался до конца (canceled, без ссылки):
// тогда создайте новый платёж с новым ключом идемпотентности
if (payment.status !== "pending" || !payment.confirmation?.confirmation_url) {
throw new Error(`AvantPay: платёж ${payment.id} в статусе ${payment.status}, ссылки на оплату нет`);
}
return payment; // покупателя — на .confirmation.confirmation_url
}
<?php
function createPayment(string $orderId, string $email, string $amount, string $returnUrl, string $idempotenceKey): array
{
$ch = curl_init('https://api.avantpay.io/v3/payments');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_USERPWD => getenv('AVANTPAY_SHOP_ID') . ':' . getenv('AVANTPAY_SECRET_KEY'),
CURLOPT_HTTPHEADER => [
'Idempotence-Key: ' . $idempotenceKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'amount' => ['value' => $amount, 'currency' => 'RUB'],
'capture' => true,
'confirmation' => ['type' => 'redirect', 'return_url' => $returnUrl],
'description' => 'Заказ №' . $orderId,
// email покупателя обязателен; покупатель из Telegram — $telegramId . '@telegram.org'
'metadata' => ['email' => $email, 'order_id' => $orderId],
], JSON_UNESCAPED_UNICODE),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($response === false || $httpCode !== 200) {
throw new RuntimeException('AvantPay: HTTP ' . $httpCode . ': ' . $response);
}
$payment = json_decode($response, true);
// Повтор с тем же ключом может вернуть платёж, который не создался до конца (canceled, без ссылки):
// тогда создайте новый платёж с новым ключом идемпотентности
if ($payment['status'] !== 'pending' || empty($payment['confirmation']['confirmation_url'])) {
throw new RuntimeException('AvantPay: платёж ' . $payment['id'] . ' в статусе ' . $payment['status'] . ', ссылки на оплату нет');
}
return $payment; // покупателя — на ['confirmation']['confirmation_url']
}
Что в запросе:
| Что | Что передать |
|---|---|
Idempotence-Key | Ключ идемпотентности: любая уникальная строка до 64 символов, лучше UUID. Создайте его до запроса и сохраните в заказе. Если ответ не пришёл, повторите запрос с тем же ключом — второй платёж не появится. Подробнее |
amount.value | Сумма строкой с двумя знаками после точки. |
amount.currency | RUB. |
metadata.email | Обязательно. Email покупателя, до 254 символов. Покупатель из Telegram — <id или username>@telegram.org. |
capture | Указывается true. |
confirmation.type | redirect — покупатель перейдёт на страницу оплаты AvantPay. |
confirmation.return_url | Куда вернуть покупателя после оплаты или отказа от неё. Укажите адрес страницы заказа: AvantPay не добавляет к нему параметры. |
description | Необязательно. Описание до 128 символов. Его видит покупатель на странице оплаты. |
metadata.order_id | Необязательно. Ваш номер заказа. Вернётся в объекте платежа и в уведомлениях. |
Способ оплаты здесь не передан: покупатель выберет СБП или карту на странице оплаты. Все поля запроса — в справочнике: Создать платёж.
Ответ — объект платежа со статусом pending:
{
"id": "2f9b6c1e-4d7a-4c3b-9e8f-1a2b3c4d5e6f",
"status": "pending",
"paid": false,
"amount": {
"value": "100.00",
"currency": "RUB"
},
"description": "Заказ №1",
"recipient": {
"account_id": "33661"
},
"created_at": "2026-10-18T10:15:30.123Z",
"expires_at": "2026-10-18T10:35:30.123Z",
"confirmation": {
"type": "redirect",
"confirmation_url": "https://avantpay.io/link/Aq91c7d",
"return_url": "https://example.com/orders/1"
},
"test": false,
"refundable": false,
"metadata": {
"email": "[email protected]",
"order_id": "1"
}
}
Сохраните id платежа в своём заказе. По нему вы проверите платёж, когда придёт уведомление.
Шаг 3. Отправьте покупателя на страницу оплаты
Перенаправьте покупателя на адрес из confirmation.confirmation_url. Например, ответьте браузеру кодом HTTP 302 с этим адресом в заголовке Location или покажите кнопку «Оплатить» с этой ссылкой.
Покупатель должен заплатить до expires_at — это 20 минут после создания платежа. Потом платёж отменится.
После оплаты или отказа от неё AvantPay откроет у покупателя return_url — ровно тот адрес, что вы передали, без параметров. Поэтому указывайте в return_url адрес страницы заказа, например https://example.com/orders/1. На этой странице возьмите id платежа из заказа и запросите платёж (шаг 4). Возврат на return_url не означает, что платёж оплачен.
Шаг 4. Узнайте результат
Используйте оба способа: уведомления и запрос платежа.
Уведомления
Когда платёж оплатят или отменят, AvantPay отправит на адрес из шага 1 POST-запрос с JSON. Здесь покупатель оплатил картой:
{
"type": "notification",
"event": "payment.succeeded",
"object": {
"id": "2f9b6c1e-4d7a-4c3b-9e8f-1a2b3c4d5e6f",
"status": "succeeded",
"paid": true,
"amount": {
"value": "100.00",
"currency": "RUB"
},
"income_amount": {
"value": "97.50",
"currency": "RUB"
},
"description": "Заказ №1",
"recipient": {
"account_id": "33661",
"gateway_id": "6b1f3c0a-58e2-4f7d-9a41-0c2d7e5b8f93"
},
"payment_method": {
"type": "bank_card",
"id": "2f9b6c1e-4d7a-4c3b-9e8f-1a2b3c4d5e6f",
"saved": false,
"status": "inactive",
"title": "Банковская карта"
},
"captured_at": "2026-10-18T10:17:02.418Z",
"created_at": "2026-10-18T10:15:30.123Z",
"expires_at": "2026-10-18T10:35:30.123Z",
"confirmation": {
"type": "redirect",
"confirmation_url": "https://avantpay.io/link/Aq91c7d",
"return_url": "https://example.com/orders/1"
},
"test": false,
"refundable": false,
"metadata": {
"email": "[email protected]",
"order_id": "1"
}
}
}
Что сделать, когда пришло уведомление:
- Возьмите
object.id. - Запросите этот платёж через API (запрос ниже). Решение принимайте по ответу API, а не по телу уведомления. Ответ 404 — платежа нет у магазина: ответьте 200 и ничего не делайте.
- Если
statusравенsucceededиamountравен сумме заказа — отметьте заказ оплаченным атомарно (например,UPDATE … WHERE paid_payment_id IS NULL) и выполните его. Если заказ уже отмечен — ничего не делайте. Возврат покупателя наreturn_urlприходит одновременно с уведомлением, поэтому без атомарности заказ выполнится дважды. - Ответьте на уведомление кодом HTTP 200 не позже чем через 10 секунд. Если не ответить, AvantPay будет повторять уведомление.
Подробнее и готовые обработчики на Python, Node.js и PHP — на странице Уведомления.
Запрос платежа
- cURL
- Python
- Node.js
- PHP
curl https://api.avantpay.io/v3/payments/2f9b6c1e-4d7a-4c3b-9e8f-1a2b3c4d5e6f \
-u "$AVANTPAY_SHOP_ID:$AVANTPAY_SECRET_KEY"
import os
from typing import Optional
import requests
SHOP_ID = os.environ["AVANTPAY_SHOP_ID"]
SECRET_KEY = os.environ["AVANTPAY_SECRET_KEY"]
def get_payment(payment_id: str) -> Optional[dict]:
"""Платёж из API; None — у магазина нет такого платежа (404)"""
response = requests.get(
f"https://api.avantpay.io/v3/payments/{payment_id}",
auth=(SHOP_ID, SECRET_KEY),
timeout=30,
)
if response.status_code == 404:
return None
if response.status_code != 200:
raise RuntimeError(f"AvantPay: HTTP {response.status_code}: {response.text}")
return response.json()
const AUTH =
"Basic " +
Buffer.from(`${process.env.AVANTPAY_SHOP_ID}:${process.env.AVANTPAY_SECRET_KEY}`).toString("base64");
// Платёж из API; null — у магазина нет такого платежа (404)
export async function getPayment(paymentId) {
const response = await fetch(`https://api.avantpay.io/v3/payments/${encodeURIComponent(paymentId)}`, {
headers: { Authorization: AUTH },
signal: AbortSignal.timeout(30000),
});
if (response.status === 404) return null;
const text = await response.text();
if (response.status !== 200) {
throw new Error(`AvantPay: HTTP ${response.status}: ${text}`);
}
return JSON.parse(text);
}
<?php
// Платёж из API; null — у магазина нет такого платежа (404)
function getPayment(string $paymentId): ?array
{
$ch = curl_init('https://api.avantpay.io/v3/payments/' . rawurlencode($paymentId));
curl_setopt_array($ch, [
CURLOPT_USERPWD => getenv('AVANTPAY_SHOP_ID') . ':' . getenv('AVANTPAY_SECRET_KEY'),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 404) {
return null;
}
if ($response === false || $httpCode !== 200) {
throw new RuntimeException('AvantPay: HTTP ' . $httpCode . ': ' . $response);
}
return json_decode($response, true);
}
Ответ — объект платежа в текущем состоянии, такой же, как в object уведомления. Запрашивайте платёж:
- когда пришло уведомление;
- когда покупатель вернулся на
return_url; - когда запрос на создание платежа закончился ошибкой 500 или без ответа;
- раз в несколько минут для сверки: уведомление может не дойти (как сверяться).
Что делать по статусу
status | Что значит | Что делать |
|---|---|---|
pending | Покупатель ещё не заплатил. | Ждать. Заказ не выполнять. |
succeeded | Оплачен. | Сверить amount с суммой заказа и выполнить заказ один раз. |
canceled | Не оплачен: истёк срок, банк отказал или сработала проверка. | Заказ не выполнять. Чтобы покупатель заплатил снова, создать новый платёж с новым ключом идемпотентности. |
Все подробности — на странице Статусы платежа.
Готово
Интеграция работает, если:
- платёж создаётся с email покупателя, а покупатель попадает на страницу оплаты;
- после оплаты ваш сервер получает
payment.succeeded, проверяет платёж запросом и выполняет заказ один раз; - после отмены ваш сервер получает
payment.canceledи не выполняет заказ; - покупатель, вернувшийся на
return_url, видит правильный результат.
Перед запуском пройдите чеклист.