Adsrek Pay API Documentation
Site/App connection for payment acceptance, invoice journal, separate API profiles for payouts, access permissions, webhooks and refunds.
How Adsrek Pay works
Payment acceptance and programmatic payouts are separated into different flows.
Used for payment acceptance: invoice creation, status checks, Status/Callback URL, Success/Fail URL and refund of a specific payment.
Separate API profiles for server-side actions. Only here can you enable money-out, configure IP allowlist, rate limit and method permissions.
Journal of all invoices created by your Site/App: site, order ID, amount, created/paid date, Adsrek Pay invoice ID and status.
Site SHOP ID / API KEY / SECRET cannot be used for payouts. A payout requires the API ID and keys of a separate API profile.
shop_id to the payout endpoint, the server returns PAYOUT_REQUIRES_API_PROFILE.Site and app connections
Both types accept payments, but they are configured differently.
Enter a name and HTTPS domain. Configure the Status/Callback URL to confirm payment. Success/Fail URLs are used only to redirect the client.
Use an app connection if there is no separate domain. Specify IP:Port, for example 203.0.113.10:443, and, if needed, Status/Callback and redirect URLs.
Иконка Adsrek Pay для сайта
Готовый значок для кнопки оплаты, списка платёжных систем and страницы выбора способа оплаты.
Для интерфейса сайта используйте official SVG. Он остаётся чётким при любом размере and подходит для кнопок вроде «Pay через Adsrek Pay».
<img
src="https://adsrekpay.com/img/brand/adsrekpay-icon.svg"
alt="Adsrek Pay"
width="40"
height="40"
><link rel="icon" type="image/png" sizes="32x32"
href="https://adsrekpay.com/favicon-32x32.png">Payment invoices
Journal of incoming invoices from your Site/App.
Section «Payment invoices» does not create a separate payment integration. It shows existing invoices and helps the connection owner monitor payments.
Site/App name, order ID, description, amount and currency, creation date, payment date and internal Adsrek Pay invoice ID.
new — pending, paid — paid, expired — expired, cancel — cancelled, refunded — refunded.
API profiles, security and permissions
An API profile is not a merchant connection and does not use Site/App keys.
Create a profile in «API integration». The profile receives its own API ID, API KEY and SECRET. SECRET is shown only when created or rotated.
You can allow any IP or specify your server IPv4/IPv6/CIDR. A fixed server IP is recommended for payout APIs.
Each API profile has a rate limit, a maximum number of payouts per day and a daily amount limit by currency.
| Permission | Purpose |
|---|---|
| Account lookup | Check whether an AR wallet exists. |
| Balance | Read the API owner balances. |
| Notifications | Read API events. |
| Transfer / payout | Allows money-out from the Adsrek Pay balance. |
| Exchange | Permission to use the exchange API when the corresponding endpoint is available. |
| History | Retrieve the operation list. |
| Operation | Retrieve a single transaction from history. |
| Invoices | View invoices from Merchant connections. |
| Invoice creation | Create incoming invoices through the permitted API flow. |
Merchant API
Unified API for invoice creation, status checks and refunds.
https://adsrekpay.com/api/pay/create.php
https://adsrekpay.com/api/pay/status.php
https://adsrekpay.com/api/pay/payout.php
https://adsrekpay.com/api/pay/refund.php
timestamp (±300 seconds tolerance) and a unique nonce 16–96 characters long. For create, payout and refund is additionally required idempotency_key. Repeating a request with the same key and the same data returns the saved result; changing the data while reusing the key returns IDEMPOTENCY_CONFLICT.order_id, refund_order_id, nonce and idempotency_key use only Latin letters, digits and ._:-. Free-text and URL fields are replaced with their SHA-256 hex before inclusion in the canonical string. An empty string is hashed as well.Canonical string:
merchant|ACTION|SHOP_ID|API_KEY|TIMESTAMP|NONCE|IDEMPOTENCY_KEY|ORDER_ID|REFUND_ORDER_ID|AMOUNT|CURRENCY|TARGET|SHA256(DESCRIPTION)|SHA256(CALLBACK_URL)|SHA256(SUCCESS_URL)|SHA256(FAIL_URL){
"shop_id": 1001,
"api_key": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"timestamp": 1786300000,
"nonce": "n_7f0c9b21a44f8e71",
"idempotency_key": "order-1001-create",
"order_id": "ORDER-1001",
"amount": "10.00",
"currency": "RUB",
"description": "Payment for ORDER-1001",
"callback_url": "https://site.ru/adsrek/webhook",
"success_url": "https://site.ru/pay/success",
"fail_url": "https://site.ru/pay/fail",
"sign": "HMAC_SHA256_HEX"
}{
"shop_id": 1001,
"api_key": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"timestamp": 1786300100,
"nonce": "n_8c0d3a11b55e9f72",
"idempotency_key": "refund-1001",
"order_id": "ORDER-1001",
"refund_order_id": "REFUND-1001",
"sign": "HMAC_SHA256_HEX"
}{
"shop_id": 1001,
"api_key": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"timestamp": 1787541904,
"nonce": "statusNonce12345678",
"order_id": "ORDER-1001",
"sign": "HMAC_SHA256_HEX"
}
Webhook
Reliable notification queue with retry delivery.
POST application/json. The entire JSON body is signed.
Header X-Adsrek-Signature: sha256=HEX, where HEX = HMAC-SHA256 of the raw request body using the SECRET KEY.
X-Adsrek-Event-ID and the field event_id. Store it and process each event only once.
payment.paid and payment.refunded.
{
"event": "payment.paid",
"event_id": "evt_...",
"created_at": 1786300125,
"data": {
"invoice_id": 1501,
"shop_id": 1001,
"order_id": "ORDER-1001",
"amount": "10.00",
"currency": "RUB",
"status": "paid",
"paid_at": 1786300120
}
}The first delivery is attempted immediately. If the merchant server does not return a 2xx code, the queue retries after approximately 1 minute, 5 minutes, 15 minutes, 1 hour, 6 hours, 24 hours and another 24 hours. For automatic retries, add the following command to cron php /path/to/site/bin/merchant_webhook_worker.php once per minute.
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.
RUB, USD and EUR use 2 decimal places. The amount is normalized by the server before signing.
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.
Payout through a separate API profile
POST https://adsrekpay.com/api/pay/payout.php
{
"api_id": 7001,
"api_key": "API_PROFILE_KEY",
"timestamp": 1787541904,
"nonce": "payoutNonce1234567890",
"idempotency_key": "payout-1001-unique",
"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"
}
}api_id and api_key are taken from the “API integration” section. The signature is calculated from the string api|payout|API_ID|API_KEY|TIMESTAMP|NONCE|IDEMPOTENCY_KEY|ORDER_ID|AMOUNT|CURRENCY|TARGET. SECRET is used only for HMAC-SHA256 and is not sent in the request. nonce must be new for each request, while idempotency_key protects the payout from duplicate debiting.
Invoice statuses
Incoming invoice 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. |
| 403 | PAYOUT_REQUIRES_API_PROFILE | shop_id was sent to the payout endpoint instead of a separate API ID. |
| 403 | PAYOUT_DISABLED | The API profile does not have the “Transfer / payout” permission enabled. |
| 403 | IP_NOT_ALLOWED | The sender IP is not in the API profile allowlist. |
| 429 | RATE_LIMITED | API profile rate limit exceeded. |
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.
- Do not use one API profile for everything. Create separate profiles for different servers/apps with the minimum required permissions.
- Set an IP whitelist for payouts. An empty list technically allows any IP and is not recommended for money-out.
- Use Site/App keys for payment acceptance. Use separate keys from “API integration” for payouts. Site/App keys are not allowed to perform money-out. In an API profile, permissions for balance, history, invoices, payouts and other methods are configured separately.
- Payouts using site keys are prohibited. Money-out is available only through a separate API profile with its own IP allowlist and limits.
- The IP allowlist supports IPv4, IPv6 and CIDR. An empty list allows access from any IP.
- Keep a backup of config/paycore.local.php. Adsrek Pay needs this file to decrypt merchant SECRET KEY values.
Deleting Site/App and API profile
Deletion does not destroy financial history.
In “My sites”, the connection has a “Delete” action. A financial PIN and confirmation are required. New payments are no longer accepted through the connection after deletion.
An API profile can be deleted in “API integration”. The old API KEY/SECRET are revoked, payout is disabled and the profile disappears from the account.
Limits
Core API limits and rules.
0.01 in the selected currency.
1.00% is deducted from the amount credited to the merchant.
0.50% is charged additionally to the API profile owner.
A separate sandbox is not available yet. For testing, use a separate site and the minimum amount.
For each API profile, the rate is configured in “API integration” within 10–600 requests per minute. Merchant protection is applied separately to Site/App.
For an API profile, you can limit the number of payouts per day and the amount separately by currency, for example RUB=100000 or USD=1000.
When an allowlist is configured, a request from another address receives HTTP 403 and IP_NOT_ALLOWED. The restriction applies to all protected API requests.
Balance, history, invoice, exchange and payout permissions are stored separately for each API profile. A payout without permission returns PAYOUT_DISABLED.