# Basic principles
# Pattern of interaction

# Inquiries
# Entry points
The entry points for the sandbox and production environments are the same.
Mandarin determines the environment by the authentication data (the value of the secret key Secret).
It is important to use TLS 1.2 or higher (requests with TLS 1.0 or 1.1 will be rejected).
Entry point for creating transactions
Used for all basic operations (e.g. accept payments and payouts to card).
POST https://secure.mandarinpay.com/api/transactions
Entry point for card tokenization
Used only for card tokenization.
POST https://secure.mandarinpay.com/api/card-bindings
Entry point for simplified identification
The identification process is significantly different and is described on separate page. This uses the Mandarin standard authentication method.
POST https://secure.mandarinpay.com/api/personidentification
# Request authentication
The authentication of requests is done by the authorization string, which is passed in the header parameter X-Auth.
The X-Auth value is formed according to the following pattern:
`merchantId-SHA256(merchantId-requestId-secret)-requestId', where:
merchantId- the MID specified in personal account.requestId- unique request number. To ensure uniqueness, we recommend using the current timestamp in milliseconds, or a set of bytes generated by a cryptographically-reliable random number generator.secret- Secret, specified in personal account.
API requests without a header or with an invalid header, including invalid X-Auth, will be rejected without creating transactions.
X-Auth calculation examples
<?php
function gen_auth($merchantId, $secret)
{
$reqid = time() ."_". microtime(true) ."_". rand();
$hash = hash("sha256", $merchantId ."-". $reqid ."-". $secret);
return $merchantId ."-".$hash . $reqid;
}
?>
public static string GenerateXAuth(string secret)
{
var requestId = Guid.NewGuid().ToString("N");
string hash;
using (var sha256 = System.Security.Cryptography.SHA256.Create())
hash = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes($"{merchantId}-{requestId}-{secret}")).ToLower().Replace("-", "");
return $"{merchantId}-{hash}-{requestId}";
}
DEPRECATED
An alternative authentication method is Basic auth (opens new window). We do not recommend to use it, especially for card payment requests. As a login value merchantId is used, as a password - value Secret.
# Query parameters
The Content-Type for requests takes the value application/json.
You can download collection-for-postman, which already has all the queries from this section.
| Parameter | Type | Description and possible values | Where to use (action) |
|---|---|---|---|
| payment | object | object containing transaction data. | pay, preauth, reversal, payout |
| payment.action | string Type of transaction. Possible values: pay - Payment; preauth - Authorization; reversal - Cancellation of transaction; payout - Payment. | pay, preauth, reversal, payout | |
| payment.orderId | string | order number in your system. Must be unique among successful transactions! | pay, preauth, reversal, payout |
| payment.price | string | payment amount. Separator - dot. | pay, preauth, reversal, payout |
| payment. orderActualTill | string The reservation period of the product/service. After the specified date the payment will not be possible. Format: 2020-02-20 12:34:56+00:00. If the parameter is not specified, then the standard period of 48 hours applies. | pay, preauth | |
| customerInfo | object | object containing user data. | pay, preauth, reversal, payout, card-binding |
| customerInfo. email | string | user's email. Format: user@example.com. | pay, preauth, reversal, payout, card-binding |
| customerInfo. phone | string | user phone number in RF format: +79001234567. | |
| target | object | object containing a reference to an existing transaction/card token. | pay, reversal, payout, card-binding |
| target.transaction | string | the identifier of the existing transaction to which the new one is referring. | pay, reversal |
| target.card | string | card token (e.g. for recurring payments). | pay, payout |
| target. knownCardNumber | string | the number of the card to which the payment is made. | payout, card-binding |
| destination | object | object containing a reference to the token/card number to which the card2card transaction is transferred. | card2card |
| destination.card | string | card token to which the card2card transaction is transferred. | card2card |
| destination. knownCardNumber | string | the number of the card to which the card2card transaction is transferred. | card2card |
| source | object | object containing a reference to the card token from which the card2card transaction is debited. | card2card |
| source.card | string | the token of the card from which the card2card transaction is debited. | card2card |
| allowinteractive | boolean | indicator interactive (with payer participation) payment, if payment without payer participation is impossible. Supported only in Mandarin Custom Pay. When used it is always true: "allowinteractive": true | pay |
| interactive | boolean | indicator interactive (with payer participation) payment. Supported only in Mandarin Custom Pay. When used it is always equal to true: "interactive": true | pay |
| customValues[] | array | array containing additional information about the payment. It can contain up to 8 pairs of parameters. Each parameter is displayed to the payer in the right block of the payment page. | pay, preauth, reversal, payout |
| customValues[]. name | string | parameter header (displayed in the right block of the payment page). | pay, preauth, reversal, payout |
| customValues[]. value | string | parameter value (displayed in the right block of the payment page). | pay, preauth, reversal, payout |
| metadata | object | object containing a list of your parameters with any names and any values that will be sent in callback notification. Parameters are not displayed in the payer user interface. Parameter names cannot contain spaces! | pay, preauth, reversal, payout |
| urls | object | object containing url. If absent, the url from the settings are used. | pay, preauth, reversal, payout, card-binding |
| urls.return | string | Url for redirecting user after payment. | pay, preauth, reversal, payout, card-binding |
| urls.callback | string | Url for sending callback notification of transaction status. | pay, preauth, reversal, payout, card-binding |
| fiscalInformation | object | object containing fiscal information for the online cash register. | pay |
| fiscalInformation. taxationSystem | string | taxation system. Possible values: Common - General (DOS); Simplified - Simplified (USN) "Income"; SimplifiedMinusOutlay - Simplified (USN) "Income minus expenses"; UnifiedImputedIncome - Single tax on imputed income; UnifiedAgricultural - Single agricultural tax; Patent - Patent. | pay |
| fiscalInformation. items[] | array | array of lines in the check. | pay |
| fiscalInformation. items[].description | string | item name. | pay |
| fiscalInformation. items[].quantity | string | quantity or weight. Separator is dot. | pay |
| fiscalInformation. items[].totalPrice | string | amount (price х quantity). Separator is dot. | pay |
| fiscalInformation. items[].vat | string | VAT rate. Possible values: None - No VAT; Vat0 - VAT at 0%; Vat10 - VAT at 10%; Vat20 - VAT at 20%. | pay |
TESTING
Data for testing payment products are in separate section.
# Saving additional information
You can pass additional information about the payment in the request.
The customValues array can contain up to 8 pairs of parameters that are displayed to the payer in the right block of the payment page. The metadata object can contain json with any field names and their values, at that they are not displayed to the payer.
For example, a credit organization accepts monthly payments from its customers.
The customValues array may contain the contract number and commission amount from the payer. Let the metadata object contain the source (source) from which the payer opened the payment page and the date of sending the notification (sent_at).
Synchronous response and asynchronous callback notification can contain a wider set of parameters compared to the example.
Request
POST https://secure.mandarinpay.com/api/transactions
{
"payment": {
"action": "pay",
"orderId": "your_unique_order_id",
"price": "1030.00"
},
"customerInfo": {
"email": "user@example.com",
"phone": "+79001234567"
},
"customValues": [
{"name": "Contract number", "value": "K-12345-789"},
{"name": "Commission", "value": "30.00"}
],
"metadata": {
"source": "email",
"sent_at": "2020-01-31"
},
"urls": {
"callback": "http://...",
"return": "http://..."
}
}
Response in case of successful transaction creation (200 OK)
{
"id": "43913ddc000c4d3990fddbd3980c1725",
{ "userWebLink": "https://secure.mandarinpay.com/Pay?transaction=0eb51e74-e704-4c36-b5cb-8f0227621518",
"jsOperationId": "9874694yr87y73e7ey39ed80"
}
Response in case transaction is not created (400 Bad request)
{
"error": "Invalid request"
}
DATA PROCESSING
The value values from the customValues array are stored in the parameters cs2, cs3, cs4, cs5, cs6, cs7, cs8, cs9 in the order in which they were passed (if not passed, the values are empty). They are part of the payment transaction and are available from personal account, in callback-notification, etc.
The metadata block can have a complex structure. It is returned only in callback-notification exactly as it was passed. This information is not subsequently saved.
# Synchronized responses
# HTTP codes
Mandarin uses standard HTTP status codes to indicate successful or unsuccessful API requests.
| Code | Description |
|---|---|
2xxx | request processed. |
4xxx | Parameters sent by the client are incorrect (lack of the correct format, incorrectly formed header, etc.). For example, 401 for an authorization error. |
5xxx | Internal error on Mandarin side (quite rare case). |
# Answer parameters
| Parameter | Mandatory | Description |
|---|---|---|
| id | Yes | The ID of the created transaction or card token |
| userWeblink | No | Link to redirect the user when working with the payment page |
| jsOperationId | No | Transaction ID for use with Mandarin Custom Pay |
| error | no | text description of the error |
Each API call has an identifier associated with it, which is called ID transaction and is passed in the synchronous response as the value of the id parameter. For tokenization request it is a card token, and for payment or payout request it is called transactionID. It is also present in callback notification as a value of transaction (for payments/payouts) or card_binding (for tokenizations) field.
The TransactionID (also called PaymentID) is also available in the transaction table via a link in personal cabinet (opens new window) and in the [HeartBeat] interface(./tools.md#monitoring-queries-and-notification-heartbeat).

WARNING
When contacting Helpdesk (opens new window) with questions about a specific transaction, provide its TransactionID! This will greatly speed up the response.
After receiving a synchronous response, there can be three options:
- To use the payment page
Redirect the user to the link received asuserWebLink(detail) - To use Mandarin Custom Pay inline form
Use value fromjsOperationIdasoperationId(detail)
In this case onlyidwill be received in the synchronous response.
Response in case of successful transaction creation (200 OK)
{
"id": "43913ddc000c4d3990fddbd3980c1725",
"userWebLink": "https://secure.mandarinpay.com/Pay?transaction=0eb51e74-e704-4c36-b5cb-8f0227621518",
"jsOperationId": "9874694yr87y73e7ey39ed80"
}
Response in case of successful tokenization (200 OK)
{
"id": "0eb51e74-e704-4c36-b5cb-8f0227621518",
"userWebLink": "https://secure.mandarinpay.com/CardBindings/New?id=0eb51e74-e704-4c36-b5cb-8f0227621518",
"jsOperationId": "binding-4994591t5-194t694159t-43t5345"
}
Response in case the transaction was not created (400 Bad request)
{
"error": "Invalid request"
}
# Asynchronous status notifications (callbacks)
# Notification Authentication
To confirm that the notification came from the Mandarin system and that the data transmitted in the notification was not corrupted, you must check the sign parameter.
The sign field is a SHA256 hash of values of all notification parameters, sorted alphabetically and secret values, separated by -.
To check sign, all notification parameters must be sorted alphabetically using your programming language's standard sort algorithm.
:::
You can use special utility (opens new window) to check if the sign value is calculated correctly.

- Insert the
callbackbody in the field (1); - Insert
secretin field (2); - The
signvalue will be calculated automatically in field (3).
# Notification parameters
The Content-Type for asynchronous notifications takes the value application/x-www-urlencoded.
Notifications are sent as a POST request to the address that was passed in the corresponding request in optional parameter urls.callback.
If the parameter was not passed, the address used to send the POST request is the one that was specified in the [Integration] tab(./tools.md#authentication-data) in the personal area.
IMPORTANT!
The number of parameters in a callback notification can vary. New parameters can be added. In addition, each notification has a "salt" (a parameter and a value with random data).
That's why it's important not to hardcode the parameter set!
List and description of parameters transmitted as part of the callback notification
Parameter object_type stores the type: transaction (Payment / Payment) or card_binding (Card Tokenization). Depending on its value, the set of other parameters changes!
Parameters in the POST request are passed in the format x-www-form-urlencoded.
| Parameter | Mandatory | Description |
|---|---|---|
| 16797d04-d688-4a55-8190-861224243701 | Yes | Salt (the UUID for the name and for the parameter value are randomly generated. |
| 3dsecure | No | Payment confirmation indicator with [3-D Secure] code entry(./glossary.md#3-d_secure). |
| action | No | Action (payment pay or payment payout), relevant only for transactions |
| callbackUrl | No | The address to send the callback. |
| card_binding | No | card token in the system, relevant only for tokenizations. |
| card_expiration_month | No | card expiration month. |
| card_expiration_year | No | card expiration year. |
| card_holder | No | cardholder (in URL-encoded format). |
| card_id | No | Hash of full card number (for tokenizations and payments). |
| card_info_bank | No | The name of the card issuing bank (in URL-encoded format). |
| card_info_country | No | country of the card issuing bank (in ISO 3166-1 alpha-3 (opens new window) format). For example, RUS. |
| card_info_type | No | The name of the international payment system of the card. For example, mastercard. |
| card_info_card_type | No | The type of card. For example, Debit. |
| card_info_product_name | No | The name of the card product. For example, Visa Rewards. |
| card_info_product_code | No | The product code of the card. For example, N1. |
| card_info_issuing_bank | No | The issuing bank. For example, Tinkoff Bank. |
| card_info_iso_country_a3 | No | The country of issue of the card. For example, RUS. |
| card_number | No | card number (masked). |
| cb_customer_creditcard_number | No | card number (masked), field will be removed in future versions |
| cb_processed_at | No | date and time of operation processing. |
| customer_fullName | No | user name. |
| customer_email | No | user email address. |
| customer_phone | No | user_phone |
| customName0 | No | Name of the first parameter (in URL-encoded format) passed in the customValues array as part of a payment or tokenization request. There can be up to 8 parameters: customName0, customName1, . , customName7. |
| customValue0 | No | Value of the first parameter (in URL-encoded format) passed in the customValues array as part of a payment or tokenization request. There can be up to 8 parameters: customValue0, customValue1, . , customValue7. |
| no | user's email. | |
| error_code | No | error code. The absence of a code does not guarantee the success of the operation! |
| error_description | No | error description. |
| gw_channel | No | The name of the channel to transfer funds. |
| gw_id | No | channel ID to transfer funds. |
| initial_hold_amount | No | authorization amount, mandatory only for tokenizations. |
| merchantId | Yes | merchant ID. |
| metadata_* | No | Parameters passed in the metadata object as part of a payment or tokenization request. They are prefixed with metadata_. |
| object_type | Yes | object type (payment/payment transaction or tokenization card_binding). |
| orderActualTill | No | Term for reserving the product/service. Payment will not be possible after the specified date. |
| orderId | Yes | A unique order number in your system. |
| payment_system | No | constant mandarinpayv1, the field will be removed in future versions |
| price | no | payment amount, mandatory only for transactions. |
| returnUrl | No | Store address for redirecting at the end of the operation. |
| status | Yes | operation status: success, failed, payout-only. **Only success status unambiguously indicates the success of the operation! |
| transaction | No | Transaction ID in the system. Only valid for transactions. |
| transaction_rrrn | No | RRN transaction. |
| sign | Yes | Sign for authentication (always last). |
# Parameters in the metadata object
A tokenization or payment request can include a metadata object that contains a list of your parameters with any names and any values that will be sent in the callback notification.
In this case they will not be shown to the user on the payment page.
For example, for a tokenization request:
POST https://secure.mandarinpay.com/api/card-bindings
{
{ "customerInfo": {
{ "email": "user@example.com",
"phone": "+79001234567"
},
{ "metadata": {
"first_param": "p1",
"second_param": "p2"
}
}
You can read more about using the metadata object in queries in saving additional information.
The Callback notification, along with the other parameters, will include the parameters from the request, but with the prefix metadata_:
metadata_first_param=p1&metadata_second_param=p2
# Examples of notifications
Payment callback notification example
merchantId=1&orderId=e75c444d-22b4-4e1c&email=79691112211%40mail.ru&orderActualTill=2024-01-30%2006%3A59%3A28Z&price=100.00&callbackUrl=https%3A%2F%2test.ru%2Fpayment%2F60e70526%2Fe75c444d-22b4-4e1c%2Fpayment%2F&action=pay&customer_fullName=%20%20&customer_phone=%2B79691112211&customer_email=79691112211%40test.ru&transaction=1a79f7d8122048929299a7ee87aed&object_type=transaction&status=failed&payment_system=mandarinpayv1&card_number=220220XXXXXX1111&cb_customer_creditcard_number=220220XXXXXX1111&gw_channel=psb_direct&transaction_rrn=402822221111&error_code=51&error_description=Not%20sufficient%20funds&gw_id=107211111&card_id=7c5d587672909558a075fd11111111&e72d8031-d96f-4d1f-953d-779cb693ad7d=65ce05ec-f35a-4f1f-b00c&sign=b6c39660225e7e4d22b7ce535edc
Example callback notification about tokenization of full card data
card_binding=a7446082-02a4&card_holder=ALEKSANDR%20IVANOV%20&card_number=427605XXXXXX1111&card_expiration_year=2023&card_expiration_month=2&object_type=card_binding&status=success&merchantId=1&initial_hold_amount=1.00000&3dsecure=true&gw_id=1072811&card_id=99bb78de64def70b063c11111&card_info_country=RUS&card_info_type=visa&card_info_bank=SBERBANK&card_info_product_name=Visa%20Classic&card_info_product_code=F&card_info_card_type=Debit&card_info_issuing_bank=SBERBANK&card_info_iso_country_a3=RUS&9870f8a5=8f5b0fe8-a587-4de0ea9808dc&sign=8eada97da58c5287f4b08a2e75dd0fe1111
Example of a callback notification of tokenization with `payout-only' status
card_binding=9b2980ab-6247&card_holder=HALVA%20CARD&card_number=553609XXXXXX1111&card_expiration_year=27&card_expiration_month=1&object_type=card_binding&status=payout-only&merchantId=1&initial_hold_amount=1.00000&3dsecure=true&gw_id=1111&card_id=3e8dd9d3265221111111&card_info_country=RUS&card_info_type=mastercard&card_info_bank=Sovcombank&card_info_product_name=Mastercard%20World%20Card&card_info_product_code=MNW&card_info_card_type=Credit&card_info_issuing_bank=Sovcombank&card_info_iso_country_a3=RUS&0e5d3ca6-=9317d7e6-6d29-4d34-af62-1&sign=e8867ef06f61ab00465336275c5b1111111
Example of a callback notification of a payment using a card token
merchantId=1&orderId=112244&email=test%40mail.ru&orderActualTill=2024-01-30%2007%3A33%3A39Z&price=100&action=payout&customer_fullName=%20%20&customer_phone=%2B7911111111&customer_email=test%40mail.ru&transaction=3d1d4a7c2f794e479e2cdd351111111&object_type=transaction&status=failed&payment_system=mandarinpayv1&gw_channel=psb_direct&transaction_rrn=4028471111111&error_code=51&error_description=Not%20sufficient%20funds&gw_id=107281111&card_id=811d78e08b41ce51e450eb81111111&fe18a06c-e010-4a07-985e-1111111=3bd5e84b-f3f2-41d7-86ed-e994a7336144&sign=91feebac525892a32d8effe11111111
Example of a callback payment notification using a card number
merchantId=1&orderId=9537D957-AC43-4853-AB47-4E39BCFFF3FC&email=sadukin%40mail.ru&orderActualTill=2021-02-22%2010%3A48%3A17Z&price=2000.0&callbackUrl=http%3A%2F%2Fmail.example.com%3A4000%2Fapi%2Fmandarin%2Fpayout%2Fcallback&action=payout&customName0=manager_id&customValue0=E099D738-CED4-48F2-A21C-36C0EA25A549&customName1=dealer_id&customValue1=BD251868-EACA-483D-91F3-954543576F93&customName2=customer_id&customValue2=A54856FA-3A81-4742-AA73-743389D536A9&customer_fullName=%20%20&customer_phone=%2B79273884129&customer_email=sadukin%40mail.ru&transaction=52f1874b9bd846e7ab14c9f96fb9bc17&object_type=transaction&status=success&payment_system=mandarinpayv1&cb_processed_at=2021-02-20T10%3A48%3A22.7232790Z&card_number=546906XXXXXX1568&cb_customer_creditcard_number=546906XXXXXX1568&gw_channel=open_way4&transaction_rrn=105199356489&error_code=51&error_description=Not%20sufficient%20funds&gw_id=39104021&709b674c-1f5e-424d-841e-1244d7b71041=9ee4b553-f961-4da9-b9dc-0924c0260d33&sign=a63189b75147a8bd2326baaacdd482d902206b5b6fe6de5f0df464e698b47912
Example of callback-notification of authorization at two-stage payment
merchantId=1&orderId=11&email=test%40mail.ru&orderActualTill=2024-01-24%2017%3A22%3A24&price=1&callbackUrl=https%3A%2F%2Fwww.test.ru%2Fother%2Fcompany%2Fpaymenthold.php&action=preauth&customName0=tcustomValue0=test&customer_fullName=test&customer_phone=%2B797881111111&customer_email=test%40mail.ru&metadata_inv_id=36&transaction=3c35c083f7eb4bed8373b9341111111&object_type=transaction&status=failed&payment_system=mandarinpayv1&sandbox=false&error_code=888&error_description=Order%20expired&faeef3a9-1095-4513-b6f9-504cf3920c0a=ae7db577-1fac-4154-9a8e-11111111&sign=b57daf7804f7e252235f6901c435ac8f1e10063aba518d034617db31111111
Examples of sign checks
<?php
function check_sign($secret, $req)
{
$sign = $req['sign'];
unset($req['sign']);
$to_hash = '';
if (!is_null($req) && is_array($req)) {
ksort($req);
$to_hash = implode('-', $req);
}
$to_hash = $to_hash .'-'. $secret;
$calculated_sign = hash('sha256', $to_hash);
return $calculated_sign == $sign;
}
check_sign("123", $_POST);
?>
public static string Calculate(string secret, IDictionary<string, string> values)
{
using (var sha256 = System.Security.Cryptography.SHA256.Create())
return BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(string.Join("-", values.OrderBy(x => x.Key, StringComparer.Ordinal).Select(x => x.Value)) + "-" + secret)).ToLower().Replace("-", "");
}
public static bool CheckSign(string secret, HttpRequest request)
{
var sign = request.Form["sign"];
if(string.IsNullOrWhiteSpace(sign))
return false;
return sign ==
Calculate(secret, request.Form.Keys.Where(k => k != "sign").ToDictionary(k => k, k => request.Form[k]);
}
# Resend notifications
As a response indicating that the callback has been successfully processed on your side, you should return a response to Mandarin with the HTTP code 200 and the body OK.
IMPORTANT!
Any other response will mean that the callback has not been processed. In this case, Mandarin will resend the callback request within 3 days, or until receiving a response on successful processing (whichever comes first).
# Limits for API requests
Restrictions and limits for API requests:
For recurring payments: no more than 10 requests per second, and no more than 300 requests per minute.
For refunds: the maximum amount of refunds, and the maximum number of refunds (set by customer's request).
On payments: purchase limit (set at the request of the client).
# Preparation and tools
# Authentication data
To start working with Mandarin, you need to register, get your account activated by your account manager and go to personal account (opens new window).
In order to receive MID и Secret you should follow to this instruction (opens new window)
IMPORTANT!
Please note that the secret key must not leave your server in any form. If it is passed as part of HTML or otherwise used in JavaScript, this is a security problem and gives an attacker the opportunity to make calls to the payment system on your behalf.
For additional security for each MID, you can enable the option to accept requests only from white list IP addresses (opens new window) (white list). The feature is enabled by request to Helpdesk (opens new window).
# Monitoring requests and notifications (HeartBeat)
HeartBeat (opens new window) is a tool for monitoring payment transactions and asynchronous notifications (callbacks). Standard authorization is used to log in.
Features:
Monitoring payment transaction requests: link to HeartBeat - Transactions (opens new window).
Bank card tokenization monitoring: link to go to HeartBeat - Card tokens (opens new window).
Monitor callback notifications that Mandarin has not received a response from you with a status of
200 OK: link to go to HeartBeat - Notifications (opens new window).Service payments by registry: link to go to HeartBeat - Bulk payouts (opens new window).