NAV

Overview

Crypto Pay is a solution designed to be used as a crypto-currency Payment Service Provider for Payment Aggregators and as a standalone crypto-currency payment solution for Corporate Clients (Merchants) and provides the ability for Merchant Clients to deposit or pay for goods/services using crypto-currency. Features:

Base URL

The base url is https://api.cryptopayx.tech

As per RESTful design patterns, Crypto Pay API uses following HTTP methods:

When you are making a request, you can pass arguments in it as:

Timestamps and other time-related fields are in milliseconds.

Data in response is listed in chronological order, newest on top.

Parameters for GET endpoints must be sent as a query string.

Parameters For POST, PUT, and DELETE endpoints may be sent as a query string or in the request body with content type application/json. You can mix parameters between both the query string and request body.

Parameters can be sent in any order.

If a parameter is sent in both the query string and request body, the query string parameter will be used.

Postman

We provide postman collections and environments for quick and easy use:

Return codes

200 Successful Request.

201 Created successfully.

400 Bad Request. Check the format of your request for mistakes and try again.

401 Unauthorized. Check if your API key is eligible for using the endpoint.

500 Server Error. Issue on our side. Contact us for more information.

404 Resource is missing. Contact us for more information.

Authentication

API Key

To access Crypto PayX API endpoints you have to obtain API key and secret. Starting 09/12/2024, we added a possibility for customers to generate and manage Crypto PayX credentials directly from Client Area.

For the customers with this functionality enabled, it can be accessed in their account Security settings.

Security Settings

The following API key management functionality is possible within the Client Area: - New API key request. One pair (key/secret) can be created for Crypto PayX. - Delete the existing API key. - Reset. Delete the existing API key and create a new one.

Keys_desktop_web

Keys_mobile_web

Make sure to replace <apiKey> and <apiSecret> in the code examples with your API key and secret respectively.

Use https://api.sandbox.cryptopayx.tech/ URL for Crypto PayX Sandbox. See Sandbox for more info.

// C# example
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;

var apiKey = "<apiKey>";
var apiSecret = "<apiSecret>";


var client = new HttpClient
{
    BaseAddress = new Uri("https://api.cryptopayx.tech")
};

var pathWithQuery = "/v1/test-api?testParam1=test1&testParam2=test2";
var pathWithOutQuery = "/v1/test-api";

var requestBody = JsonConvert.SerializeObject(
            new
            {
                testProperty1 = "test1",
                testProperty2 = "test12"
            });

var request = new HttpRequestMessage()
{
    Method = HttpMethod.Post,
    Content = new StringContent(requestBody, Encoding.UTF8, "application/json"),
    RequestUri = new Uri($"{pathWithQuery}", UriKind.Relative)
};

using HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(apiSecret));
using var sha256 = SHA256.Create();

var contentHash = Convert.ToBase64String(sha256.ComputeHash(Encoding.UTF8.GetBytes(content)));
var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
var signatureString = $"{timestamp}{request.Method}{pathWithOutQuery}{contentHash}";

var signatureHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(signatureString));
request.Headers.Add("CRYPTO-PAY-API-KEY", apiKey);
request.Headers.Add("CRYPTO-PAY-API-SIGN", Convert.ToBase64String(signatureHash));
request.Headers.Add("CRYPTO-PAY-API-TIMESTAMP", timestamp.ToString());

var response = await client.SendAsync(request);
// ...
//JavaScript example
const crypto = require('crypto');
const request = require('request');

const apiKey = "<apiKey>";
const apiSecret = "<apiSecret>";
const pathWithOutQuery = "/v1/test-api";

const req = {
    method: 'POST',
    url: '/v1/test-api?testParam1=test1&testParam2=test2',
    body: JSON.stringify({testProperty1:"test1",testProperty2:"test2"})
};
const timestamp = Math.floor(Date.now());
const contentHash = crypto.createHash("sha256").update(req.body).digest().toString("base64");
const signatureString = timestamp + req.method + pathWithOutQuery + contentHash;
const signature = crypto.createHmac("sha256",  Buffer.from(apiSecret, "base64")).update(Buffer.from(signatureString,"utf8")).digest().toString("base64");

const options = {
    baseUrl: 'https://api.cryptopayx.tech',
    url: req.url,
    method: req.method,
    headers: {
        'CRYPTO-PAY-API-SIGN': signature,
        'CRYPTO-PAY-API-TIMESTAMP': timestamp,
        'CRYPTO-PAY-API-KEY': apiKey,
        'content-type': 'application/json'
    },
    body: req.body
};

request(options,function(err, response){
  // ...
}

Making a request

All requests to authorized endpoints must contain the following headers:

All request bodies should have content type application/json and be valid JSON

Selecting timestamp

CRYPTO-PAY-API-TIMESTAMP must be number of milliseconds since
UNIX Epoch. It should be within 60 seconds of the API service time to be considered as valid.

Signing message

Signature is generated by creating a SHA256 HMAC using the API secret on the string timestamp + method + pathWithQuery + contentHash

Sandbox for payment intent

Overview

Crypto Payx sandbox is aimed to help those involved in Crypto Pay integration.

With Sandbox, it is possible to emulate payment intents with different parameters to test all possible scenarios for the integration, without the need to operate real data.

All the endpoints, response formats, error codes, and security features for the Sandbox are identical to that of real Crypto Payx.

How to test Crypto Payx integration using Sandbox

Make sure to have a real Crypto Payx Sandbox account created beforehand.

Crypto Payx Sandbox account is separate from your real account, and uses a separate API key and secret, which need to be generated for it. To create it please contact us.

After you have the API key and secret for your Crypto Pay Sandbox, you can authenticate by following the instructions at Authentication and test various flows for the payment intent.

URL for the Crypto Pay Sandbox: https://api.sandbox.cryptopayx.tech/

Possible payment intent flows

All the the mock payment intents in Crypto Payx Sandbox are done in the following amounts for the currencies in the table below:

Coin Network Mock payment amount
USDT BNB_TEST 100 USDT
BTC BTC_TEST 0.01 BTC
ETH BNB_TEST 1 ETH
XRP XRP_TEST 0 XRP
ADA ADA_TEST 100 ADA in two separate deposits for one payment intent.

It means that if a payment intent is created with USDT coin and BNB_TEST network, Sandbox will emulate sending 100USDT for this payment intent. All the possible flows can be tested by adjusting the requested amount of crypto, and changing the account settings for:

Default threshold is set at 2%, if enabled. See Payment intent threshold for more info.

Flow 1

Executing the flow via iframe

HTTP Request

POST /v1/payment-intents/

  1. Create payment intent for 100 USD regardless of threshold and conversion settings.
  2. Choose coin USDT and network Binance Smart Chain Testnet (BNB_TEST).

Executing the flow via API

HTTP Request

POST /v2/payment-intents/

Request Body

  "currencyFrom": "USDT",  
  "currencyTo": "USD",  
  "amountTo": 100,  
  "networkCode": "BNB_TEST",  
  "customOrderId": "test 1",  
  "callbackUrl": "https://webhook.site/e3f6bc53-f711-456d-85cb-a8cc3f9d27e7"  
}

Expected Response

{  
  "paymentIntentId": "f7d6bb02-b399-40ef-9127-676d4db21861",  
  "currencyFrom": "USDT",  
  "amountFrom": 100,  
  "currencyTo": "USD",  
  "amountTo": 100,  
  "address": "pZvcn7hQNR7ptnF0X8mM4gnMBC6e3ihOrNsfWQRZ",  
  "additionalAddress": "string",  
  "additionalAddressType": "string",  
  "quoteValidTo": "2024-01-01T10:40:10.840Z",  
  "customOrderId":"test 1"  
}

Expected Result

You should get two notifications as the payment intent is processed.

The first one with the payment intent pending.

