Adsrek Pay API Documentation
Полное руководство по созданию счетов, HMAC-подписям, проверке статусов, callback-уведомлениям and внутренним выплатам at AR-кошельки.
Quick start
Minimal working payment acceptance flow.
payment_url.https://adsrekpay.compaid and signature verification.General requirements
Request format and supported values.
All methods accept only POST. Recommended header: Content-Type: application/json. A regular POST array is also accepted.
Maximum request body size — 65,536 bytes. Exceeding this limit returns HTTP 413.
RUB, USD, EUR, USDT.
RUB, USD and EUR use 2 decimal places. USDT uses 8. The server normalizes the amount before signature verification.
An invoice is valid for 24 hours from creation. The response includes the Unix timestamp expires_at.
Use UTF-8. Fields order_id and description are sanitized and length-limited.
Авторизация and HMAC-SHA256
Every request is signed with the selected site SECRET KEY.
Every request always includes shop_id, api_key and a 64-character hexadecimal sign. The SECRET KEY is used only to calculate the signature and is never sent to the API.
create|SHOP_ID|API_KEY|ORDER_ID|AMOUNT|CURRENCYstatus|SHOP_ID|API_KEY|ORDER_IDpayout|SHOP_ID|API_KEY|ORDER_ID|AMOUNT|CURRENCY|TARGETfunction adsrekSign(string $canonical, string $secretKey): string
{
return hash_hmac('sha256', $canonical, $secretKey);
}
$amount = number_format(10, 2, '.', '');
$canonical = 'create|1001|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|ORDER-1001|' . $amount . '|RUB';
$sign = adsrekSign($canonical, 'YOUR_SECRET_KEY');
10.00, and for 1 USDT — 1.00000000. Currency is sent in uppercase.Invoice creation
POST https://adsrekpay.com/api/pay/create.php
| Field | Required | Description |
|---|---|---|
shop_id | Yes | Site ID from your account. |
api_key | Yes | Public API KEY of the site. |
order_id | Yes | Unique order ID within the site, up to 100 characters. |
amount | Yes | Amount must be at least 0.01. |
currency | Yes | RUB, USD, EUR or USDT. |
description | No | Order description, up to 255 characters. |
callback_url | No | Public HTTPS URL. Overrides the site URL for this invoice. |
success_url | No | HTTPS return URL after successful payment. |
fail_url | No | HTTPS return URL after cancellation or error. |
sign | Yes | HMAC-SHA256 of the canonical string. |
{
"shop_id": 1001,
"api_key": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"order_id": "ORDER-1001",
"amount": "10.00",
"currency": "RUB",
"description": "Order payment ORDER-1001",
"callback_url": "https://site.ru/payment/callback",
"success_url": "https://site.ru/payment/success",
"fail_url": "https://site.ru/payment/fail",
"sign": "HMAC_SHA256_HEX"
}
{
"ok": true,
"invoice_id": 1501,
"order_id": "ORDER-1001",
"status": "new",
"amount": "10.00",
"currency": "RUB",
"payment_url": "https://adsrekpay.com/merchant/invoice.php?id=TOKEN",
"expires_at": 1785704400
}
order_id, amount and currency returns the existing invoice. If the amount or currency differs, the API returns ORDER_ID_CONFLICT.Check invoice status
POST https://adsrekpay.com/api/pay/status.php
{
"shop_id": 1001,
"api_key": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"order_id": "ORDER-1001",
"sign": "HMAC_SHA256_HEX"
}{
"ok": true,
"invoice": {
"id": "1501",
"order_id": "ORDER-1001",
"amount": "10.00",
"currency": "RUB",
"status": "paid",
"created_at": "1785618000",
"paid_at": "1785618125"
}
}Verify together status, amount, currency and order_id. Do not mark an order as paid based only on the return URL.
Callback / webhook
A notification is sent after the invoice is successfully paid.
POST application/x-www-form-urlencoded.
Any HTTP status from 200 through 299 is treated as successful delivery.
Up to 5 attempts, at least 5 minutes apart, until a 2xx response is received.
Public HTTPS only, with SSL verification and no redirects. Connection timeout is 5 seconds; total timeout is 10 seconds.
invoice_id=1501
shop_id=1001order_id=ORDER-1001
amount=10.00
currency=RUB
status=paid
paid_at=1785618125
sign=HMAC_SHA256_HEXinvoice_id|shop_id|order_id|amount|currency|status
1501|1001|ORDER-1001|10.00|RUB|paid<?php
$secretKey = getenv('ADSREK_PAY_SECRET');
$data = $_POST;
$required = ['invoice_id','shop_id','order_id','amount','currency','status','sign'];
foreach ($required as $field) {
if (!isset($data[$field])) {
http_response_code(400);
exit('MISSING_FIELD');
}
}
$canonical = implode('|', [
(int)$data['invoice_id'],
(int)$data['shop_id'],
(string)$data['order_id'],
(string)$data['amount'],
(string)$data['currency'],
(string)$data['status'],
]);
$expected = hash_hmac('sha256', $canonical, $secretKey);
if (!hash_equals($expected, strtolower((string)$data['sign']))) {
http_response_code(401);
exit('BAD_SIGNATURE');
}
// Find the order by order_id and lock the row in a database transaction.
// A repeated callback for an already paid order must return 200 without crediting it again.
if ($data['status'] === 'paid') {
// Also compare amount and currency with your order.
// Mark the order as paid atomically.
}
http_response_code(200);
echo 'OK';
Payout to an AR wallet
POST https://adsrekpay.com/api/pay/payout.php
{
"shop_id": 1001,
"api_key": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"order_id": "PAYOUT-1001",
"amount": "10.00",
"currency": "RUB",
"target": "AR584193027",
"sign": "HMAC_SHA256_HEX"
}{
"ok": true,
"payout": {
"transfer_id": 9021,
"amount": "10.00",
"currency": "RUB",
"recipient": "AR584193027"
}
}order_id is required and provides idempotency. Repeating a successfully completed payout returns the saved result instead of debiting funds again.
Invoice statuses
Actual Merchant API v1 statuses.
newAwaiting paymentThe invoice has been created and is available to the customer.paidPaidFinal successful status.expiredExpired24 hours elapsed without payment.cancelCancelledFinal cancellation status.refundedRefundedFunds have been refunded.API errors
An error response has the form {"ok":false,"error":"CODE"}.
| HTTP | Code | Value |
|---|---|---|
| 400 | INVALID_JSON | The request body could not be parsed. |
| 401 | AUTH_REQUIRED | shop_id, api_key or a valid 64-character signature is missing. |
| 401 | SHOP_NOT_FOUND | The site was not found, is disabled, or the API KEY is invalid. |
| 401 | BAD_SIGNATURE | The HMAC signature does not match. |
| 401 | SHOP_SECRET_ERROR | The server could not decrypt the site SECRET KEY. |
| 404 | INVOICE_NOT_FOUND | No invoice was found for the specified order_id. |
| 405 | METHOD_NOT_ALLOWED | A method other than POST was used. |
| 413 | PAYLOAD_TOO_LARGE | The request body exceeds 65,536 bytes. |
| 422 | BAD_CURRENCY | The currency is not supported. |
| 422 | BAD_AMOUNT | The amount failed normalization. |
| 422 | BAD_INVOICE | order_id is empty or the amount is below the minimum. |
| 422 | BAD_CALLBACK_URL | The callback URL is not a public HTTPS address. |
| 422 | ORDER_ID_CONFLICT | A repeated order_id was sent with a different amount or currency. |
| 422 | RECIPIENT_NOT_FOUND | The internal payout recipient was not found. |
| 422 | INSUFFICIENT_FUNDS | The merchant balance is insufficient for the amount plus fee. |
| 422 | DUPLICATE_OR_IN_PROGRESS | A payout with this order_id is already processing or previously failed. |
| 422 | SELF_PAYOUT_NOT_ALLOWED | You cannot make an API payout to yourself. |
Ready examples
Code for server-side integration.
<?php
$shopId = 1001;
$apiKey = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
$secretKey = getenv('ADSREK_PAY_SECRET');
$orderId = 'ORDER-1001';
$amount = number_format(10, 2, '.', '');
$currency = 'RUB';
$canonical = implode('|', ['create', $shopId, $apiKey, $orderId, $amount, $currency]);
$payload = [
'shop_id' => $shopId,
'api_key' => $apiKey,
'order_id' => $orderId,
'amount' => $amount,
'currency' => $currency,
'description' => 'Order payment ' . $orderId,
'sign' => hash_hmac('sha256', $canonical, $secretKey),
];
$ch = curl_init('https://adsrekpay.com/api/pay/create.php');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) {
throw new RuntimeException(curl_error($ch));
}
curl_close($ch);
$data = json_decode($response, true, 512, JSON_THROW_ON_ERROR);
if ($httpCode !== 200 || empty($data['ok'])) {
throw new RuntimeException($data['error'] ?? 'Adsrek Pay API error');
}
header('Location: ' . $data['payment_url']);
exit;
import hashlib
import hmac
import os
import requests
shop_id = 1001api_key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
secret_key = os.environ["ADSREK_PAY_SECRET"]
order_id = "ORDER-1001"
amount = "10.00"
currency = "RUB"
canonical = f"create|{shop_id}|{api_key}|{order_id}|{amount}|{currency}"
sign = hmac.new(secret_key.encode(), canonical.encode(), hashlib.sha256).hexdigest()
payload = {
"shop_id": shop_id,
"api_key": api_key,
"order_id": order_id,
"amount": amount,
"currency": currency,
"description": f"Order payment {order_id}",
"sign": sign,
}
response = requests.post("https://adsrekpay.com/api/pay/create.php", json=payload, timeout=15)
response.raise_for_status()
data = response.json()
print(data["payment_url"])
// The invoice is created only on your server, where the SECRET KEY is stored.
const response = await fetch('/your-server/create-adsrek-invoice', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({order_id: 'ORDER-1001'})
});
const data = await response.json();
if (!data.payment_url) throw new Error('Could not create invoice');
window.location.assign(data.payment_url);
Security
Mandatory rules for production integration.
- SECRET KEY — server-side only. Do not put it in HTML, JavaScript, a mobile app or a public repository.
- Always use HTTPS. HTTP callbacks and local/private IP addresses are blocked.
- Verify signatures with hash_equals. Regular string comparison can be vulnerable to timing attacks.
- Verify the amount, currency and order_id. Match the signed callback against the order data in your database.
- Process repeated notifications idempotently. One invoice must never be credited twice.
- After key rotation, the old keys stop working immediately. Update configuration atomically.
- Keep a backup of config/paycore.local.php. Adsrek Pay needs this file to decrypt merchant SECRET KEY values.
Limits and current version
Фактические параметры Merchant API v1.
Merchant API v1. Endpoint URLs include PHP file names and must be used unchanged.
0.01 in the selected currency.
1.00% is deducted from the amount credited to the merchant.
0.50% is charged additionally to the merchant.
A separate sandbox is not available yet. For testing, use a separate site and the minimum amount.
Специальный тарифный rate limit в текущей версии не задан. Не отправляйте частые циклические запросы: используйте callback and разумный polling.