{ "paymentIntentId": "f34d28d4-ddf2-448a-b70a-ae14342d1e83", "customOrderId": "test 1", "amountFrom": 100, "amountTo": 100, "currencyFrom": "USDT", "currencyTo": "USD", "status": "Pending", "receivedAmount": null, "executedAmountTo": 100, "executedCurrencyTo": null, "statusDescription": null, "address": "pZvcn7hQNR7ptnF0X8mM4gnMBC6e3ihOrNsfWQRZ", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": null, "sourceAddress": null, "notificationType": "PaymentIntentNotification" }

The second notification - when the payment intent is successfully completed.

{ "paymentIntentId": "f34d28d4-ddf2-448a-b70a-ae14342d1e83", "customOrderId": "test 1", "amountFrom": 100, "amountTo": 100, "currencyFrom": "USDT", "currencyTo": "USD", "status": "Completed", "receivedAmount": 100, "executedAmountTo": 100, "executedCurrencyTo": "USD", "statusDescription": null, "address": "pZvcn7hQNR7ptnF0X8mM4gnMBC6e3ihOrNsfWQRZ", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": "lcevjc4idx7i1819t7uasgnjkv03gh", "sourceAddress": "JYp7hxUCsm", "notificationType": "PaymentIntentNotification" }

Flow 2

Executing the flow via iframe

HTTP Request

POST /v1/payment-intents/

  1. Create payment intent for 102 USD with default 2% threshold and conversion disabled for account or a specific currency.
  2. Choose coin USDT and network Binance Smart Chain Testnet (BNB_TEST).

Executing the flow via API

HTTP Request

POST /v2/payment-intents/

Request Body

{  
  "currencyFrom": "USDT",  
  "currencyTo": "USD",  
  "amountTo": 102,  
  "networkCode": "BNB_TEST",  
  "customOrderId": "test 1",  
  "callbackUrl": "https://webhook.site/e3f6bc53-f711-456d-85cb-a8cc3f9d27e7"  
}

Expected Response

{  
  "paymentIntentId": "f7d6bb02-b399-40ef-9127-676d4db21862"   
  "currencyFrom": "USDT",  
  "amountFrom": 102,  
  "currencyTo": "USD",  
  "amountTo": 102,  
  "address": "rltH58oowqTZjCziPhGL6m4jdzqeeqx3jAGr16de",  
  "additionalAddress": "string",  
  "additionalAddressType": "string",  
  "quoteValidTo": "2024-01-01T10:40:10.840Z",  
  "customOrderId":"test 1"  
}

Expected Result

You should get three notifications as the payment intent is processed.

The first one with the payment intent pending.

{ "paymentIntentId": "3d53363a-e3f1-412e-a808-457802e42d7c", "customOrderId": "test 1", "amountFrom": 102, "amountTo": 102, "currencyFrom": "USDT", "currencyTo": "USD", "status": "Pending", "receivedAmount": null, "executedAmountTo": 102, "executedCurrencyTo": null, "statusDescription": null, "address": "rltH58oowqTZjCziPhGL6m4jdzqeeqx3jAGr16de", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": null, "sourceAddress": null, "notificationType": "PaymentIntentNotification" }

As the amount is not equal to the amount requested, which fails the initial payment intent, but within the threshold, the automatic retry payment intent is initiated and gets completed successfully.

{ "paymentIntentId": "3d53363a-e3f1-412e-a808-457802e42d7c", "retryPaymentIntentId": "9fffbaa3-e565-4b81-96ef-a474042a902b", "customOrderId": "test 1", "amountFrom": 100, "amountTo": 100, "currencyFrom": "USDT", "currencyTo": "USD", "status": "Completed", "notificationType": "AutoRetryPaymentIntentNotification" }

After the auto retry is completed, the initial payment intent is completed with "Partially completed" status, and the third notification is sent.

{ "paymentIntentId": "3d53363a-e3f1-412e-a808-457802e42d7c", "customOrderId": "test 1", "amountFrom": 102, "amountTo": 102, "currencyFrom": "USDT", "currencyTo": "USD", "status": "PartiallyCompleted", "receivedAmount": 100, "executedAmountTo": 100, "executedCurrencyTo": "USD", "statusDescription": "Invalid amount: Less than expected", "address": "rltH58oowqTZjCziPhGL6m4jdzqeeqx3jAGr16de", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": "oixtgm042pg7p4y12qbwybq3ne2w6e", "sourceAddress": "6VYFAWqT1g", "notificationType": "PaymentIntentNotification" }

Flow 3

Executing the flow via iframe

HTTP Request

POST /v1/payment-intents/

  1. Create payment intent for 132 USD with default 2% threshold and conversion disabled for account or specific currency.
  2. Choose coin USDT and network Binance Smart Chain Testnet (BNB_TEST).

Executing the flow via API

HTTP Request

POST /v2/payment-intents/

Request Body

{  
  "currencyFrom": "USDT",  
  "currencyTo": "USD", 
  "amountTo": 132,  
  "networkCode": "BNB_TEST",  
  "customOrderId": "test 1",  
  "callbackUrl": "https://webhook.site/e3f6bc53-f711-456d-85cb-a8cc3f9d27e7"  
}

Expected Response

{  
  "paymentIntentId": "f7d6bb02-b399-40ef-9127-676d4db21862",   
  "currencyFrom": "USDT",  
  "amountFrom": 132,  
  "currencyTo": "USD",  
  "amountTo": 132,  
  "address": "rltH58oowqTZjCziPhGL6m4jdzqeeqx3jAGr16de",  
  "additionalAddress": "string",  
  "additionalAddressType": "string",  
  "quoteValidTo": "2024-01-01T10:40:10.840Z",  
  "customOrderId":"test 1"  
}

Expected Result

You should get three notifications as the payment intent is processed.

The first one with the payment intent pending.

{ "paymentIntentId": "2d24bd55-2cbd-456a-9319-9972d5394237", "customOrderId": "test 1", "amountFrom": 132, "amountTo": 132, "currencyFrom": "USDT", "currencyTo": "USD", "status": "Pending", "receivedAmount": null, "executedAmountTo": 132, "executedCurrencyTo": null, "statusDescription": null, "address": "GutRzPnRdFRKnF6IMtgiYXbq9dxMbJsLLUpT8dBn", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": null, "sourceAddress": null, "notificationType": "PaymentIntentNotification" }

As the amount is not equal to the amount requested, which fails the initial payment intent, and doesn't satisfy the threshold, the automatic retry payment intent is initiated and fails.

{ "paymentIntentId": "2d24bd55-2cbd-456a-9319-9972d5394237", "retryPaymentIntentId": "81e00873-cb54-4fe2-9969-58804ad75a07", "customOrderId": "test 1", "amountFrom": 100, "amountTo": 100, "currencyFrom": "USDT", "currencyTo": "USD", "status": "Failed", "notificationType": "AutoRetryPaymentIntentNotification" }

After the auto retry has failed, the initial payment intent is completed with "Manual action required" status, and the third notification is sent.

{ "paymentIntentId": "2d24bd55-2cbd-456a-9319-9972d5394237", "customOrderId": "test 1", "amountFrom": 132, "amountTo": 132, "currencyFrom": "USDT", "currencyTo": "USD", "status": "ManualActionRequired", "receivedAmount": 100, "executedAmountTo": 132, "executedCurrencyTo": null, "statusDescription": "Invalid amount: Less than expected", "address": "GutRzPnRdFRKnF6IMtgiYXbq9dxMbJsLLUpT8dBn", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": "lrkzdzu28mtq93m1jtzc2fsaaqhaaz", "sourceAddress": "XIzmJWPM63", "notificationType": "PaymentIntentNotification" }

Flow 4

Executing the flow via iframe

HTTP Request

POST /v1/payment-intents/

  1. Create payment intent for 92 USD with default 2% threshold and enabled conversion.
  2. Choose coin USDT and network Binance Smart Chain Testnet (BNB_TEST).

Executing the flow via API

HTTP Request

POST /v2/payment-intents/

Request Body

{  
  "currencyFrom": "USDT",  
  "currencyTo": "USD",  
  "amountTo": 92,  
  "networkCode": "BNB_TEST",  
  "customOrderId": "test 1",  
  "callbackUrl": "https://webhook.site/e3f6bc53-f711-456d-85cb-a8cc3f9d27e7"  
}

Expected Response

{  
  "paymentIntentId": "f7d6bb02-b399-40ef-9127-676d4db21862",   
  "currencyFrom": "USDT",  
  "amountFrom": 92,  
  "currencyTo": "USD",  
  "amountTo": 92,  
  "address": "rltH58oowqTZjCziPhGL6m4jdzqeeqx3jAGr16de",  
  "additionalAddress": "string",  
  "additionalAddressType": "string",  
  "quoteValidTo": "2024-01-01T10:40:10.840Z",  
  "customOrderId":"test 1"  
}

Expected Result

You should get three notifications as the payment intent is processed.

The first one with the payment intent pending.

{ "paymentIntentId": "2d24bd55-2cbd-456a-9319-9972d5394237", "customOrderId": "test 1", "amountFrom": 92, "amountTo": 92, "currencyFrom": "USDT", "currencyTo": "USD", "status": "Pending", "receivedAmount": null, "executedAmountTo": 92, "executedCurrencyTo": null, "statusDescription": null, "address": "GutRzPnRdFRKnF6IMtgiYXbq9dxMbJsLLUpT8dBn", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": null, "sourceAddress": null, "notificationType": "PaymentIntentNotification" }

As the amount is not equal to the amount requested, which fails the initial payment intent, and doesn't satisfy the threshold, the automatic retry payment intent is initiated and fails.

{ "paymentIntentId": "2d24bd55-2cbd-456a-9319-9972d5394237", "retryPaymentIntentId": "81e00873-cb54-4fe2-9969-58804ad75a07", "customOrderId": "test 1", "amountFrom": 100, "amountTo": 100, "currencyFrom": "USDT", "currencyTo": "USD", "status": "Failed", "notificationType": "AutoRetryPaymentIntentNotification" }

After the auto retry has failed, the initial payment intent is completed with "Manual action required" status, and the third notification is sent.

{ "paymentIntentId": "2d24bd55-2cbd-456a-9319-9972d5394237", "customOrderId": "test 1", "amountFrom": 92, "amountTo": 92, "currencyFrom": "USDT", "currencyTo": "USD", "status": "ManualActionRequired", "receivedAmount": 100, "executedAmountTo": 92, "executedCurrencyTo": null, "statusDescription": "Invalid amount: Less than expected", "address": "GutRzPnRdFRKnF6IMtgiYXbq9dxMbJsLLUpT8dBn", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": "lrkzdzu28mtq93m1jtzc2fsaaqhaaz", "sourceAddress": "XIzmJWPM63", "notificationType": "PaymentIntentNotification" }

Flow 5

Executing the flow via iframe

HTTP Request

POST /v1/payment-intents/

  1. Create payment intent for 99 USD with disabled threshold and enabled conversion.
  2. Choose coin USDT and network Binance Smart Chain Testnet (BNB_TEST).

Executing the flow via API

HTTP Request

POST /v2/payment-intents/

Request Body

{  
  "currencyFrom": "USDT",  
  "currencyTo": "USD",  
  "amountTo": 99,  
  "networkCode": "BNB_TEST",  
  "customOrderId": "test 1",  
  "callbackUrl": "https://webhook.site/e3f6bc53-f711-456d-85cb-a8cc3f9d27e7"  
}

Expected Response

{  
  "paymentIntentId": "f7d6bb02-b399-40ef-9127-676d4db21862",   
  "currencyFrom": "USDT",  
  "amountFrom": 99,  
  "currencyTo": "USD",  
  "amountTo": 99,  
  "address": "rltH58oowqTZjCziPhGL6m4jdzqeeqx3jAGr16de",  
  "additionalAddress": "string",  
  "additionalAddressType": "string",  
  "quoteValidTo": "2024-01-01T10:40:10.840Z",  
  "customOrderId":"test 1"  
}

Expected Result

You should get three notifications as the payment intent is processed.

The first one with the payment intent pending.

{ "paymentIntentId": "2d24bd55-2cbd-456a-9319-9972d5394237", "customOrderId": "test 1", "amountFrom": 99, "amountTo": 99, "currencyFrom": "USDT", "currencyTo": "USD", "status": "Pending", "receivedAmount": null, "executedAmountTo": 99, "executedCurrencyTo": null, "statusDescription": null, "address": "GutRzPnRdFRKnF6IMtgiYXbq9dxMbJsLLUpT8dBn", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": null, "sourceAddress": null, "notificationType": "PaymentIntentNotification" }

As the amount is not equal to the amount requested, which fails the initial payment intent, and there is no threshold to allow any deviation from the requested amount, the automatic retry payment intent is initiated and fails.

{ "paymentIntentId": "2d24bd55-2cbd-456a-9319-9972d5394237", "retryPaymentIntentId": "81e00873-cb54-4fe2-9969-58804ad75a07", "customOrderId": "test 1", "amountFrom": 100, "amountTo": 100, "currencyFrom": "USDT", "currencyTo": "USD", "status": "Failed", "notificationType": "AutoRetryPaymentIntentNotification" }

After the auto retry has failed, the initial payment intent is completed with "Manual action required" status, and the third notification is sent.

{ "paymentIntentId": "2d24bd55-2cbd-456a-9319-9972d5394237", "customOrderId": "test 1", "amountFrom": 99, "amountTo": 99, "currencyFrom": "USDT", "currencyTo": "USD", "status": "ManualActionRequired", "receivedAmount": 100, "executedAmountTo": 99, "executedCurrencyTo": null, "statusDescription": "Invalid amount: More than expected", "address": "GutRzPnRdFRKnF6IMtgiYXbq9dxMbJsLLUpT8dBn", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": "lrkzdzu28mtq93m1jtzc2fsaaqhaaz", "sourceAddress": "XIzmJWPM63", "notificationType": "PaymentIntentNotification" }

Flow 6

Executing the flow via iframe

HTTP Request

POST /v1/payment-intents/

  1. Create payment intent for 101 USD with disabled threshold and disabled conversion.
  2. Choose coin USDT and network Binance Smart Chain Testnet (BNB_TEST).

Executing the flow via API

HTTP Request

POST /v2/payment-intents/

Request Body

{  
  "currencyFrom": "USDT",  
  "currencyTo": "USD",  
  "amountTo": 101,  
  "networkCode": "BNB_TEST",  
  "customOrderId": "test 1",  
  "callbackUrl": "https://webhook.site/e3f6bc53-f711-456d-85cb-a8cc3f9d27e7"  
}

Expected Response

{
  "paymentIntentId": "f7d6bb02-b399-40ef-9127-676d4db21862",   
  "currencyFrom": "USDT",  
  "amountFrom": 101,  
  "currencyTo": "USD",  
  "amountTo": 101,  
  "address": "rltH58oowqTZjCziPhGL6m4jdzqeeqx3jAGr16de",  
  "additionalAddress": "string",  
  "additionalAddressType": "string",  
  "quoteValidTo": "2024-01-01T10:40:10.840Z",  
  "customOrderId":"test 1"  
}

Expected Result

You should get three notifications as the payment intent is processed.

The first one with the payment intent pending.

{ "paymentIntentId": "2d24bd55-2cbd-456a-9319-9972d5394237", "customOrderId": "test 1", "amountFrom": 101, "amountTo": 101, "currencyFrom": "USDT", "currencyTo": "USD", "status": "Pending", "receivedAmount": null, "executedAmountTo": 101, "executedCurrencyTo": null, "statusDescription": null, "address": "GutRzPnRdFRKnF6IMtgiYXbq9dxMbJsLLUpT8dBn", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": null, "sourceAddress": null, "notificationType": "PaymentIntentNotification" }

As the amount is not equal to the amount requested, which fails the initial payment intent, and there is no threshold to allow any deviation from the requested amount, the automatic retry payment intent is initiated and fails.

{ "paymentIntentId": "2d24bd55-2cbd-456a-9319-9972d5394237", "retryPaymentIntentId": "81e00873-cb54-4fe2-9969-58804ad75a07", "customOrderId": "test 1", "amountFrom": 100, "amountTo": 100, "currencyFrom": "USDT", "currencyTo": "USD", "status": "Failed", "notificationType": "AutoRetryPaymentIntentNotification" }

After the auto retry has failed, the initial payment intent is completed with "Manual action required" status, and the third notification is sent.

{ "paymentIntentId": "2d24bd55-2cbd-456a-9319-9972d5394237", "customOrderId": "test 1", "amountFrom": 101, "amountTo": 101, "currencyFrom": "USDT", "currencyTo": "USD", "status": "ManualActionRequired", "receivedAmount": 100, "executedAmountTo": 101, "executedCurrencyTo": null, "statusDescription": "Invalid amount: Less than expected", "address": "GutRzPnRdFRKnF6IMtgiYXbq9dxMbJsLLUpT8dBn", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": "lrkzdzu28mtq93m1jtzc2fsaaqhaaz", "sourceAddress": "XIzmJWPM63", "notificationType": "PaymentIntentNotification" }

Flow 7

If the deposit will be received after the payment intent validity timeframe, and the deposit sum satisfies payment intent threshold requirements, payment intent status will change to `Completed'

Executing the flow via iframe

HTTP Request

POST /v1/payment-intents/

  1. Create payment intent for 0 USD.
  2. Choose coin XRP and network XRP_TEST.

Executing the flow via API

HTTP Request POST /v2/payment-intents/

Request Body

{  
  "currencyFrom": "XRP",  
  "currencyTo": "USD",  
  "amountTo": 132,  
  "networkCode": "XRP_TEST",  
  "customOrderId": "test 1",  
  "callbackUrl": "https://webhook.site/e3f6bc53-f711-456d-85cb-a8cc3f9d27e7"  
}

Expected Response

{  
  "paymentIntentId": "f7d6bb02-b399-40ef-9127-676d4db21862",  
  "currencyFrom": "XRP",  
  "amountFrom": 1334.52,  
  "currencyTo": "USD",  
  "amountTo": 132,  
  "address": "rltF58oowqTZjCziPhGL6m4jdzqeeqx3jAGr16de",  
  "additionalAddress": "string",  
  "additionalAddressType": "string",  
  "quoteValidTo": "2024-01-01T10:40:10.840Z",  
  "customOrderId":"test 1"  
}

Expected Result

You should get two notifications as the payment intent is processed.

The first one with the payment intent pending.

{ "paymentIntentId": "c435d1fb-82b8-4ed9-8aee-535996fe5e01", "customOrderId": "test 1", "amountFrom": 1334.52, "amountTo": 132, "currencyFrom": "XRP", "currencyTo": "USD", "status": "Pending", "receivedAmount": null, "executedAmountTo": 132, "executedCurrencyTo": null, "statusDescription": null, "address": "okwKBxzZWygcCPNO2QTu8G6dIuv9WfzZu1D9C2Os", "networkCode": "XRP_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": null, "sourceAddress": null, "notificationType": "PaymentIntentNotification" }

since "receivedAmount": null means no mock deposit is send for this payment intent, after the 30 seconds from the creation of this payment intent is elapsed, it fails and sends a notification for this.

{ "paymentIntentId": "c435d1fb-82b8-4ed9-8aee-535996fe5e01", "customOrderId": "test 1", "amountFrom": 1334.52, "amountTo": 132, "currencyFrom": "XRP", "currencyTo": "USD", "status": "Failed", "receivedAmount": null, "executedAmountTo": 132, "executedCurrencyTo": null, "statusDescription": "Out of time", "address": "okwKBxzZWygcCPNO2QTu8G6dIuv9WfzZu1D9C2Os", "networkCode": "XRP_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": null, "sourceAddress": null, "notificationType": "PaymentIntentNotification" }

Flow 8

Refund

In case deposit amount by the payment intent is more than zero, and it has a status "ManualActionRequired", it is possible to emulate processing a crypto refund and return the deposited funds back.

Two endpoints are used to emulate the flow.

  1. Payment intent refund fee estimate.
  2. Payment intent refund execution.

1.HTTP Request

[POST] /v1/payment-intents/{paymentIntentId}/crypto-refunds/fee where {paymentIntentID} is the ID of a payment intent you want to refund.

Expected Response

{  
  "amount" : 80.00,  
  "feeAmount"  : 10.00,  
  "totalAmount"  : 90.00  
}

Expected Result

No notification is sent on this step.

2.HTTP Request

[POST] /v1/payment-intents/{paymentIntentId}/crypto-refunds where {paymentIntentID}` is the ID of a payment intent to manually retry.

Expected Result

On the second step, refund is executed, and the deposit amount gets sent to the address it was sent from, minus the fee.

Three notifications should be sent on this step.

The first one notifies about the processing refund.

{ "paymentIntentId": "470d0f71-6c7f-455f-a742-064992af8781", "cryptoRefundPaymentIntentId": "4c438cc0-422c-4d90-ab2a-688bb78f6f0b", "customOrderId": "test 1", "amount": 100, "feeAmount": 10, "currency": "USDT", "destinationAddress": "sdfsd", "destinationAdditionalAddress": "", "networkCode": "BNB_TEST", "status": "ProcessingRefund", "externalTransactionId": null, "statusDescription": null, "notificationType": "CryptoRefundPaymentIntentNotification" }

The second notification is sent when the refund has been successfully withdrawn to the source address.

{ "paymentIntentId": "470d0f71-6c7f-455f-a742-064992af8781", "cryptoRefundPaymentIntentId": "4c438cc0-422c-4d90-ab2a-688bb78f6f0b", "customOrderId": "test 1", "amount": 100, "feeAmount": 10, "currency": "USDT", "destinationAddress": "sdfsd", "destinationAdditionalAddress": "", "networkCode": "BNB_TEST", "status": "Completed", "externalTransactionId": null, "statusDescription": null, "notificationType": "CryptoRefundPaymentIntentNotification", }

The third notification is sent when the initial payment intent status is changed to "ManuallyCompletedWithRefund".

{ "paymentIntentId": "470d0f71-6c7f-455f-a742-064992af8781", "customOrderId": "test 1", "amountFrom": 132, "amountTo": 132, "currencyFrom": "USDT", "currencyTo": "USD", "status": "ManuallyCompletedWithRefund", "receivedAmount": 100, "executedAmountTo": 100, "executedCurrencyTo": "USDT", "statusDescription": "Invalid amount: Less than expected", "address": "F2uCZbiEXadqm1L79aRkRjTKPP7JuVGsFYQKbbIV", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": "1bv12qcs8ihsrlnszs2gyik4jbizze", "sourceAddress": "Vyiq1dF0xp", "notificationType": "PaymentIntentNotification" }

Flow 9

Retry

In case deposit amount by the payment intent is more than zero, it has a status "ManualActionRequired" and conversion is enabled, it is possible to emulate processing a retry.

Retry flow wiil process this payment intent with the actual amount deposited.

Two endpoints are used to emulate the flow

1.Manual payment intent retry quote request. 2.Manual payment intent retry execution.

1.HTTP Request

[POST] /v1/payment-intents/{paymentIntentId}/retry/request-for-quotewhere {paymentIntentID} is the ID of a payment intent to manually retry.

Expected Response

{  
  "currencyFrom": "USDT",  
  "amountFrom": 90,  
  "currencyTo": "USD",  
  "amountTo": 90,  
  "quoteValidTo": "2023-11-01T10:40:10.840Z"  
}

Expected Result

Requesting the quote for the payment intent manual retry is a required step.

It will initiate the manual payment retry, and put it in Pending status until the second step is completed.

Notification regarding that should be sent.

{ "paymentIntentId": "b11c532e-a552-437f-8fe5-1e8a837126b3", "retryPaymentIntentId": "21c4ad2a-1a07-4b15-ae7e-589f256c6c50", "customOrderId": "test 1", "amountFrom": 90, "amountTo": 90, "currencyFrom": "USDT", "currencyTo": "USD", "quoteValidTo": "2024-02-01T17:23:53.5312917Z", "status": "Pending", "notificationType": "RetryPaymentIntentNotification" }

2.HTTP Request

[POST] /v1/payment-intents/{paymentIntentId}/retrywhere {paymentIntentID} is the ID of a payment intent to manually retry.

Expected Result

On the second step, manual retry is executed, and payment intent gets processed with the actual deposit amount, regardless of the initial requested one.

Two notifications should be sent on this step.

The first one notifies about the completed retry payment intent.

{ "paymentIntentId": "b11c532e-a552-437f-8fe5-1e8a837126b3", "retryPaymentIntentId": "21c4ad2a-1a07-4b15-ae7e-589f256c6c50", "customOrderId": "test 1", "amountFrom": 90, "amountTo": 90, "currencyFrom": "USDT", "currencyTo": "USD", "quoteValidTo": "2024-02-01T17:23:53.531291Z", "status": "Completed", "notificationType": "RetryPaymentIntentNotification" }

In case of customer currency conversion, an additional PaymentIntentMerchantConversion notification will be sent.

{ "merchantConversionId": "6dd8d03d-0c01-4560-892d-24f3efb9453b", "paymentIntentId": "e0c2f97c-48f7-4c31-883d-2e2621b88592", "amountFrom": 72, "amountTo": 0.02650896, "currencyFrom": "USDT", "currencyTo": "ETH", "status": "Completed", "failureReason": null, "notificationType": "PaymentIntentMerchantConversionNotification" }

The second notification is sent when the initial payment intent status is changed to "ManuallyCompletedWithRetry".

{ "paymentIntentId": "b11c532e-a552-437f-8fe5-1e8a837126b3", "customOrderId": "test 1", "amountFrom": 132, "amountTo": 132, "currencyFrom": "USDT", "currencyTo": "USD", "status": "ManuallyCompletedWithRetry", "receivedAmount": 100, "executedAmountTo": 90, "executedCurrencyTo": "USD", "statusDescription": "Invalid amount: Less than expected", "address": "b4R6rWXQn8fqpMD5LOXkPu90iCilwvHRGuE55fw0", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": "a0aone30w9vicfb9jk2fn1jvd6g59x", "sourceAddress": "gbOsgDPwfV", "notificationType": "PaymentIntentNotification" }

Flow 10

Accept recieved amount

Any deposited amount more than 0(zero) can be manually accepted for the payment intent with "ManualActionRequired" status.

HTTP Request

[POST] /v1/payment-intents/{paymentIntentId}/manually-completed where {paymentIntentID} is the ID of a payment intent to manually complete.

Expected Response

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "createdOn": "2024-03-13T09:33:53.712Z",
  "customOrderId": "string",
  "callbackUrl": "string",
  "amountFrom": 0,
  "amountTo": 0,
  "currencyFrom": "string",
  "currencyTo": "string",
  "status": "string",
  "receivedAmount": 0,
  "executedAmountTo": 0,
  "executedCurrencyTo": "string",
  "statusDescription": "string",
  "address": "string",
  "networkCode": "string",
  "additionalAddress": "string",
  "processingFeeAmount": 0,
  "processingFeeCurrency": "string",
  "originTransactionId": 0,
  "transactionHash": "string",
  "sourceAddress": "string",
  "accountId": "string",
  "retryPaymentIntents": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "createdOn": "2024-03-13T09:33:53.712Z",
      "type": "string",
      "amountFrom": 0,
      "amountTo": 0,
      "quoteValidTo": "2024-03-13T09:33:53.712Z",
      "status": "string",
      "failureReason": "string",
      "address": "string",
      "additionalAddress": "string",
      "networkCode": "string",
      "feeAmount": 0,
      "externalTransactionId": "string"
    }
  ],
  "customConversion": {
    "id": "string",
    "currencyTo": "string",
    "amountTo": 0,
    "processingFeeAmount": 0,
    "processingFeeCurrency": "string",
    "status": "string",
    "failureReason": "string"
  }
}

Expected Result

The deposited amount is manually accepted for the payment intent, and its status changes to "ManuallyCompletedAmountAcceptable".

Notification is sent once the payment intent status updates.

{ "paymentIntentId": "303e492d-1cde-4625-bd45-372a38bd92a1", "customOrderId": "test 1", "amountFrom": 132, "amountTo": 132, "currencyFrom": "USDT", "currencyTo": "USD", "status": "ManuallyCompletedAmountAcceptable", "receivedAmount": 100, "executedAmountTo": 132, "executedCurrencyTo": null, "statusDescription": "Invalid amount: Less than expected", "address": "jg2BYq1G7PsjWHCXBuPfzmKbKFTzHSJOxW9Me55T", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": "yglcgkkninm3cq1h55rc79ydxi7el7", "sourceAddress": "IBe17lGkHh", "notificationType": "PaymentIntentNotification" }

Flow 11

Underpaid payment intent top-up

HTTP Request
POST /v2/payment-intents/

Request Body

{  
  "currencyFrom": "ADA",  
  "currencyTo": "USD",  
  "amountTo": 100,  
  "networkCode": "ADA_TEST",  
  "customOrderId": "test 1",  
  "callbackUrl": "https://webhook.site/e3f6bc53-f711-456d-85cb-a8cc3f9d27e"  
}

Expected Response

{  
  "paymentIntentId": "8d6f8bad-e00f-405d-897f-45a8e5896770"   
  "currencyFrom": "ADA",  
  "amountFrom": 200,  
  "currencyTo": "USD",  
  "amountTo": 100,  
  "address": "EVnabLyYuXmINTMrRAsantpIyIHrSR0O1EC8Ugv0",  
  "additionalAddress": "string",  
  "additionalAddressType": "string",  
  "quoteValidTo": "2024-01-01T10:40:10.840Z",  
  "customOrderId":"test 1"  
}

Expected Result in case of a successful top-up flow

In this Sandbox flow we simulate the situation, where:

ADA to USD exchange rate is assumed to be 2 to 1 in this example, so 200 ADA=100 USD.

The following notifications are sent for that flow.

The first one with the payment intent pending.

{ "paymentIntentId": "8d6f8bad-e00f-405d-897f-45a8e5896770", "customOrderId": "test 1", "amountFrom": 200, "amountTo": 100, "currencyFrom": "ADA", "currencyTo": "USD", "status": "Pending", "receivedAmount": null, "executedAmountTo": 100, "executedCurrencyTo": null, "statusDescription": null, "address": "EVnabLyYuXmINTMrRAsantpIyIHrSR0O1EC8Ugv0", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": null, "sourceAddress": null, "notificationType": "PaymentIntentNotification" }

The first deposit of 100 ADA(=50 USD) is sent. As the first deposit amount is not equal to the amount requested(200 ADA=100 USD), which fails the initial payment intent, and doesn't satisfy the threshold, the automatic retry payment intent is initiated and fails.

{ "paymentIntentId": "8d6f8bad-e00f-405d-897f-45a8e5896770", "retryPaymentIntentId": "f217d6b2-98d8-428a-bf21-fa2800aff282", "customOrderId": "test 1", "amountFrom": 100, "amountTo": 50, "currencyFrom": "ADA", "currencyTo": "USD", "status": "Failed", "notificationType": "AutoRetryPaymentIntentNotification" }

After the auto retry has failed, the initial payment intent is completed with "Manual action required" status, and the following notification is sent.

{ "paymentIntentId": "8d6f8bad-e00f-405d-897f-45a8e5896770", "customOrderId": "test 1", "amountFrom": 200, "amountTo": 100, "currencyFrom": "ADA", "currencyTo": "USD", "status": "ManualActionRequired", "receivedAmount": 100, "executedAmountTo": 100, "executedCurrencyTo": null, "statusDescription": "Invalid amount: Less than expected", "address": "EVnabLyYuXmINTMrRAsantpIyIHrSR0O1EC8Ugv0", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": "x8e2veduhrlnc36n4mlddqkz5tnikb", "sourceAddress": "lUROvAjmN2", "notificationType": "PaymentIntentNotification" }

The second deposit of 100 ADA(=50 USD) is sent for the same payment request.

As the sum of the first and second deposit (100 ADA+100 ADA=200 ADA=100 USD) satisfies the initial payment request of 100 USD, the automatic retry payment intent is initiated and completes successfully.

{ "paymentIntentId": "8d6f8bad-e00f-405d-897f-45a8e5896770", "retryPaymentIntentId": "f217d6b2-98d8-428a-bf21-fa2800aff282", "customOrderId": "test 1", "amountFrom": 200, "amountTo": 100, "currencyFrom": "ADA", "currencyTo": "USD", "status": "Completed", "notificationType": "AutoRetryPaymentIntentNotification" }

After the auto retry is successfully completed, the initial payment intent is completed with "Partially completed" status, and the following notification is sent.

{ "paymentIntentId": "8d6f8bad-e00f-405d-897f-45a8e5896770", "customOrderId": "test 1", "amountFrom": 200, "amountTo": 100, "currencyFrom": "ADA", "currencyTo": "USD", "status": "PartiallyCompleted", "receivedAmount": 200, "executedAmountTo": 100, "executedCurrencyTo": "USD", "statusDescription": "Invalid amount: Less than expected", "address": "EVnabLyYuXmINTMrRAsantpIyIHrSR0O1EC8Ugv0", "networkCode": "BNB_TEST", "additionalAddress": "", "originTransactionId": null, "transactionHash": "zo8n4xw52c7tuc903k2csbulx9mex9", "sourceAddress": "lUROvAjmN2", "notificationType": "PaymentIntentNotification" }

Expected Result in case of a failed top-up flow

In this Sandbox flow we simulate the situation, where:

ADA to USD exchange rate is assumed to be 2 to 1 in this example, so 200 ADA=100 USD.

In this case consecutive deposits won't change the "Manual action required" status of a payment intent, as the sum of deposits by the payment intent wil still exceed both the payment intent required amount and the threshold, and further manual action will be required:

Executing the flow via iframe

  1. Create payment intent for 100 USD.
  2. Choose coin ADA and network ADA_TEST.

Payment intent

Payment intent is a request for a deposit of a certain amount and currency on Crypto PayX customer's wallet. Crypto PayX customers can deposit crypto to their account and accept deposits from others via payment intents. Payment intents can be payed in a currency different from the currency customer wants to deposit on their account. In that case the deposit equvalent is requested and converted automatically.

There are two ways of creating and processing a payment intent:

  1. Via iframe generated for the particular payment intent.
  2. Via API.
  3. Without the need of integration, by payment request link.

Payment intent fees

Each payment intent has a percentage-based and fixed processing fees. To know the exact amount of processing fees, please contact us.

If multiple deposits are made per payment intent, the sum of processing fees will be charged for each deposit.

If the amount sent by the payment intent is equal to or less than the processing fees sum, it will be spent on paying these fees, and no amount will be deposited per the payment intent.

If the payment intent amount is equal to or less than processing fees sum, its creation will not be possible, and an error will be returned in response.

Single payment intent address

By default, a separate crypto address is generated per each payment intent. In some cases, where this can be problematic, Crypto PayX can enable single payment intent address by customer request.

Single payment intent address flow allows Crypto PayX customers to use a single permanent crypto address for multiple payment intents per one Account ID.

If single address flow is enabled for the customer, Crypto PayX will recognise multiple deposits to the address and associate each of them with the appropriate payment intents by account ID.

Account ID needs to be passed as accountId parameter when creating a payment intent using the following endpoints.

If Account ID will not be added when creating a payment intent request, single payment intent address flow will not be applied, regardless of single address settings for the customer. Please check your integration to ensure it complies with this requirement.

Payment intent statuses grid

Flow # Payment intent condition Threshold Conversion settings Old status (obsolete from 15.02.24) Current status Available manual actions Сomment
Is initiated and awaits deposit n/a n/a Pending Pending n/a
Transaction is received and being processed n/a n/a n/a Processing n/a
1 Received amount is equal to expected amount Satisfied n/a Completed Completed n/a
2 Received amount is more or less than expected amount Satisfied n/a Partially completed Partially completed n/a
3 Received amount is more or less than expected amount Not satisfied Conversion disabled for account or deposit currency Partially completed Manual action required Refund, Accept recieved amount, Underpaid payment intent top-up
4 Received amount more or less than expected amount Not satisfied Conversion enabled Failed Manual action required Refund, Retry, Accept recieved amount, Underpaid payment intent top-up
5 Received amount more or less than expected amount 0% Conversion disabled for account or deposit currency Partially completed Manual action required Refund, Accept recieved amount, Underpaid payment intent top-up
6 Received amount more or less than expected amount 0% Conversion disabled for account or deposit currency Failed Manual action required Refund, Retry, Accept recieved amount, Underpaid payment intent top-up
7 No funds were received within 30 seconds validity timeframe n/a n/a Failed Failed n/a If the deposit will be received after the time limit, and the deposit sum satisfies payment intent threshold requirements, payment intent status will change to Completed
8.Refund Deposit is greater than 0, payment intent is in "Manual action required" status n/a n/a n/a Manually completed with Refund n/a Payment intent ID status will be changed.
9.Retry Deposit is greater than 0, payment intent is in "Manual action required" status n/a Conversion enabled n/a Manually completed with Retry n/a Payment intent ID status will be changed.
10.Accept recieved amount Deposit is greater than 0, payment intent is in "Manual action required" status n/a n/a n/a Manually completed. Accepted received amount n/a Payment intent ID status will be changed.
11.Underpaid payment intent top-up Underpaid payment intent top-up, two separate deposits Not satisfied after first deposit, satisfied after second deposit. n/a n/a Partially completed n/a Functionality description,Top-up flow

All of the possible payment intent flows, as well as the way to test them in Crypto Payx Sandbox, are described in more detail in Possible payment intent flows

Non-completed payment intent status descriptions

If the initial payment intent has not been completed, the reason for it is stated in the "statusDescription" field of the payment intent notification.

Status name Description
"Out of time" No deposit was made within the specified timeframe.
"Out of money" Deposit was made during large fluctuations in deposit currency market price, making it impossible to complete it.
"Invalid amount: Less than expected" Deposit amount is Less than expected and is lower than the payment intent threshold, if applicable.
"Invalid amount: More than expected" Deposit amount is more than expected and is higher than the payment intent threshold, if applicable.
"Server Error" Error on Crypto PayX side. Please contact us for further assistance.

Payment intent via iframe

See Payment intent via iframe endpoints.

Payment intent via API

It is possible to create a payment intent using API.

Customers can request a quote for a specific pair and amount, and create a payment intent using the endpoints. In response to a successful payment intent creation, customers get a crypto deposit address.

Auto-retry and notifications functionality work as usual for payment intents created using API.

See API payment intent endpoints.

We now give customers the possibility to generate the link to Crypto PayX payment with all the requisites filled. This link can be distributed to customers clients, so that clients can pay in a streamlined manner, without the need to authorize on Crypto PayX.

Payment link will be active for 5(five) days after it has been generated.

To generate a payment link, customer needs to click on Create a payment link. Button can be accessed either to the left, below the account funds details, or in the right top corner of Crypto PayX tab.

Create payment link

After clicking the button, customers will see Payment request popup, where they can add the details of the payment they will request using the link.

Payment request popup

Popup contains the following fields:

After entering the needed data, customers click Create a payment link button, which will generate the payment link with the provided details and copy to customers clipboard. Now customers can share the link to request a payment with the specified details. Payment link is active for 5(five) days after it has been generated. Those who receive the payment request link(requestees) and open it will see the payment request page.

Payment request page

On this page it is possible to choose the coin and network of the cryptocurrency that will be sent for this payment request.

After the requestee fills all the fields, they click Continue and go to the next page, where they see all the details, including active quote, wallet address and the amount they need to send to this address.

Requestee can see the status of their deposit on the payment request page in real time.

Customers can see statuses for the payment they requested in payment history grid on Crypto PayX tab.

Payment history grid

in case of:

We will display "page not found" to Crypto PayX customers and payment link requestees.

Page not found

Failed payment intent handling

In case of initial payment intent failure, and the deposit sum being greater than 0(zero), failed payment intent can be:

Payment intent threshold

By default, the amount of cryptocurrency deposited for the payment intent needs to be the equal to the request, to the decimals. If the deposited amount is not equal to the requested amount, payment intent status becomes failed, and further actions are needed to successfully complete it.

Threshold is a percentage of deviation from the requested fiat sum, which allows such payment intents to be processed automatically, minimizing manual handling from merchant's side. In case of a successful auto retry, no further action is required from them.

For example, if the threshold for the merchant is 2%, and fiat amount of the payment intent is 100 USD, deposits for this payment intent, equivalent to the range from 98 USD to 102 USD will be processed automatically, in case the deposit sum is not equal to the requested cryptocurrency amount and the initial payment intent is failed.

The new quote will be calculated for the automatic retry of the payment request, with the conversion rate valid at the time the automatic retry is initiated.

Payment intent manual retry

In case of payment intent retry, you need to first request for the actual quote of the retry, and if you agree with the quote, execute the retry payment intent by the date, given by the "quoteValidTo" field in the quote request response.

See Retry OTC for Payment intent for the endpoints to retry failed initial payment intent.

Refund failed payment intent

To refund failed payment intent, you first request the currency of payment intent. Refunds can be made only in the currency in which the deposit for the payment intent was made. Then calculate fee for the refund and create a refund payment intent.

See Create crypto refund for the endpoints to refund failed initial payment intent.

It is also possible to initiate a refund with UI on Crypto PayX platform.

Underpaid payment intent top-up

It is possible to add funds to the existing payment intent in case the requested sum wasn’t deposited the first time.

One or more deposits after the initial underpaid deposit are possible per payment intent until it:

Once the sum of deposits amount satisfies the requirements of payment intent it will be processed with autoretry, with the usual payment request flow.

Underpaid payment intent top-up is available both for Sandbox and real Crypto PayX account. See How to test top-up flow on Sandbox for more info.

Conversion rules for the payment intent

We are able to customize payment intent conversion rules individually. Please contact us to implement the specific configuration you need.

The following conversion settings are available:

You can also select the exceptions – one or more cryptocurrencies, deposits in which will not be converted, and will stay in the cryptocurrency they were deposited in.

Disable conversion for payment intent

In case there's no need to convert crypto funds, deposited for the payment intent, please contact us, and we disable the default conversion rules for your account.

In the case conversion is disabled, the payment intent flow will be as following:

Manual handling will be required only for cases where refund option is available.

Virtual fiat currencies

We have added a list of the following virtual fiat currencies:

Adding these currencies gives merchant the possibility to give payment intent quote using them, e.g "in order to get the equivalent of AED 200, deposit X amount of ETH."

The following scenarios are available for the merchant:

Contact us to setup the scenario that will optimally suit your needs.

Payment intent Endpoints

Payment intent via API endpoints

List all networks and coins available for payment intent

HTTP Request

[GET] v1/currencies

Successful Response

[
  {
    "fiatCurrency": "string",
    "isVirtual": false,
    "fiatCurrencyName": "string",
    "coins": [
      {
        "coin": "string",
        "name": "string",
        "coinNetworks": [
          {
            "addressType": "Single",
            "networkCode": "string",
            "networkName": "string",
            "order": 0
          }
        ]
      }
    ]
  }
]

Response Fields

Name Type Description
fiatCurrency string Acronym of fiat currency.
isVirtual boolean Is the currency listed a virtual fiat currency. true only for virtual fiat currencies. See Virtual fiat currencies for more info.
fiatCurrencyName string Name of fiat currency.
coin string Acronym of cryptocurrency.
name string Name of cryptocurrency.
addressType AddressType Type of address, based on crypto network. Can be: Single, Multiple, MultipleWithTag, MultipleWithMemo, MultipleWithNote.
networkCode string Code of network.
networkName string Name of network.

Request a quote for the payment intent

HTTP Request

POST /v2/payment-intents/estimated-quote

Request Body Example

{
  "currencyFrom": "string",
  "amountTo": 0,
  "currencyTo": "string"
}

Parameters

Name Type Required Description
currencyFrom string + Acronym of the currency to convert FROM.
amountTo number($decimal) + Amount of the currency to convert TO.
currencyTo string + Acronym of the currency to convert TO.

Successful Response

{
  "currencyFrom": "string",
  "amountFrom": 0,
  "currencyTo": "string",
  "amountTo": 0
}

Create a payment intent via API

HTTP Request

POST /v2/payment-intents/

Request Body Example

{
  "currencyFrom": "string",
  "currencyTo": "string",
  "amountTo": 0,
  "networkCode": "string",
  "customOrderId": "string",
  "accountId": "string",
  "callbackUrl": "string"
}

Parameters

Name Type Required Description
currencyFrom string + Acronym of the currency to convert FROM.
amountTo number($decimal) + Amount of the currency to convert TO.
currencyTo string + Acronym of the currency to convert TO.
networkCode string Code of the network.
customOrderId string Unique internal order ID in customer's system.
accountId string Required for Single payment intent address. Internal account ID in customer's system.
callbackUrl string Callback URL to track status changes via notifications.

Successful Response

{
  "paymentIntentId": "f7d6bb02-b399-40ef-9127-676d4db21861" 
  "currencyFrom": "string",
  "amountFrom": 0,
  "currencyTo": "string",
  "amountTo": 0,
  "address": "string",
  "additionalAddress": "string",
  "additionalAddressType": "string",
  "quoteValidTo": "2023-11-01T10:40:10.840Z",
  "customOrderId":"string"
}

Response Fields

Name Type Description
paymentIntentId string($uuid) ID of the payment made by customer's client.
currencyFrom string Acronym of the currency to convert FROM.
amountFrom number($decimal) Amount of the currency to convert FROM.
currencyTo string Acronym of the currency to convert TO.
amountTo number($decimal) Amount of the currency to convert TO.
address string Wallet address.
additionalAddress string Additional wallet address.
additionalAddressType string Additional address info of network, if applicable. Used for TAG, MEMO and NOTE of the network.
quoteValidTo string Time, to which the payment intent quote is valid.
customOrderId string Unique internal order ID in customer's system.

Payment intent via iframe endpoints

Initiate a payment intent

Payment intent is initiated when customer requests exchange, selecting Crypto Pay as a PSP. Amount and Currency are passed as a parameters to the endpoint.

HTTP Request

POST /v1/payment-intents/

Request Body Example

{
  "currency": "string",
  "amount": 0,
  "customOrderId": "string",
  "accountId": "string",
  "callbackUrl": "string"
}

Parameters

Name Type Required Description
currency string + Acronym of currency.
amount number(decimal) + Amount of currency.
customOrderId string Unique internal order ID in customer's system.
accountId string Required for Single payment intent address. Internal account ID in customer's system.
callbackUrl string Callback URL to track status changes via notifications.

Successful Response

URL to Crypto Pay iframe for the specific client's payment. Format: https://payment.cryptopayx.tech/deposit?currencyTo=USD&amountTo=100&paymentIntentId=988a2d89-2655-4641-b368-72fe802f6731&merchantId={merchantId}&token={token} .

Check payment intent status

Use this endpoint to check payment intent status by payment intent ID. Includes detailed info on failure reasons for the retry payment intent and custom conversion settings, if applicable for the account.

HTTP Request

GET v1/payment-intents/{paymentIntentId}

Parameters

Name Type Required Description
paymentIntentId string($uuid) + ID of the payment intent made by customer's client.

Successful Response

[
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "customOrderId": "string",
  "accountId": "string",
  "callbackUrl": "string",
  "amountFrom": 0,
  "amountTo": 0,
  "currencyFrom": "string",
  "currencyTo": "string",
  "executedAmountTo": 0,
  "executedCurrencyTo": "string",
  "status": "string",
  "receivedAmount": 0,
  "statusDescription": "string",
  "address": "string",
  "networkCode": "string",
  "additionalAddress": "string",
  "originTransactionId": "string",
  "transactionHash": "18d0f8fb499a571ae88ff257d43071648d0661bf4fbf0cda3cc8bf9c603aac72",
  "sourceAddress": "string",
  "processingFeeAmount": 0.98100000,
  "processingFeeCurrency": "USD",
  "retryPaymentIntents": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "type": "string",
      "currencyFrom": "string",
      "amountFrom": 0,
      "currencyTo": "string",
      "amountTo": 0,
      "quoteValidTo": "2023-12-01T08:59:02.292Z",
      "status": "string",
      "failureReason": "string",
      "address": "string",
      "additionalAddress": "string",
      "networkCode": "string",
      "feeAmount": 0,
      "externalTransactionId": "string"
    }
  ],
  "customConversion": {
    "id": "string",
    "currencyTo": "string",
    "amountTo": 0,
    "processingFeeAmount": 0,
    "processingFeeCurrency": "string",
    "status": "string",
    "failureReason": "string"
  }
}

Response Fields

Name Type Description
Id string($uuid) ID of the payment.
customOrderId string Unique internal order ID in customer's system.
accountId string Internal account ID in customer's system.
callbackUrl string Callback URL to track status changes via notifications.
amountFrom number($decimal) Amount of the currency to convert FROM.
amountTo number($decimal) Amount of the currency to convert TO.
currencyFrom string Acronym of the currency to convert FROM.
currencyTo string Acronym of the currency to convert TO.
executedAmountTo number($decimal) The actual amount customer gets with custom configuration and retry policy applied.
executedCurrencyTo string The actual currency customer gets with custom configuration and retry policy applied.
status string Status of payment at the moment of response. See Payment intent statuses for more info.
receivedAmount number($decimal) Resulting amount received to the wallet address.
statusDescription string The reason of payment failure, empty if the payment is not failed. See Failed payment intent statuses for more info.
address string Wallet address.
networkCode string Code of the network.
additionalAddress string Additional address info of network, if applicable. Used for TAG, MEMO and NOTE of the network.
originTransactionId string ID of a transaction within the internal system. Applied for internal transactions instead of transaction hash.
transactionHash string Unique identifier of a transaction in a blockchain.
sourceAddress string The address, from where the funds were withdrawn for the payment intent.
processingFeeAmount number($decimal) Payment intent transaction processing fee amount.
processingFeeCurrency string Payment intent transaction processing fee currency.

Response Fields for "retryPaymentIntents"

Name Type Description
Id string($uuid) ID of the payment.
currencyFrom string Acronym of the currency to convert FROM.
amountFrom number($decimal) Amount of the currency to convert FROM.
currencyTo string Acronym of the currency to convert TO.
amountTo number($decimal) Amount of the currency to convert TO.
quoteValidTo string Time, to which the retry payment intent quote is valid.
status string Status of payment intent retry at the moment of response. See Retry payment intent statuses for more info.
failureReason string The reason of payment intent retry failure, empty if the payment is not failed. Failed payment intent statuses for more info.
address string Wallet address.
additionalAddress string Additional address info of network, if applicable. Used for TAG, MEMO and NOTE of the network.
networkCode string Code of the network.
feeAmount number($decimal) Fee amount.
externalTransactionId string($uuid) ID of the external transaction in PSP.

Response Fields for "customConversion"

Name Type Description
Id string($uuid) ID of the custom conversion settings.
currencyTo string Acronym of the currency to convert TO.
amountTo number($decimal) Amount of the currency to convert TO.
processingFeeAmount number($decimal) Fee amount.
processingFeeCurrency string Fee amount.
status string Status of conversion at the moment of response.
failureReason string The reason of custom conversion failure.

Search payment intent by Account ID, Custom Order ID

Use this endpoint to search and filter payment intents by:

If multiple parameters for filtering are selected, response will return only the items, which satisfy ALL the parameters.

Items in response are sorted by date, newer on top.

HTTP Request

POST v1/payment-intents/search

Request Body Example

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "customOrderId": "string",
  "accountId": "string",
  "createdDateFrom": "2024-02-23T12:50:24.833Z",
  "createdDateTo": "2024-02-23T12:50:24.833Z",
  "skip": 0,
  "take": 0
}

Parameters

Name Type Required Description
id string Exact ID of a payment intent.
customOrderId string Unique internal order ID in customer's system.
accountId string Internal account ID in customer's system.
createdDateFrom string(dateTtime) Start date the payment intent was initiated.
createdDateTo string(dateTtime) End date the payment intent was initiated.
skip int The number of items to skip in the response. If the value is 500 ,the response will return the items, starting from 501.
take int The amount of items returned in response. Max value is 500.

Successful Response

[
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "createdOn": "2024-02-23T14:02:11.195Z",
  "customOrderId": "string",
  "amountFrom": 0,
  "amountTo": 0,
  "currencyFrom": "string",
  "currencyTo": "string",
  "status": "string",
  "receivedAmount": 0,
  "executedAmountTo": 0,
  "executedCurrencyTo": "string",
  "statusDescription": "string",
  "address": "string",
  "networkCode": "string",
  "additionalAddress": "string",
  "processingFeeAmount": 0,
  "processingFeeCurrency": "string",
  "originTransactionId": 0,
  "transactionHash": "string",
  "sourceAddress": "string",
  "accountId": "string",
  "callbackUrl": "string"
  "retryPaymentIntents": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "createdOn": "2024-02-23T14:02:11.195Z",
      "type": "string",
      "amountFrom": 0,
      "amountTo": 0,
      "quoteValidTo": "2024-02-23T14:02:11.196Z",
      "status": "string",
      "failureReason": "string",
      "address": "string",
      "additionalAddress": "string",
      "networkCode": "string",
      "feeAmount": 0,
      "externalTransactionId": "string"
    }
  ],
  "customConversion": {
    "id": "string",
    "currencyTo": "string",
    "amountTo": 0,
    "processingFeeAmount": 0,
    "processingFeeCurrency": "string",
    "status": "string",
    "failureReason": "string"
  }
}

Response Fields

Name Type Description
Id string($uuid) ID of the payment.
customOrderId string Internal order ID in customer's system.
accountId string Internal account ID in customer's system.
callbackUrl string Callback URL to track status changes via notifications.
amountFrom number($decimal) Amount of the currency to convert FROM.
amountTo number($decimal) Amount of the currency to convert TO.
currencyFrom string Acronym of the currency to convert FROM.
currencyTo string Acronym of the currency to convert TO.
executedAmountTo number($decimal) The actual amount customer gets with custom configuration and retry policy applied.
executedCurrencyTo string The actual currency customer gets with custom configuration and retry policy applied.
status string Status of payment at the moment of response. See Payment intent statuses for more info.
receivedAmount number($decimal) Resulting amount received to the wallet address.
statusDescription string The reason of payment failure, empty if the payment is not failed. See Failed payment intent statuses for more info.
address string Wallet address.
networkCode string Code of the network.
additionalAddress string Additional address info of network, if applicable. Used for TAG, MEMO and NOTE of the network.
originTransactionId string ID of a transaction within the internal system. Applied for internal transactions instead of transaction hash.
transactionHash string Unique identifier of a transaction in a blockchain.
sourceAddress string The address, from where the funds were withdrawn for the payment intent.
processingFeeAmount number($decimal) Payment intent transaction processing fee amount.
processingFeeCurrency string Payment intent transaction processing fee currency.

Response Fields for "retryPaymentIntents"

Name Type Description
Id string($uuid) ID of the payment.
currencyFrom string Acronym of the currency to convert FROM.
amountTo number($decimal) Amount of the currency to convert TO.
quoteValidTo string Time, to which the retry payment intent quote is valid.
status string Status of payment intent retry at the moment of response. See Retry payment intent statuses for more info.
failureReason string The reason of payment intent retry failure, empty if the payment is not failed. Failed payment intent statuses for more info.
address string Wallet address.
additionalAddress string Additional address info of network, if applicable. Used for TAG, MEMO and NOTE of the network.
networkCode string Code of the network.
feeAmount number($decimal) Fee amount.
externalTransactionId string($uuid) ID of the external transaction in PSP.

Response Fields for "customConversion"

Name Type Description
Id string($uuid) ID of the custom conversion settings.
currencyTo string Acronym of the currency to convert TO.
amountTo number($decimal) Amount of the currency to convert TO.
processingFeeAmount number($decimal) Fee amount.
processingFeeCurrency string Fee amount.
status string Status of conversion at the moment of response.
failureReason string The reason of custom conversion failure.

Retry OTC for Payment intent

If the initial payment intent has "status" : "failed" and "receivedAmount" is greater than 0, Crypto Pay gives a possibility to retry it. Use the endpoints below to request a current quote for the retry transaction and execute it.

Request quote for the retry transaction

Use this endpoint to request a current quote for the retry transaction by payment intent ID.

HTTP Request

[POST] /v1/payment-intents/{paymentIntentId}/retry/request-for-quote

Parameters

Name Type Required Description
paymentIntentId string($uuid) + Unique ID of the payment intent made by customer.

Successful Response

{
  "currencyFrom": "BTC",
  "currencyTo": "USD",
  "amountFrom": 1.00,
  "amountTo": 30000
}

Response Fields

Name Type Description
currencyFrom string Acronym of the currency to convert FROM.
currencyTo string Acronym of the currency to convert TO.
amountFrom number($decimal) Amount of the currency to convert FROM.
amountTo number($decimal) Amount of the currency to convert TO.

Execute the retry transaction

Use this endpoint to execute the retry transaction, if you agree with the current quote.

HTTP Request

[POST] /v1/payment-intents/{paymentIntentId}/retry

Parameters

Name Type Required Description
paymentIntentId string($uuid) + Unique ID of the payment intent made by customer.

Successful Response

200 if the transaction is executed successfully.

Refund failed payment intent

Available networks for the refund

Use this endpoint to list all the networks, available for the cryptocurrency of a particular payment intent.

HTTP Request

[GET] /v1/payment-intents/{paymentIntentId}/coin-networks

Parameters

Name Type Required Description
paymentIntentId string($uuid) + ID of the payment intent made by customer.

Successful Response

{
  "coin" : "string",
  "name" : "string",
  "coinNetworks" : 
    [
      {
        "addressType": "AddressType",
        "networkCode": "string",
        "networkName": "string",
        "order": 0
      }
    ]
}

Response Fields

Name Type Description
coin string Acronym of cryptocurrency.
name string Name of cryptocurrency.
addressType AddressType Type of address, based on crypto network. Can be: Single, Multiple, MultipleWithTag, MultipleWithMemo, MultipleWithNote.
networkCode string Code of network.
networkName string Name of network.

Calculate commission fee for the crypto refund

Use this endpoint to calculate fee for the refund transaction.

HTTP Request

[POST] /v1/payment-intents/{paymentIntentId}/crypto-refunds/fee

Request Body Example

{
  "address" : "string",
  "networkCode"  : "string",
  "additionalAddress"  : "string"
}

Parameters

Name Type Required Description
paymentIntentId string($uuid) + Unique ID of the payment intent made by customer.
address string + Wallet address.
networkCode string Code of the network.
additionalAddress string Additional address info of network, if applicable. Used for TAG, MEMO and NOTE of the network.

Successful Response

{
  "amount" : 98.00,
  "feeAmount"  : 2.00,
  "totalAmount"  : 100.00
}

Response Fields

Name Type Description
amount number($decimal) Amount that will be refunded, fee deducted.
feeAmount number($decimal) Fee amount.
totalAmount number($decimal) Total amount, with fee.

Create crypto refund

HTTP Request

[POST] /v1/payment-intents/{paymentIntentId}/crypto-refunds

Request Body Example

{
    "externalTransactionId" : "string"
}

Parameters

Name Type Required Description
paymentIntentId string($uuid) + Unique ID of the payment intent made by customer.
externalTransactionId string($uuid) Unique ID of the external transaction in PSP.

Successful Response

{
  "paymentIntentId": "771c6736-f0b6-4670-97fd-ad60f67e8c29",
  "cryptoRefundPaymentIntentId": "5d2d5427-9ab9-4192-8ef7-8fa1f60b098f",
  "customOrderId": "15847474-a84a-43b4-9fa6-d95cece2d6f1",
  "amount": 0.06,
  "currency": "ETH",
  "destinationAddress": "0x08A7aeDcB87088dd8b311fD709B64e13FdAFac8a",
  "destinationAdditionalAddress": "",
  "networkCode": "ETH_GOERLI",
  "status": "ProcessingRefund", 
  "externalTransactionId": "0x08A7aeDcB87088dd8b311fD709B64e13FdAFac8a"
}

Response Fields

Name Type Description
paymentIntentId string($uuid) ID of the payment intent the refund is issued for.
cryptoRefundPaymentIntentId string($uuid) ID of the refund.
customOrderId string Unique internal order ID in customer's system.
amount number($decimal) Deposited amount.
currency string Currency of the refund.
destinationAddress string Wallet address where the refund will be sent.
additionalAddress string Additional address info, if applicable. Used for TAG, MEMO and NOTE
networkCode string Code of the network.
status string Status of refund at the moment of response. Can be Pending, if the refund is initiated, ProcessingRefund,Completed, Failed.
externalTransactionId string($uuid) ID of the external transaction in PSP.

Payout

Crypto Pay allows to withdraw fiat currency from customer's account by converting it to cryptocurrency of their choice and sending it to the wallet address they provide.

There are two ways of doing that:

  1. Via graphical user interface of the iframe generated for the particular payout.
  2. Via API.

See Payout Endpoints.

After confirmation, the payout intent is set to "Pending". Once the fiat for the payout request is converted to crypto and the crypto withdrawal transaction is created, status is set to "Processing", "transactionid" is set to the unique ID of crypto transaction. After the transaction completion, status of payout intent is set to "Completed". In case of issues preventing to complete the payment intent, its status is set to "Failed".

Notifications are sent for each payout intent's status change.

Payout with iframe

If payout intent request is valid, new payout intent is initiated. The response will contain the URL to Withdrawal iframe, with the payout intent's fiat currency and amount prefilled.

Following fields in Withdrawal iframe need to be filled manually:

Amount of the cryptocurrency after conversion, and the quote validity expiration time are shown in the iframe.

After clicking "Continue", customers will be redirected to the confirmation step, where they can: - Double-check the information entered. - See the transaction fee. - See the amount of the cryptocurrency, which will be sent to the wallet address provided.

See Payout with iframe Endpoints.

Payout with API

It is possible to create and execute a payout only using API. In that case all the parameters of the payout need to be passed with the appropriate endpoints. It is also possible to access all networks and coins available for the payout, as well as calculate a fee for the particular payout.

See Payout with API Endpoints.

Payout Endpoints

Use the endpoints below to create a payout intent.

Payout with API endpoints

Use the endpoints below to create payout intent via API.

List all networks and coins available for payout

HTTP Request

[GET] v1/currencies

Successful Response

[
  {
    "fiatCurrency": "string",
    "fiatCurrencyName": "string",
    "coins": [
      {
        "coin": "string",
        "name": "string",
        "coinNetworks": [
          {
            "addressType": "Single",
            "networkCode": "string",
            "networkName": "string",
            "order": 0
          }
        ]
      }
    ]
  }
]

Response Fields

Name Type Description
fiatCurrency string Acronym of fiat currency.
fiatCurrencyName string Name of fiat currency.
coin string Acronym of cryptocurrency.
name string Name of cryptocurrency.
addressType AddressType Type of address, based on crypto network. Can be: Single, Multiple, MultipleWithTag, MultipleWithMemo, MultipleWithNote.
networkCode string Code of network.
networkName string Name of network.

Calculate a fee for the payout

Use the endpoint below to estimate a fee for the particular payout, before creating a payout intent.

HTTP Request

[POST] v2/payout-intents/estimated-fee

Request Body Example

{
  "currencyFrom": "string",
  "amountFrom": 0,
  "currencyTo": "string",
  "networkCode": "string",
  "address": "string",
  "additionalAddress": "string"
}

Parameters

Name Type Required Description
currencyFrom string + Acronym of the currency to convert FROM.
amountFrom number($decimal) + Amount of the currency to convert FROM.
currencyTo string + Acronym of the currency to convert TO.
networkCode string + Code of the network.
address string + Wallet address.
additionalAddress string Additional address info of network, if applicable. Used for TAG, MEMO and NOTE of the network.

Successful Response

{
  "currencyFrom": "string",
  "amountFrom": 0,
  "currencyTo": "string",
  "amountTo": 0,
  "feeAmount": 0,
  "feeCurrency": "string",
  "receivedAmount": 0
}

Response Fields

Name Type Description
currencyFrom string Acronym of the currency to convert FROM.
amountFrom number($decimal) Amount of the currency to convert FROM.
currencyTo string Acronym of the currency to convert TO.
amountTo number($decimal) Amount of the currency to convert TO.
feeAmount number(decimal) Fee amount.
feeCurrency string Acronym of currency for the fee.
receivedAmount number($decimal) Resulting amount received to the wallet address.

Create payout with API

Use the endpoint below to create a payout with preselected parameters.

HTTP Request

[POST] v2/payout-intents

Request Body Example

{ "currencyFrom": "string", "amountFrom": 0, "currencyTo": "string", "networkCode": "string", "address": "string", "additionalAddress": "string", "accountId": "string", "callbackUrl": "string" }

Parameters

Name Type Required Description
currencyFrom string + Acronym of the currency to convert FROM.
amountFrom number($decimal) + Amount of the currency to convert FROM.
currencyTo string + Acronym of the currency to convert TO.
networkCode string + Code of the network.
address string + Wallet address.
additionalAddress string Additional address info of network, if applicable. Used for TAG, MEMO and NOTE of the network.
accountId string Internal account ID in customer's system.
callbackUrl string Callback URL to track status changes via notifications.

Successful Response

{
  "payoutIntentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "currencyFrom": "string",
  "amountFrom": 0,
  "currencyTo": "string",
  "amountTo": 0,
  "feeAmount": 0,
  "feeCurrency": "string",
  "receivedAmount": 0
}

Response Fields

Name Type Description
payoutIntentId string($uuid) ID of the payout.
currencyFrom string Acronym of the currency to convert FROM.
amountFrom number($decimal) Amount of the currency to convert FROM.
currencyTo string Acronym of the currency to convert TO.
amountTo number($decimal) Amount of the currency to convert TO.
feeAmount number(decimal) Fee amount.
feeCurrency string Acronym of currency for the fee.
receivedAmount number($decimal) Resulting amount received to the wallet address.

Payout with iframe endpoints

Use the endpoint below to create a payout intent with iframe link generation.

HTTP Request

[POST] /v1/payout-intents/

Request Body Example

{
  "currency": "string",
  "amount": 0,
  "customOrderId": "string",
  "accountId": "string",
  "callbackUrl": "string"
}

Parameters

Name Type Required Description
currency string + Acronym of currency for payout.
amount number(decimal) + Amount of currency for payout.
customOrderId string Unique Internal order ID in customer's system.
accountId string Internal account ID in customer's system.
callbackUrl string Callback URL to track status changes via notifications.

Successful Response

URL to Crypto Pay iframe for the payout intent. Format: https://payment.cryptopayx.tech/payout?currencyTo=USD&amountTo=100&payoutIntentId=988a2d89-2655-4641-b368-72fe802f6731&merchantId={merchantId}&token={token} . csharp $"{this.generalOptions.CurrentValue.CryptoPayUiExternalUrl}/payout?currencyFrom={request.Currency}&amountFrom={request.Amount}&token={token}"

Check Payout status

Use the endpoint below to check the status of payout.

HTTP Request

GET v1/payout-intents/{payoutIntentId}

Parameters

Name Type Required Description
payoutIntentId string($uuid) + ID of the payout.

Successful Response

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "transactionId": 0,
  "customOrderId": "string",
  "accountId": "string",
  "amountFrom": 0,
  "amountTo": 0,
  "feeAmountTo": 0,
  "currencyFrom": "string",
  "currencyTo": "string",
  "status": "string",
  "address": "string",
  "networkCode": "string",
  "additionalAddress": "string",
  "transactionHash": "string",
  "statusDescription": "string"
}

Search payout by Account ID, Custom Order ID

Use this endpoint to search and filter payouts by:

If multiple parameters for filtering are selected, response will return only the items, which satisfy ALL the parameters.

Items in response are sorted by date, newer on top.

HTTP Request

POST v1/payout-intents/search

Request Body Example

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "customOrderId": "string",
  "accountId": "string",
  "createdDateFrom": "2024-02-23T12:50:24.833Z",
  "createdDateTo": "2024-02-23T12:50:24.833Z",
  "skip": 0,
  "take": 0
}

Parameters

Name Type Required Description
id string Exact ID of a payout intent.
customOrderId string Unique internal order ID in customer's system.
accountId string Internal account ID in customer's system.
createdDateFrom string(dateTtime) Start date the payout was initiated.
createdDateTo string(dateTtime) End date the payout was initiated.
skip int The number of items to skip in the response. If the value is 500 ,the response will return the items, starting from 501.
take int The amount of items returned in response. Max value is 500.

Successful Response

[
{
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "transactionId": 0,
    "customOrderId": "string",
    "amountFrom": 0,
    "amountTo": 0,
    "feeAmountTo": 0,
    "currencyFrom": "string",
    "currencyTo": "string",
    "status": "string",
    "address": "string",
    "networkCode": "string",
    "additionalAddress": "string",
    "transactionHash": "string",
    "statusDescription": "string",
    "accountId": "string"
}
]

Response Fields

Name Type Description
Id string($uuid) ID of the payout.
transactionId string Crypto Payx ID of the transaction executed for the payout.
customOrderId string Unique internal order ID in customer's system.
amountFrom number($decimal) Amount of the currency to convert FROM.
amountTo number($decimal) Amount of the currency to convert TO.
feeAmountTo number($decimal) Fee amount deducted from FIAT after conversion.
currencyFrom string Acronym of the currency to convert FROM.
currencyTo string Acronym of the currency to convert TO.
status string Status of payout at the moment of response.
address string Wallet address.
networkCode string Code of the network.
additionalAddress string Additional address info of network, if applicable. Used for TAG, MEMO and NOTE of the network.
transactionHash string Unique identifier of a transaction in a blockchain.
statusDescription string The reason of payout failure, empty if the payment is not failed.
accountId string Internal account ID in customer's system.

Notifications

Crypto Pay notifies merchants about the status changes of payments, made by their clients. Notifications are sent to the callback URL, provided in the corresponding payment intent.

Notification signing message

Merchants need to be authorized to get access to the payload of notification.

var bodyHash = Convert.ToBase64String(sha256.ComputeHash(Encoding.UTF8.GetBytes(body)));
var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
var signatureString = $"{timestamp}{method}{callbackUrl}{bodyHash}";

Signature is generated by creating a SHA256 HMAC using the API secret on the string timestamp + method + pathWithQuery + contentHash

Payment intent notifications

Notification payload contains the detailed info about the payment intent.

See the examples of notifications for all payment intent statuses. See Payment intent statuses grid for more info.

Processing payment intent notification

//Processing payment intent example
{
  "expectedAmount": 16.71,
  "paymentIntentId": "e71f4c41-472d-483e-b20e-2cfb0f1af6b8",
  "customOrderId": "Order_151223-175400",
  "amountFrom": 16.71,
  "amountTo": 15,
  "currencyFrom": "USDT",
  "currencyTo": "EUR",
  "executedAmountTo": null,
  "executedCurrencyTo": null,
  "status": "Processing",
  "receivedAmount": null,
  "statusDescription": null,
  "address": "0x5290341182CAb5bf7555eD49d91afA9275b2De92",
  "networkCode": "ERC20",
  "additionalAddress": "",
  "originTransactionId": null,
  "transactionHash": null,
  "sourceAddress": null,
  "notificationType": "PaymentIntentNotification"
}


Pending payment intent notification

//Pending payment intent example
{
  "paymentIntentId": "e71f4c41-472d-483e-b20e-2cfb0f1af6b8",
  "customOrderId": "Order_151223-175400",
  "amountFrom": 16.71,
  "amountTo": 15,
  "currencyFrom": "USDT",
  "currencyTo": "EUR",
  "executedAmountTo": null,
  "executedCurrencyTo": null,
  "status": "Pending",
  "receivedAmount": null,
  "statusDescription": null,
  "address": "0x5290341182CAb5bf7555eD49d91afA9275b2De92",
  "networkCode": "ERC20",
  "additionalAddress": "",
  "originTransactionId": null,
  "transactionHash": null,
  "sourceAddress": null,
  "notificationType": "PaymentIntentNotification"
}

Completed payment intent notification

//Completed payment intent example
{
  "paymentIntentId": "c8bd6c45-db94-4615-8735-97bb076ab617",
  "customOrderId": "Order_151223-173434",
  "amountFrom": 16.71,
  "amountTo": 15,
  "currencyFrom": "USDT",
  "currencyTo": "EUR",
  "executedAmountTo": 14.60,
  "executedCurrencyTo": "EUR",
  "status": "Completed",
  "receivedAmount": 16.71,
  "statusDescription": null,
  "address": "0x9fd548c05F070337457d5c0FBC9DBFFD7D7E619f",
  "networkCode": "ERC20",
  "additionalAddress": "",
  "originTransactionId": null,
  "transactionHash": "18d0f8fb499a571ae88ff257d43071648d0661bf4fbf0cda3cc8bf9c603aac72",
  "sourceAddress": null,
  "notificationType": "PaymentIntentNotification"
}

Failed payment intent notification

See Failed payment intent statuses for more info.

//Failed payment intent example
{
  "paymentIntentId": "66cd1a7a-3047-40b8-b928-3ae28911b321",
  "customOrderId": "Order_170523-170028",
  "amountFrom": 0.00061622,
  "amountTo": 15,
  "currencyFrom": "BTC",
  "currencyTo": "EUR",
  "executedAmountTo": 15,
  "executedCurrencyTo": null,
  "status": "Failed",
  "receivedAmount": 0.000616,
  "statusDescription": "Out of time",
  "address": "tb1qhljsj8nmwjmzlscr0x9rq5fp59ksxvsl72wteq",
  "networkCode": "BTC_TEST",
  "additionalAddress": "",
  "originTransactionId": null,
  "transactionHash": "18d0f8fb499a571ae88ff257d43071648d0661bf4fbf0cda3cc8bf9c603aac72",
  "sourceAddress": null,
  "notificationType": "PaymentIntentNotification"
}

Auto retry payment intent notification

If the threshold is set up for the merchant, and failed initial payment intent deposit is within the threshold, auto retry payment intent is executed.

Initial payment intent status is set to "PartiallyCompleted" if the auto retry for it is successful, and its status is set to "Completed".

See the example of notification for auto retry payment intent.

// Auto retry payment intent example
{
  "paymentIntentId": "66cd1a7a-3047-40b8-b928-3ae28911b321",
  "retryPaymentIntentId": "ef54010f-554c-4066-80b6-40fa21304dea",
  "customOrderId": "Order_170523-170028",
  "amountFrom": 0.000616,
  "amountTo": 15.32,
  "currencyFrom": "BTC",
  "currencyTo": "EUR",
  "status": "Completed",
  "notificationType": "AutoRetryPaymentIntentNotification"
}

Partially completed payment intent notification

Initial payment intent status is set to "PartiallyCompleted", if the auto retry for it is successful, and its status is set to "Completed".

See the example of notification for partially completed payment intent.

// Partially completed payment intent example
{
  "paymentIntentId": "9d09dff0-4a6b-4394-ac7f-1f063dbab5f7",
  "customOrderId": "Order_261223-152725",
  "amountFrom": 16.71,
  "amountTo": 15,
  "currencyFrom": "USDT",
  "currencyTo": "EUR",
  "status": "PartiallyCompleted",
  "executedAmountTo": 14.60,
  "executedCurrencyTo": "EUR",
  "receivedAmount": 16.7,
  "statusDescription": "Invalid amount: Less than expected",
  "address": "0xFCC972B2E6B1312B1AA28bCdaf4a219285254764",
  "networkCode": "BNB_TEST",
  "additionalAddress": "",
  "originTransactionId": null,
  "transactionHash": "18d0f8fb499a571ae88ff257d43071648d0661bf4fbf0cda3cc8bf9c603aac72",
  "sourceAddress": null,
  "notificationType": "PaymentIntentNotification"
}

Manual retry payment intent notification

If the initial payment intent has "status" : "failed", its "recievedAmount" is greater than 0, no threshold is set up for the merchant and retry transaction for it is executed, its "notificationType": "RetryPaymentIntentNotification".

See the example of notification for retry payment intent.

//Retry payment intent example
{
  "paymentIntentId": "66cd1a7a-3047-40b8-b928-3ae28911b321",
  "customOrderId": "Order_170523-170028",
  "amountFrom": 0.000616,
  "amountTo": 15.35,
  "currencyFrom": "BTC",
  "currencyTo": "EUR",
  "quoteValidTo": "2023-05-18T12:41:36.5339709Z",
  "status": "Pending",
  "notificationType": "RetryPaymentIntentNotification"
}

Refund payment intent notification

Notification payload contains the detailed info about the refund for failed initial payment intent.

//Refund payment intent example
{
  "paymentIntentId": "7d3d2e72-5aa4-42dd-9cd1-16fadf3220fc",
  "cryptoRefundPaymentIntentId": "0c648b75-f314-4fa7-8d9d-9358c76ca0f9",
  "customOrderId": "Order_230523-155734",
  "amount": 0.00055,
  "currency": "BTC",
  "destinationAddress": "tb1qdu5wgl6zqx79mw7dq7gp9pygxs349gkwl59duj",
  "destinationAdditionalAddress": null,
  "networkCode": "BTC_TEST",
  "status": "Completed",
  "notificationType": "CryptoRefundPaymentIntentNotification"
}

Payout intent notifications

Pending payout intent notification

Notification payload contains the detailed info about the payout intent.

//Pending payout intent example
{ 
    "payoutIntentId": "4e12da21-e9c2-48ac-8874-e26d3a59cf11", 
    "transactionId": 123412, 
    "customOrderld": "Order_110523-094305",
    "amountFrom": 35,
    "amountTo": 0.0012551, 
    "feeAmountTo": 0, 
    "currencyFrom": "USD", 
    "currencyTo": "BTC", 
    "status": "Pending", 
    "address": "tblq4yp7sceez346scrklfyhghhnnaj7gkzeyddhgt", 
    "networkCode": "BTCTEST",
    "additionalAddress": null 
} 

Completed payout intent notification

In case of completed payout intent, the notification includes the transaction hash.

//Completed payout intent example
{ 
    "payoutIntentId": "4e12da21-e9c2-48ac-8874-e26d3a59cf11", 
    "transactionId": 123412, 
    "customOrderld": "Order_110523-094305",
    "amountFrom": 35,
    "amountTo": 0.0012551, 
    "feeAmountTo": 0, 
    "currencyFrom": "USD", 
    "currencyTo": "BTC", 
    "status": "Сompleted", 
    "address": "tblq4yp7sceez346scrklfyhghhnnaj7gkzeyddhgt",
    "transactionHash": "18d0f8fb499a571ae88ff257d43071648d0661bf4fbf0cda3cc8bf9c603aac72",  
    "networkCode": "BTCTEST",
    "additionalAddress": null 
} 

Failed payout intent notification

See the example of the notification sent in case of failed payout intent.

"failureReason" field can have the following values:

//Failed withdrawal notification example
{ 
    "transactionId":64086,
    "customerId":170000,
    "currency":"USDT",
    "currencyType":"crypto",
    "amount":100001.00000000,
    "amountUsd":99727.99727,
    "feeAmount":0.00010000,
    "feeAmountUsd":0.00010,
    "failureReason":"Not enough balance",
    "producedOn":"2023-11-28T14:56:53.3285832Z"
} 

Other notifications

Withdrawal via bank transfer notification

Notification payload contains the detailed info about the withdrawal via bank transfer.

//Processing withdrawal via bank transfer example
{
  "id": "7c3af34f-7271-47e6-bdc5-ace979402c9f",
  "fiatWithdrawalTransactionId": 1445,
  "amount": 35,
  "feeAmount": 2.35,
  "currency": "USD",
  "bankCountryCode": "UA",
  "comment": null,
  "status": "Processing",
  "iban": "UA582124178898553591476647222",
  "recipientName": "CryptoPay_recipient",
  "paymentReason": "CryptoPay_reason",
  "externalTransactionId": "EXT1686232925805",
  "failureReason": null,
  "createdOn": "2023-06-08T14:02:10.2607593Z",
  "notificationType": "FiatTransactionNotification"
}

Merchant account management

Check Account Balance

Use this endpoint to check the balance on your accounts.

HTTP Request

[GET] /v1/accounts?type={type}

Type can be: - fiat to return only fiat accounts balances. - crypto to return only crypto accounts balances. - none to return only crypto accounts balances.

Request Body Example

[
  {
    "name": "US Dollar",
    "symbol": "USD",
    "type": "Fiat",
    "totalBalance": 788720.56,
    "totalBalanceUsd": 786196.66,
    "availableBalance": 788720.56,
    "blockedAmount": 0
  },
  {
    "name": "USD Coin",
    "symbol": "USDC",
    "type": "Crypto",
    "totalBalance": 788720.5662889,
    "totalBalanceUsd": 786196.66,
    "availableBalance": 788720.5662889,
    "availableWithdrawalBalance" : 0,
    "availableWithdrawalBalanceUsd": 0,
    "blockedAmount": 0
    }
]

Response Fields

Name Type Description
name string Name of fiat or cryptocurrency.
symbol string Acronym of fiat or cryptocurrency.
type string Type of fiat or cryptocurrency. Can be Fiat and Crypto.
totalBalance number($decimal) Total balance of the account.
totalBalanceUsd number($decimal) USD equivalent of the account balance sum.
availableBalance number($decimal) Available balance.
availableWithdrawalBalance number($decimal) Balance available for withdrawal. Credit funds are deducted from the available balance.
availableWithdrawalBalanceUsd number($decimal) Balance available for withdrawal equivalent in USD.
blockedAmount string Is 1 in case the account is blocked, otherwise the account is active.

Bank transfer

Crypto pay allows to withdraw fiat via bank transfer. To successfully execute the transfer, account balance needs to be at least the amount of withdrawal + fee. Notifications are sent for each status change of the withdrawal.

Use the endpoints below to withdraw fiat from account via bank transfer.

Calculate fee for the withdrawal

Use this endpoint to calculate fee and total amount for the withdrawal.

HTTP Request

[POST] v1/fiat-withdrawals/fee

Request Body Example

{
  "amount": 100,
  "currency": "USD",
  "bankCountryCode":"BR"
}

Parameters

Name Type Required Description
amount number(decimal) + Amount of currency for withdrawal.
currency string + Acronym of currency for withdrawal.
bankCountryCode string + Country two-letter code in ISO 3166-1 alpha-2 code format.

Successful Response

{
  "amount": 100,
  "feeAmount": 3.5,
  "totalAmount": 103.5
}

Response Fields

Name Type Description
amount number(decimal) Amount of withdrawal.
feeAmount number(decimal) Fee amount.
totalAmount number(decimal) Total amount, with fee.

Create a fiat withdrawal via bank transfer

HTTP Request

[POST] v1/fiat-withdrawals/

Request Body Example

{
  "amount": 100,
  "feeAmount": 3.5,
  "currency": "USD",
  "iban": "UA1231231231234444",
  "recipientName": "string",
  "paymentReason": "string",
  "externalTransactionId": "string",
  "callbackUrl": "string",
  "bankCountryCode": "BR"
}

Parameters

Name Type Required Description
amount number(decimal) + Amount of currency for withdrawal.
feeAmount number(decimal) + Fee amount.
currency string + Acronym of currency for withdrawal.
iban string + International bank account number of the recepient.
recipientName string + Name of the recepient.
paymentReason string + Payment reason.
externalTransactionId string Unique ID of the external transaction in PSP.
callbackUrl string Callback URL to track status changes via notifications.
bankCountryCode string + Country two-letter code in ISO 3166-1 alpha-2 code format.

Successful Response

{
    "id": "51af711f-b041-44bd-90e0-82d2880cae0f",
    "fiatWithdrawalTransactionId": 1610,
    "amount": 35.0,
    "feeAmount": 2.57,
    "currency": "EUR",
    "status": "Processing",
    "iban": "UA582124178898553591476647222",
    "bankCountryCode": "BR",
    "recipientName": "CryptoPay_recipient",
    "paymentReason": "CryptoPay_reason",
    "externalTransactionId": "EXT1686319532841",
    "createdOn": "2023-06-09T14:05:39.5388983Z"
}

Response Fields

Name Type Description
id string Unique ID of the withdrawal transaction.
fiatWithdrawalTransactionId string Unique ID of the fiat withdrawal.
amount number(decimal) Amount of currency for withdrawal.
feeAmount number(decimal) Fee amount.
currency string Acronym of currency for withdrawal.
status string Status of the withdrawal. Can be Pending, Declined, Completed.
iban string International bank account number of the recepient.
bankCountryCode string Country two-letter code in ISO 3166-1 alpha-2 code format.
recipientName string Name of the recepient.
paymentReason string Payment reason.
externalTransactionId string Unique ID of the external transaction in PSP.
createdOn string Time the withdrawal was initiated.

Crypto PayX Updates

Keep yourself up to date on new and updated Crypto PayX features. See Authentication for details.

(19/12/2024)

Support virtual fiat currency

It is now possible to configure any virtual fiat currency for pay in operations, in case real fiat currency is not supported by our liquidity providers. Using virtual fiat currency means that CryptoPayX merchant can offer any fiat currency to their customers, while actual conversion to this currency is not available. See Virtual fiat currencies for more info.

Request a new quote after expiration

If the quote for the payment intent is expired, customers of a CryptoPayX merchant will be able to request a new one. Request attempts are not limited and are available during 5(five) calendar days after the payment link is generated.

(9/12/2024)

API key management via Client Area

API keys can be generated and managed in your Client Areа Security settings.

(07/11/2024)

Payment intent Processing status and notification

We have added an additional Processing status for payment intent, which will make the process clearer and make it easier to diagnose possible issues.

This status is assigned to payment intent as soon as the deposit started being processed by Crypto PayX.

We also will sending a notification for this status, with the added expectedAmount parameter, with the value representing the amount of funds which started processing, and will be received in case of a successful payment intent.

(14/03/2024)

Single payment intent address per Account ID

We added a single address flow that allows Crypto PayX customers to use single permanent address per one Account ID. This feature will be helpful for customers operating in specific regions, where using multiple addresses for deposits requires additional actions from the customer.

See Single payment intent address for more info.

(29/02/2024)

Add external customer Account ID for payment intent and payout

We added an additional AccountId field, which will allow merchant to save external custom identifier to create payment intents and payouts with it and use it to search the transactions by this parameter.

Search transaction status by Custom Order ID and Account ID

We added two endpoints:

Using which customers can check the statuses for their payment intent and payout intents respectively.

It is possible to filter transactions by:

Underpaid payment intent top-up

We now make it possible adding funds to the existing payment intent in case the requested sum wasn’t deposited the first time.

See Underpaid payment intent top-up for more info.

(18/01/2024)

Source address, transaction hash in payment intent response and UI

We added the following parameters to notifications and payment intent status check response:

This info is also added to the payment intent detail in transaction UI for desktop and mobile view.

Empty fields will be hidden from the view.

(04/01/2024)

Separate notification for partially completed payment intent

Previously, in case of the initial payment intent failure, we’ve changed its status to “PartiallyCompleted”, but didn’t send the automatic notification for that. Now, we’re sending Crypto PayX customers a separate notification in case the initial payment intent fails for some reason, with the field “failureReason” to understand why it has failed.

Processing fee field in payment intent status response

We’ve added processing fee amount and currency fields in response for payment intent status check via API, to clarify the amount Crypto PayX subtracted from the transaction amount.

"Not found" page

Now in case of: - Expired token. - Expired payment link. - Broken payment link. - Payment link, that has been already used. - Opened payment.Cryptopayx.tech page.

We will display customers and payment link requestees page not found in Crypto PayX GUI.

(21/12/2023)

Overview

We give XBO customers, retail and corporate, the ability to request and use Payment link.

With this release, Get payment link button will be active for all customer types. (1.) Crypto PayX menu tab will be available for all customers on Webtrader. (2.)

Customers will request access on Request access popup. (3.)

How will it work?

In case the customer didn't have access to Crypto PayX, upon entering Crypto PayX tab they will see empty transactions grid, with Get payment link button active.

After clicking the button, they will see Payment request popup with the Request access button in the yellow section below, that they need to click to initiate the credential request.

Once customer clicks Request access button,they will be taken to a newpopup with the same name, with the information regarding Crypto PayX key features, and Proceed button they need to click to confirm the request.

After customer click Proceed, Crypto PayX credentials are created for their account on the background, their account gets marked as Merchant in our system, and button changes from Proceed to Done.

After that, customer can click on Done button, which will take them to the Request Payment popup, but with the full access to its functionality, including the ability to generate payment link for deposit requests.