# Introduction

Last update: 10.01.2025

The API is organized around REST. It accepts and returns JSON-encoded bodies and responses, uses standard HTTP response codes & authentication. Our API forces HTTPS to ensure the security of sensitive data.

All transaction data should only contain ASCII characters.

# Authentication

# Base URLs

Sandbox (dev):
API_BASE_URL='https://api-dev.cdnsoftwaretech.com/api/v1/merchant'
Production:
API_BASE_URL='https://api.cdnsoftwaretech.com/api/v1/merchant'

# Public key (base64-encoded)

Sandbox (dev):
GET https://api-dev.cdnsoftwaretech.com/api/v1/p/key
Production:
GET https://api.cdnsoftwaretech.com/api/v1/p/key

# Merchant registration

  1. After onboarding, our team provides a unique Merchant ID.
  2. Merchant generates a 2048-bit public-private keypair and provides the public key to CDN in PEM format.
  3. Merchant may delete the public key and provide a new one in case it is needed.

# Making a request

All requests are private and should contain the following headers:

  • x-merchant-id - Merchant ID that our team provides (you can also see it in the dashboard)
  • x-signature - Signature of the request generated using SHA256 with RSA (check the details on signature generation algorithm below)

# Signature generation

# x-signature

The entire HTTP request body is used to generate the signature. To generate the digital signature using Secure Hash Algorithm (SHA256RSA):

  1. Prepare the payload by concatenating method, full request URL with query string parameters and request body (if present). You can find the examples below.
  2. Obtain the hash of the string generated above using SHA256 algorithm. Data must be encoded using UTF8 while computing hash.
  3. Use the RSA signature algorithm to generate the digital signature using the hash produced above.
  4. The output generated is the signature.
  5. Pass this signature in the x-signature header for all API requests, unless x-short-signature is used.

Note: in most programming languages steps 2 and 3 are combined into a single SHA256RSA function. Splitting them may help you debug the issues if you encounter them.

See code examples below

# x-short-signature

Only the UUID of the transaction is used to generate the signature. To generate the digital signature using Secure Hash Algorithm (SHA256RSA):
Sample string - 3a5f04af-fb52-41ce-b9bc-283e72207cd5

  1. Obtain the hash of the string generated above using SHA256 algorithm. Data must be encoded using UTF8 while computing hash.
  2. Use the RSA signature algorithm to generate the digital signature using the hash produced above.
  3. The output generated is the signature.
  4. Pass this signature in the x-short-signature header for all API requests that require this header.

Example code Python for x-signature
import base64
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15

client_public_key = "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmjioBgaues2Cv2jlnNnp
I8HXktevZzJJaaiPWIh6m8psyay4IuDscJM8DOYAat5pxwQBtqsP8iO0/wAtSfL7
eUD1ryIS47YRqi+pRFICfVT8Lno1hCJFTaP2CMPAYxmM5/5X43ChiR5e7ho8E+J9
iPmevDJEUBOQV17GGLrD7jzxbo62Pqv4lFt9PIuPV7LyagjrU+6ep0X3Ul82je7N
tvKhtMC6Y8GgbkjxTytvO6FaNJAx35PHRaZ55asA81xwWSqoH4hsM0PK2PGICqfR
mj4zu5mbGnTss7/2xnHkxGKXUTfzt8yi9wzI2fna0+SZVIxjO+HhVAig9EkUJSvh
KQIDAQAB
-----END PUBLIC KEY-----"

client_privat_key = "-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAmjioBgaues2Cv2jlnNnpI8HXktevZzJJaaiPWIh6m8psyay4
IuDscJM8DOYAat5pxwQBtqsP8iO0/wAtSfL7eUD1ryIS47YRqi+pRFICfVT8Lno1
hCJFTaP2CMPAYxmM5/5X43ChiR5e7ho8E+J9iPmevDJEUBOQV17GGLrD7jzxbo62
Pqv4lFt9PIuPV7LyagjrU+6ep0X3Ul82je7NtvKhtMC6Y8GgbkjxTytvO6FaNJAx
35PHRaZ55asA81xwWSqoH4hsM0PK2PGICqfRmj4zu5mbGnTss7/2xnHkxGKXUTfz
t8yi9wzI2fna0+SZVIxjO+HhVAig9EkUJSvhKQIDAQABAoIBABBUx5Y7xuZCNQJH
/WiqusGKmWV3aZ+n95Y0v1lEupcczIBexfELmH4jWUyUXp7yhokIp5XMb5fYqCYI
wsL99BtXAa1WEmICucQn3+jYNmNHSJ0zW89uQaCDKF6tPAZCgmVezbfMCY8XpD3a
kVoZtel3ZZPQTuOb7sERzDB6Np1XtJxvtF93td6GgW/Q3obfwU3VmSVjydVRG1Ui
CiACzsPZUobeqBrWHaYd0TyM3UfSpvUYfEivCiSuhiTxXntijXgvJxUu2cUrL410
U10II4eamV3ZwZm2DM2szoEvrr/WQP7tUGYnSv9I78HZEhQRz7LHWQJz18v0BnuV
xhfoaTECgYEA1Fn3igEPBxonmYjE175q8OcDnlkyFnY/KzmqM0+tqMxkbvVb8aZz
OhT6Taqjyu0pikrDeNswxr4LG7oP1+OMLTJv4m8+0+sOtvMd6lVmRRp6PffFQwlp
gF2CibF74TO5D7u/NUV4Xli2xE2Os6cTFIOmE0z3vGqmSARp7BBoojcCgYEAueva
3l1VVP3NyTSAsR2yh98h9o1d+xev3bhOWE3cQ83Hp79/YYvxRw9BrbyAyXbAc7Qc
pOg6w5oGrimO71d8IIYGMpGGkmEbrCVs5AodrGEk3WcNd13uaRnVGe/+Ia7fgJr+
TUuI5q5r4/wVbc9GiOz4LHRqk+CJp0z3cMLtZ58CgYEAzsCd3Hc1a4PSpJFennRe
6Rj0E/viYa5VyL9HcNgWTDBdZQ9tqvWWYSnFn1MSUOTiuiwa8BPyBL9KT3+0J038
0JC4EO6hbHIDjKtfKCZoAcZK2QThwmhqmTnyfCAbbmQOvjvdan+uN6YGpVCiLVbx
o9qeG1KoLoJkTeBGRTqgtbcCgYEAhrfgYEBBFNTTyHfCyJQ8STfl5EGLV+ZSCNcD
7fh9IqR5h5O7OXOt4U+sx7dPmqvxx+U63ENqUVHKhWiXqdY6m1aCJyJL4MV8x8BW
puatmbrKe6Ownk3x8zZEtAaynrWYPhgRLPEOwhihFRIUdP08nvsW2R+CGqUZGaEr
qwmT/QECgYBtSALhzndWGY0HA1Qim1PyrI9vW1hocPSRUZXCYy8ComSFKKbM9Ho+
si51JB+5db78c3ECiogfAYQ7PZWCwBPkVSK+nlLbMZg4+qZ2EdD3lsbj0BOwusfU
IsZgSztrFag/naKCJtqeHxhrDi4gqxAmQnBcObH+ouPbJ2k3DFjVbw==
-----END RSA PRIVATE KEY-----"

raw_text = 'POSThttps://api-dev.cdnsoftwaretech.com/api/v1/merchant/transactions/{"external_id":"24","amount":150.23,"currency":"eur","redirect_url_success":"https://example.com/successful_transaction","redirect_url_fail":"https://example.com/failed_transaction","expires_at":"2021-12-22T05:17:56.323","payer_details":{"external_id":"32556","first_name":"Edvard","last_name":"Munch","email":"ed.munch@gmail.com","address1":"Toyengata 53","city":"Oslo","state":"","country":"NO","zip":"0578","phone":"+4723493500","date_of_birth":"2019-08-24T14:15:22Z"}}'

def generate_signature(payload: str, rsa_key=None):
key = RSA.importKey(rsa_key or client_privat_key)
h = SHA256.new(payload.encode())
signature = pkcs1_15.new(key).sign(h)
return base64.b64encode(signature).decode("utf-8")

def verify_signature(payload: str, signature: str, rsa_key=None):
key = RSA.importKey(rsa_key or client_public_key)
h = SHA256.new(payload.encode())
try:
pkcs1_15.new(key).verify(h, base64.b64decode(signature))
return True
except (ValueError, TypeError):
return False

signature = generate_signature(raw_text)
print(f"{signature=}")
print("Is valid: ", verify_signature(raw_text, signature, client_public_key)) # True

Example code PHP for x-signature

<?php
// Replace with your actual private/public keys
$publicKey = <<<EOD
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmjioBgaues2Cv2jlnNnp
I8HXktevZzJJaaiPWIh6m8psyay4IuDscJM8DOYAat5pxwQBtqsP8iO0/wAtSfL7
eUD1ryIS47YRqi+pRFICfVT8Lno1hCJFTaP2CMPAYxmM5/5X43ChiR5e7ho8E+J9
iPmevDJEUBOQV17GGLrD7jzxbo62Pqv4lFt9PIuPV7LyagjrU+6ep0X3Ul82je7N
tvKhtMC6Y8GgbkjxTytvO6FaNJAx35PHRaZ55asA81xwWSqoH4hsM0PK2PGICqfR
mj4zu5mbGnTss7/2xnHkxGKXUTfzt8yi9wzI2fna0+SZVIxjO+HhVAig9EkUJSvh
KQIDAQAB
-----END PUBLIC KEY-----
EOD;
$privateKey = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAmjioBgaues2Cv2jlnNnpI8HXktevZzJJaaiPWIh6m8psyay4
IuDscJM8DOYAat5pxwQBtqsP8iO0/wAtSfL7eUD1ryIS47YRqi+pRFICfVT8Lno1
hCJFTaP2CMPAYxmM5/5X43ChiR5e7ho8E+J9iPmevDJEUBOQV17GGLrD7jzxbo62
Pqv4lFt9PIuPV7LyagjrU+6ep0X3Ul82je7NtvKhtMC6Y8GgbkjxTytvO6FaNJAx
35PHRaZ55asA81xwWSqoH4hsM0PK2PGICqfRmj4zu5mbGnTss7/2xnHkxGKXUTfz
t8yi9wzI2fna0+SZVIxjO+HhVAig9EkUJSvhKQIDAQABAoIBABBUx5Y7xuZCNQJH
/WiqusGKmWV3aZ+n95Y0v1lEupcczIBexfELmH4jWUyUXp7yhokIp5XMb5fYqCYI
wsL99BtXAa1WEmICucQn3+jYNmNHSJ0zW89uQaCDKF6tPAZCgmVezbfMCY8XpD3a
kVoZtel3ZZPQTuOb7sERzDB6Np1XtJxvtF93td6GgW/Q3obfwU3VmSVjydVRG1Ui
CiACzsPZUobeqBrWHaYd0TyM3UfSpvUYfEivCiSuhiTxXntijXgvJxUu2cUrL410
U10II4eamV3ZwZm2DM2szoEvrr/WQP7tUGYnSv9I78HZEhQRz7LHWQJz18v0BnuV
xhfoaTECgYEA1Fn3igEPBxonmYjE175q8OcDnlkyFnY/KzmqM0+tqMxkbvVb8aZz
OhT6Taqjyu0pikrDeNswxr4LG7oP1+OMLTJv4m8+0+sOtvMd6lVmRRp6PffFQwlp
gF2CibF74TO5D7u/NUV4Xli2xE2Os6cTFIOmE0z3vGqmSARp7BBoojcCgYEAueva
3l1VVP3NyTSAsR2yh98h9o1d+xev3bhOWE3cQ83Hp79/YYvxRw9BrbyAyXbAc7Qc
pOg6w5oGrimO71d8IIYGMpGGkmEbrCVs5AodrGEk3WcNd13uaRnVGe/+Ia7fgJr+
TUuI5q5r4/wVbc9GiOz4LHRqk+CJp0z3cMLtZ58CgYEAzsCd3Hc1a4PSpJFennRe
6Rj0E/viYa5VyL9HcNgWTDBdZQ9tqvWWYSnFn1MSUOTiuiwa8BPyBL9KT3+0J038
0JC4EO6hbHIDjKtfKCZoAcZK2QThwmhqmTnyfCAbbmQOvjvdan+uN6YGpVCiLVbx
o9qeG1KoLoJkTeBGRTqgtbcCgYEAhrfgYEBBFNTTyHfCyJQ8STfl5EGLV+ZSCNcD
7fh9IqR5h5O7OXOt4U+sx7dPmqvxx+U63ENqUVHKhWiXqdY6m1aCJyJL4MV8x8BW
puatmbrKe6Ownk3x8zZEtAaynrWYPhgRLPEOwhihFRIUdP08nvsW2R+CGqUZGaEr
qwmT/QECgYBtSALhzndWGY0HA1Qim1PyrI9vW1hocPSRUZXCYy8ComSFKKbM9Ho+
si51JB+5db78c3ECiogfAYQ7PZWCwBPkVSK+nlLbMZg4+qZ2EdD3lsbj0BOwusfU
IsZgSztrFag/naKCJtqeHxhrDi4gqxAmQnBcObH+ouPbJ2k3DFjVbw==
-----END RSA PRIVATE KEY-----
EOD;

// Replace with your actual payload
$rawText = 'POSThttps://api-dev.cdnsoftwaretech.com/api/v1/merchant/transactions/{"external_id":"24","amount":150.23,"currency":"eur","redirect_url_success":"https://example.com/successful_transaction","redirect_url_fail":"https://example.com/failed_transaction","expires_at":"2021-12-22T05:17:56.323","payer_details":{"external_id":"32556","first_name":"Edvard","last_name":"Munch","email":"ed.munch@gmail.com","address1":"Toyengata 53","city":"Oslo","state":"","country":"NO","zip":"0578","phone":"+4723493500","date_of_birth":"2019-08-24T14:15:22Z"}}';

function gen_signature($rawText, $privateKey) {
// Sign the data using the private key
if (openssl_sign($rawText, $signature, $privateKey, OPENSSL_ALGO_SHA256)) {
return base64_encode($signature);
} else {
echo "Signature generation failed!";
return "";
}
};

function verify_signature($rawText, $signatureBase64, $publicKey) {
$signature = base64_decode($signatureBase64);
// Verify the signature using the public key
$verificationResult = openssl_verify($rawText, $signature, $publicKey, OPENSSL_ALGO_SHA256);

if ($verificationResult === 1) {
return "Signature is valid.";
} elseif ($verificationResult === 0) {
return "Signature is invalid.";
} else {
return "Error occurred during signature verification.";
}
};

$signatureBase64 = gen_signature($rawText, $privateKey);
echo $signatureBase64 . "\n";
echo str_repeat("_", 25);
echo verify_signature($rawText, $signatureBase64, $publicKey);
?>

# Response Header

# The x-signature response header is a signature generated from the response payload using the private key and is included in every API response. Merchant should use the public key to validate and verify the response message integrity. Although this step is optional, it is highly recommended for security reasons.

# Core API requests

# Payments

# Create a transaction

POST {API_BASE_URL}/transactions/
Body:

Attribute Type Required? Description
external_id string - Unique transaction id in your system.
amount decimal / string + The amount of a transaction that will be deducted from the user's card.
currency string + The currency of a card transaction, according to ISO 4217 (only selected currencies are supported). Supported currencies.
method string - Payment method. Supported methods. card is by default.
redirect_url_success string + The URL where the user should be redirected after the successful transaction.
redirect_url_fail string + The URL where the user should be redirected after the failed/canceled transaction.
notification_url string - The URL which should be used for server-to-server webhooks. If not sent — defaults to a pre-set-up URL for all transactions.
expires_at string - Time of the transaction expiration, timestamp+30min by default. If the transaction is not completed by this time, we will reject any attempt to complete it. The expiration is extended each time a user (re-)submits a payment, so provided expiration date will be changed in most cases. Max value is (now)+3h.
payer_details.external_id string - Your unique customer's id in your system.
payer_details.first_name string + Your customer’s first name.
payer_details.last_name string + Your customer’s last name.
payer_details.email string + Your customer’s email.
payer_details.address1 string + Your customer’s billing address.
payer_details.address2 string - Your customer’s billing address (second line).
payer_details.city string + Your customer’s billing city.
payer_details.state string - Your customer’s billing state.
payer_details.country string + Your customer’s billing 2-char country code (ISO 3166-1, alpha-2).
payer_details.zip string - Your customer’s billing zip code.
payer_details.phone string - Your customer’s phone number with country code included.
payer_details.date_of_birth string + Your customer’s date of birth (must be 18+ y.o.).
sending_card_details bool - Send "true" if you will provide the user's card details server-side instead of the user entering them in our UI. Check with your account manager to enable this feature.

Example:

{"external_id":"24","amount":150.23,"currency":"eur","redirect_url_success":"https://example.com/successful_transaction","redirect_url_fail":"https://example.com/failed_transaction","expires_at":"2021-12-22T05:17:56.323","payer_details":{"external_id":"32556","first_name":"Edvard","last_name":"Munch","email":"ed.munch@gmail.com","address1":"Toyengata 53","city":"Oslo","state":"","country":"NO","zip":"0578","phone":"+4723493500","date_of_birth":"2019-08-24"}}

Response:

{"id":"3a5f04af-fb52-41ce-b9bc-283e72207cd5","external_id":"24","amount":150.23,"currency":"eur","created_at":"2022-04-08T11:11:59.711317","updated_at":"2022-04-08T11:11:59.711319","expires_at":"2022-04-08T11:11:59.711320","status":"pending","error_code":null,"error_message":null,"payment_url":"https://pay-dev.worldwidesecuretx.com/3a5f04af-fb52-41ce-b9bc-283e72207cd5","merchant_currency_amount":150.23}

If you don't plan to send card details via API, then you need to redirect the user or open a new browser window to/with the link {body.payment_url}. If you sent sending_card_details=true, then you need to proceed with sending card data to the endpoint from the response: {body.card_details_url}.

# Payment methods

This list shows all the methods currently supported. However, some methods might not be available for your integration, please check with your account manager to confirm which methods are accessible for your setup.

Method Description
all Hosted payment page integration. All payment methods will be available to the user. You must redirect the user or open a new browser window to/with the link {body.payment_url}
card Credit and debit card payments.
bank Bank transfer

If payment method is not specified in create transaction API request, then card is used by default.

# Send card details

This request uses x-short-signature instead of x-signature.
POST {card_details_url}
Body:

Attribute Type Required? Description
transaction_id string + Transaction UUID, id from the response of the tx creation request.
number string + Full card number.
exp_month int + Card expiry month (1..12)
exp_year int + Card expiry year (e.g. 2024)
csc string + 3-digit card security code (CVV2/CVC2).

Note:
Inside your integration (code) while sending card details on card_details_url use header:
accept-encoding: "gzip"

While using Postman - remove accept-encoding header completely

Example:

{"transaction_id":"3a5f04af-fb52-41ce-b9bc-283e72207cd5","number":"4242424242424242","exp_month":6,"exp_year":2025,"csc":"048"}

Response:

{"payment_url":"https://pay-dev.cdnsoftwaretech.com/3a5f04af-fb52-41ce-b9bc-283e72207cd5"}

Then you need to redirect the user or open a new browser window to/with the link {body.payment_url}.

# Check transaction

GET {API_BASE_URL}/transactions/:id
GET {API_BASE_URL}/transactions/?external_id={external_id}
Examples:

/transactions/3a5f04af-fb52-41ce-b9bc-283e72207cd5
/transactions?external_id=24

Response:

{"id": "3a5f04af-fb52-41ce-b9bc-283e72207cd5", "external_id": "24", "amount": "150.23", "currency": "eur", "created_at": "2022-04-08T11:11:59.711317", "updated_at": "2022-04-08T11:11:59.711319", "expires_at": "2022-04-08T11:11:59.711320", "status": "executed", "error_code": null, "error_message": null, "payment_url": "https://pay-dev.worldwidesecuretx.com/3a5f04af-fb52-41ce-b9bc-283e72207cd5", "merchant_currency_amount": 150.23}

# Payment statuses

Status Description
pending User sees a screen to make a payment
confirming User submitted the card data and transaction is being processed
retrying User has performed 1 or more unsuccessful attempts and is trying again
executed User successfully paid with his card
expired The transaction has expired without a payment
canceled User canceled the transaction
failed Transaction didn't go through because of an error

#

# Supported currencies

The list of supported currencies depends on your merchant configuration. Please check with the account manager or the integration support team.

Code Currency
CAD Canadian Dollar
USD United States Dollar
EUR Euro
SEK Swedish Krona
NOK Norwegian Krone
PLN Polish Złoty
DKK Danish Krone
GBP British Pound
AED United Arab Emirates Dirham
AUD Australian Dollar
CHF Swiss Franc
HUF Hungarian Forint
NZD New Zealand Dollar
ZAR South African Rand
JPY Japanese Yen
KZT Kazakhstani Tenge

# Payouts

# Create a payout transaction

POST {API_BASE_URL}/payouts/
Body:

Attribute Type Required? Description
external_id string + An external identifier used by the merchant to track this specific payout request.
amount decimal / string + The amount of money to be transferred
currency string + The currency of a payout transaction, according to ISO 4217 (only selected currencies are supported).
redirect_url_success string * The URL where the user should be redirected after the successful transaction. Required if sending_card_details parameter is false.
redirect_url_fail string * The URL where the user should be redirected after the failed/canceled transaction. Required if sending_card_details parameter is false.
nonce string + A unique 32-character string used for request deduplication and securing the request.
notification_url string - The URL where the merchant will receive notifications about the payout status. It can be null if no notification URL is provided.
firstname string + The first name of the user associated with the payout.
lastname string + The last name of the user associated with the payout.
email string + The email address of the user associated with the payout.
ip string + The IP address of the user associated with the payout.
sending_card_details bool - Send "true" if you will provide the user's card details server-side instead of the user entering them in our UI. Check with your account manager to enable this feature.

Example:

{ "amount": 100.11, "currency": "EUR", "external_id": "8bf10678-c3a1-47e6-89b7-25fd8552f154", "firstname": "John", "lastname": "Doe", "email": "test@test.com", "ip": "10.10.10.10", "nonce": "5qDYsAnMz32fULl81YpGqvK9e4nCfvrU", "notification_url": "https://example.com/webhook", "sending_card_details": false }

Response:

{ "uuid": "33788af4-8a3d-4806-b546-4e8f1418197d", "external_id": "8bf10678-c3a1-47e6-89b7-25fd8552f154", "status": "pending", "error_code": null, "error_message": null, "amount": "100.11", "currency": "eur", "card_details_url": null, "payout_url": "https://payout-dev.cdnsoftwaretech.com/3a5f04af-fb52-41ce-b9bc-283e72207cd5", "created_at": "2024-10-14T07:13:07.582317", "updated_at": "2024-10-14T07:13:07.582320" }

If you don't plan to send card details via API, then you need to redirect the user or open a new browser window to/with the link {body.payout_url}. If you sent sending_card_details=true, then you need to proceed with sending card data to the endpoint from the response: {body.card_details_url}.

# Send card details

This request uses x-short-signature instead of x-signature. It is calculated as a concatenation of multiple parameters. The concatenated string should consist of:
transaction_id + card bin (first 6 digits) + last4 digits
Then, as usual, this string is hashed with SHA256, signed with the private key, and encoded in base64

POST {card_details_url}
Body:

Attribute Type Required? Description
transaction_id string + Transaction UUID, id from the response of the payout creation request.
number string + Full card number.
exp_month int + Card expiry month (1..12)
exp_year int + Card expiry year (e.g. 2024)

Note:
Inside your integration (code) while sending card details on card_details_url use header:
accept-encoding: "gzip"

While using Postman - remove accept-encoding header completely

Example:

{ "transaction_id": "3a5f04af-fb52-41ce-b9bc-283e72207cd5", "number": "4242424242424242", "exp_month": 6, "exp_year": 2025 }

Response:

{ "status": "executed", "error_code": null, "error_message": null }

Then you need to redirect the user or open a new browser window to/with the link {body.payout_url}.

# Check transaction

This request uses x-signature header, where only the uuid or external_id (based on the query you use) of the transaction is used to generate the signature. Sign with your merchant's RSA private key using SHA-256 hashing, base64-encode the signature, and include it in the header.

GET {API_BASE_URL}/payouts?uuid={uuid}
GET {API_BASE_URL}/payouts?external_id={external_id}
Examples:

/api/v1/merchant/payouts?uuid=3a5f04af-fb52-41ce-b9bc-283e72207cd5
/api/v1/merchant/payouts?external_id=24

Response:

{ "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "external_id": "string", "status": "string", "error_code": "string", "error_message": "string", "amount": "string", "currency": "string", "created_at": "2024-10-10T22:26:40.239Z", "updated_at": "2024-10-10T22:26:40.239Z" }

# Payout statuses

Status Description
pending Transaction was created and is being processed.
executed Transaction is processed successfully.
failed Transaction didn't go through because of an error.
refunded Transaction was canceled for additional reasons, the payout amount was fully refunded.

#

# Supported currencies

The list of supported currencies depends on your merchant configuration. Please check with the account manager or the integration support team.

Code Currency
EUR Euro
KZT Kazakhstani Tenge

# iFrame

For merchant-server and user-server integrations iFrame is available.
You can open payment url like this:

<iframe src=“https://pay.domain.com/p/:uuid” />

# Webhooks (server-2-server notifications)

# Getting webhooks

Our service should be able to post webhooks to merchants' servers. If a merchant wants to add a webhook, he should set it up via the admin tool (at the moment, this can be done via the tech support team).
Webhooks are sent asynchronously and may arrive out of order. The merchant’s server should acknowledge the receipt of the webhook by sending an HTTP 200 OK response. If the server hasn't acknowledged the receipt of the webhook, we will start a backoff mechanism (immediately -> 10 minutes -> 15 minutes -> 30 minutes -> 1 hour -> 2 hours -> 6 hours -> 6 hours- > 6 hours -> 6 hours -> send an email notification about the server connection issue to the merchant's email address).

# Webhook types

Type Description Payload
tx_status_updated This webhook is sent every time a transaction status changes (including when it's created). {"id": "3a5f04af-fb52-41ce-b9bc-283e72207cd5", "external_id": "24", "amount": 150.23, "currency": "eur", "created_at": "2022-04-08T11:11:59.711317", "updated_at": "2022-04-08T11:11:59.711319", "expires_at": "2022-04-08T11:11:59.711320", "status": "executed", "error_code": null, "error_message": null, "payment_url": "https://pay-dev.worldwidesecuretx.com/3a5f04af-fb52-41ce-b9bc-283e72207cd5", "merchant_currency_amount": 150.23}

Webhook data may differ from the example above, please check with your account manager to clarify which additional fields can/will be sent (e.g. masked card number).

# Verifying webhook/response sender (optional)

In order to make sure that a webhook is sent by CDN, you are strongly advised to check our digital signature. The x-signature header is included in every webhook & response. It is a signature generated from the webhook body using the standard signature generation algorithm with CDN’s private key.
Example body:

{"id":"3a5f04af-fb52-41ce-b9bc-283e72207cd5","external_id":"24","amount":150.23,"currency":"eur","created_at":"2022-04-08T11:11:59.711317","updated_at":"2022-04-08T11:11:59.711319","expires_at":"2022-04-08T11:11:59.711320","status":"executed","error_code":null,"error_message":null,"payment_url":"https://pay-dev.worldwidesecuretx.com/3a5f04af-fb52-41ce-b9bc-283e72207cd5","merchant_currency_amount":150.23}

⬇️⬇️⬇️ (in the example we use the same private key as in Signature generation examples)
evRePZNKZxUK5ThSld2hcV5LXgwBzuErzaiOJadJP09DEG04C4Kg9XRN/yGiRmCFqTSrt/3b1NUO9yKdVc6bJTSKVp82iKwVTGoBEkT0lj/b/h2QKHc5dBhuwMmaopPbgs3KU7SWa0oqLpq6cRDzwb+G3pA2rrUyi9rnZS3pLtNMeBstte4Fbg1Fed09Xp6ZlFkFi9bVxkTrvy3z300nvabI9VNq86rEZpUPuQmIMYlCCTkDViGxpJPg+sIiEHpWf0RzeUaOZfR13oII88Zn2iRtRMg6OM615JRTzqnc4uZgf6BWJr56j2NJvHJZTUxU+vePWy1OaABJFyY0Ye2PuQ==

# Errors

# HTTP response codes:

# 200 OK

Everything works as expected.

# 400 Bad request

Invalid data was sent or some parameters are missing.

# 401 Unauthorized

No valid Bearer key provided.

# 403 Forbidden

The API key doesn't have a permission for this action.

# 404 Not found

The requested resource doesn't exist.

# 422 Unprocessable Entity

The request payload could not pass the validation (probably incorrect).

# 429 Too many requests

Too many requests hit the API too quickly.

# 5XX Server errors

Something went wrong on our side.

# Internal error codes:

Payment Gateway Errors:

  • GENERIC_DECLINE : 201001 : Generic Decline
  • INSUFFICIENT_FUNDS : 201002 : Insufficient funds
  • DO_NOT_HONOUR : 201003 : Do not honour
  • NO_3DS_SUPPORT : 201004 : Card or Issuer Doesn't Support 3DS
  • EXCEEDS_ACQUIRER_LIMIT : 201005 : Exceeds payment gateway limits
  • SUSPECTED_FRAUD : 201006 : Suspected fraud
  • AUTH_3DS_FAILED : 201007 : 3D authentication failed
  • INVALID_CARD_NUMBER : 201008 : Invalid card number
  • INVALID_CVV : 201009 : Invalid CVV
  • INVALID_CARDHOLDER_NAME : 201010 : Invalid name on card
  • CARD_IS_EXPIRED : 201011 : Expired card
  • GATEWAY_TIMEOUT : 201012 : Timeout
  • INVALID_AMOUNT : 201013 : Payment gateway declined transaction amount
  • USER_IS_BLOCKED : 201014 : User is blocked
  • INVALID_ADDRESS : 201015 : Invalid billing address
  • INVALID_CURRENCY : 201016 : Invalid currency
  • CANCELLED_BY_USER : 201017 : Cancelled by user on payment gateway page
  • INVALID_CARD_NETWORK : 201018 : Invalid card network
  • INVALID_CARD : 201019 : Invalid card
  • ERROR_FROM_ISSUING_BANK : 201021 : Error from issuing bank
  • RESTRICTED_CARD : 201023 : Card is restricted or blocked
  • CARD_BLACKLISTED_BY_ACQUIRER : 201104 : Card is blacklisted on acquirer side
  • CANNOT_AUTHORIZE : 201027 : Cannot authorize
  • UNKNOWN_ERROR : 201028 : Unknown error
  • EXCEEDS_CARD_LIMIT : 201030 : Exceeds card limits
  • BLACKLISTED_BY_ACQUIRER : 201101 : User/Domain or card is blacklisted on acquirer side
  • NOT_PERMITTED : 201104 : Transaction not permitted to cardholder
  • VALIDATION_FAILED : 201105 : Validation failed
  • BLACKLISTED_CARD : 201107 : Card is prohibited due to internal policy. Do not retry with this card.
  • INVALID_CARD_EXP_DATE : 201106 : Invalid card expiration date
  • USER_EMAIL_VALIDATION_FAILED: 201108 : User's email address validation has failed
  • BLACKLISTED_IP_ADDRESS: 201109 : IP address is blacklisted.

Transaction Errors:

  • NO_ACQUIRER_TO_CHOOSE : 100300 : No acquirers to choose
  • CANCELED_BY_USER : 100302 : Transaction canceled by user
  • EXPIRED : 100303 : Transaction expired
  • CARD_IS_SUSPENDED : 100306 : Card is suspended
  • CARD_COUNTRY_IS_RESTRICTED : 100307 : Card country is restricted

Generic Errors:

  • TRANSACTION_DOES_NOT_EXIST : 100500 : Transaction does not exist
  • INVALID_PAYMENT_METHOD : 100501 : Invalid payment method
  • INVALID_CARD_DETAILS_LINK : 100502 : Invalid card details link

Transaction Creation Errors:

  • UNFILLED_MERCHANT_DATA : 100100 : Merchant data unfilled
  • MERCHANT_DOESNT_HAVE_KEYS : 100101 : Merchant does not have keys
  • MERCHANT_WRONG_SIGNATURE : 100102 : Wrong Merchant's signature
  • USER_COUNTRY_NOT_SUPPORTED : 100103 : User’s country is not supported
  • INVALID_CURRENCY_SPECIFIED : 100104 : Invalid currency specified
  • CURRENCY_NOT_SUPPORTED : 100106 : currency is not configured for your account. Please contact your account manager.
  • EXTERNAL_TX_ID_DUPLICATE : 100107 : Transaction with specified external_id already exists
  • USER_IS_BANNED : 100108 : This user is banned and cannot perform transactions on our service.
  • NO_ACQUIRER_TO_CHOOSE : 100300 : No acquirer to choose
  • WRONG_TRANSACTION_AMOUNT : 100110 : Transaction amount must be between {min_amount} and {max_amount}
  • USER_IS_SUSPENDED : 100111 : User is suspended
  • USER_NAME_VALIDATION_FAILED : 100112 : User's name validation has failed

Card Details Errors:

  • CARD_NETWORK_NOT_SUPPORTED : 100204 : Your credit card network is not supported
  • FAILED_TO_ADD_CARD : 100201 : Failed to add card. Try again or contact support
  • MERCHANT_WRONG_SIGNATURE : 100102 : Wrong Merchant's signature
  • TRANSACTION_ALREADY_HAS_CARD : 100202 : Card details were already provided
  • CARD_COUNTRY_NOT_SUPPORTED : 100203 : Your credit card country is not supported
  • BLACKLISTED_CARD : 201107 : Card is prohibited due to internal policy. Do not retry with this card.

Internal Errors:

  • INTERNAL_ERROR : 300000 : Internal error
  • PAYMENT_CREATION_ERROR : 300001 : Error during payment creation
  • UNEXPECTED_RESPONSE_STATUS : 300004 : Unexpected response status:

# Test credentials (dev)

# Credit cards

Card number: 4000 0278 9138 0961
Date: any valid date in the future
CVV: 123

Card number: 4761 3441 3614 1390
Date: any valid date in the future
CVV: 123

Card number: 5101 0810 4600 6034
Date: any valid date in the future
CVV: 123

Card number: 4242 4242 4242 4242
Date: any valid date in the future
CVV: 123

If 3DS asks you for the confirmation code, use 4444.

Please check with our technical support team if the above cards do not work for you, sometimes we change the testing cards.

# Signature generation examples

# Payload preparation

You should use a minified JSON (no whitespaces!) for signature generation. The payload used for signature generation must be 100% the same as the payload sent in the request.
POST
https://api-dev.cdnsoftwaretech.com/api/v1/merchant/transactions/

{"external_id":"24","amount":150.23,"currency":"eur","redirect_url_success":"https://example.com/successful_transaction","redirect_url_fail":"https://example.com/failed_transaction","expires_at":"2021-12-22T05:17:56.323","payer_details":{"external_id":"32556","first_name":"Edvard","last_name":"Munch","email":"ed.munch@gmail.com","address1":"Toyengata 53","city":"Oslo","state":"","country":"NO","zip":"0578","phone":"+4723493500","date_of_birth":"2019-08-24T14:15:22Z"}}

⬇️⬇️⬇️
POSThttps://api-dev.cdnsoftwaretech.com/api/v1/merchant/transactions/{"external_id":"24","amount":150.23,"currency":"eur","redirect_url_success":"https://example.com/successful_transaction","redirect_url_fail":"https://example.com/failed_transaction","expires_at":"2021-12-22T05:17:56.323","payer_details":{"external_id":"32556","first_name":"Edvard","last_name":"Munch","email":"ed.munch@gmail.com","address1":"Toyengata 53","city":"Oslo","state":"","country":"NO","zip":"0578","phone":"+4723493500","date_of_birth":"2019-08-24T14:15:22Z"}}

GET https://api-dev.cdnsoftwaretech.com/api/v1/merchant/transactions/?external_id=24
⬇️⬇️⬇️
GEThttps://api-dev.cdnsoftwaretech.com/api/v1/merchant/transactions/?external_id=24

GET https://api-dev.cdnsoftwaretech.com/api/v1/merchant/transactions/3a5f04af-fb52-41ce-b9bc-283e72207cd5
⬇️⬇️⬇️
GEThttps://api-dev.cdnsoftwaretech.com/api/v1/merchant/transactions/3a5f04af-fb52-41ce-b9bc-283e72207cd5

# Generating SHA-256 with RSA signature

Example public-private keypair

-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAmjioBgaues2Cv2jlnNnpI8HXktevZzJJaaiPWIh6m8psyay4 IuDscJM8DOYAat5pxwQBtqsP8iO0/wAtSfL7eUD1ryIS47YRqi+pRFICfVT8Lno1 hCJFTaP2CMPAYxmM5/5X43ChiR5e7ho8E+J9iPmevDJEUBOQV17GGLrD7jzxbo62 Pqv4lFt9PIuPV7LyagjrU+6ep0X3Ul82je7NtvKhtMC6Y8GgbkjxTytvO6FaNJAx 35PHRaZ55asA81xwWSqoH4hsM0PK2PGICqfRmj4zu5mbGnTss7/2xnHkxGKXUTfz t8yi9wzI2fna0+SZVIxjO+HhVAig9EkUJSvhKQIDAQABAoIBABBUx5Y7xuZCNQJH /WiqusGKmWV3aZ+n95Y0v1lEupcczIBexfELmH4jWUyUXp7yhokIp5XMb5fYqCYI wsL99BtXAa1WEmICucQn3+jYNmNHSJ0zW89uQaCDKF6tPAZCgmVezbfMCY8XpD3a kVoZtel3ZZPQTuOb7sERzDB6Np1XtJxvtF93td6GgW/Q3obfwU3VmSVjydVRG1Ui CiACzsPZUobeqBrWHaYd0TyM3UfSpvUYfEivCiSuhiTxXntijXgvJxUu2cUrL410 U10II4eamV3ZwZm2DM2szoEvrr/WQP7tUGYnSv9I78HZEhQRz7LHWQJz18v0BnuV xhfoaTECgYEA1Fn3igEPBxonmYjE175q8OcDnlkyFnY/KzmqM0+tqMxkbvVb8aZz OhT6Taqjyu0pikrDeNswxr4LG7oP1+OMLTJv4m8+0+sOtvMd6lVmRRp6PffFQwlp gF2CibF74TO5D7u/NUV4Xli2xE2Os6cTFIOmE0z3vGqmSARp7BBoojcCgYEAueva 3l1VVP3NyTSAsR2yh98h9o1d+xev3bhOWE3cQ83Hp79/YYvxRw9BrbyAyXbAc7Qc pOg6w5oGrimO71d8IIYGMpGGkmEbrCVs5AodrGEk3WcNd13uaRnVGe/+Ia7fgJr+ TUuI5q5r4/wVbc9GiOz4LHRqk+CJp0z3cMLtZ58CgYEAzsCd3Hc1a4PSpJFennRe 6Rj0E/viYa5VyL9HcNgWTDBdZQ9tqvWWYSnFn1MSUOTiuiwa8BPyBL9KT3+0J038 0JC4EO6hbHIDjKtfKCZoAcZK2QThwmhqmTnyfCAbbmQOvjvdan+uN6YGpVCiLVbx o9qeG1KoLoJkTeBGRTqgtbcCgYEAhrfgYEBBFNTTyHfCyJQ8STfl5EGLV+ZSCNcD 7fh9IqR5h5O7OXOt4U+sx7dPmqvxx+U63ENqUVHKhWiXqdY6m1aCJyJL4MV8x8BW puatmbrKe6Ownk3x8zZEtAaynrWYPhgRLPEOwhihFRIUdP08nvsW2R+CGqUZGaEr qwmT/QECgYBtSALhzndWGY0HA1Qim1PyrI9vW1hocPSRUZXCYy8ComSFKKbM9Ho+ si51JB+5db78c3ECiogfAYQ7PZWCwBPkVSK+nlLbMZg4+qZ2EdD3lsbj0BOwusfU IsZgSztrFag/naKCJtqeHxhrDi4gqxAmQnBcObH+ouPbJ2k3DFjVbw== -----END RSA PRIVATE KEY-----
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmjioBgaues2Cv2jlnNnp I8HXktevZzJJaaiPWIh6m8psyay4IuDscJM8DOYAat5pxwQBtqsP8iO0/wAtSfL7 eUD1ryIS47YRqi+pRFICfVT8Lno1hCJFTaP2CMPAYxmM5/5X43ChiR5e7ho8E+J9 iPmevDJEUBOQV17GGLrD7jzxbo62Pqv4lFt9PIuPV7LyagjrU+6ep0X3Ul82je7N tvKhtMC6Y8GgbkjxTytvO6FaNJAx35PHRaZ55asA81xwWSqoH4hsM0PK2PGICqfR mj4zu5mbGnTss7/2xnHkxGKXUTfzt8yi9wzI2fna0+SZVIxjO+HhVAig9EkUJSvh KQIDAQAB -----END PUBLIC KEY-----

RSA signing (SHA256withRSA)
POSThttps://api-dev.cdnsoftwaretech.com/api/v1/merchant/transactions/{"external_id":"24","amount":150.23,"currency":"eur","redirect_url_success":"https://example.com/successful_transaction","redirect_url_fail":"https://example.com/failed_transaction","expires_at":"2021-12-22T05:17:56.323","payer_details":{"external_id":"32556","first_name":"Edvard","last_name":"Munch","email":"ed.munch@gmail.com","address1":"Toyengata 53","city":"Oslo","state":"","country":"NO","zip":"0578","phone":"+4723493500","date_of_birth":"2019-08-24T14:15:22Z"}}
⬇️⬇️⬇️
PPoh2Cpxj7xG0jKnFicX0Tv7D9P9Zo7vn7HK0e2+Xwbvao6MLWR39eLgqvxYjPY4LaAkggBuOPZFcJkdjBP2FPufbEbB0pKgie19Vcg/OANWlgk0d+snTwtdg0touY+VAmoj3gVfeHTSZpdntrF12jqKTx0Kq6HRaquzJ7hiJlulb0GoKwW+hVY5VOA+ulIg4XQvBn/runpKvQP2UkvSJw3aBD1GZBgzVXM8LW/u79QqopyZMFtI/mqAd583F0IYPB4nXZigpcf1Tq/ekmxsjBquMl54J8LekpuNXsaopcFuzlKplwjS7CH55VRrgNxPKeMMeWGPg5AOxLdE7uDN0w==

GEThttps://api-dev.cdnsoftwaretech.com/api/v1/merchant/transactions/?external_id=24
⬇️⬇️⬇️
Wn8e3M2C3VFILseo9qrplxVET4Wg7GXS+l3NCeiL3tk1ss67EKPIbWPZVrcnlR6L3s14MEiibeZJKfMxnJpwWNIAvx9SINOjwtCj07W3TowDUOpgzS09hJd3p57U2nhTjArm9MyoCCNruUwxr0qNE/v7poFIdOcR1AcqQVGLtBIUSIkDkyB7XeeynwCFNIX4CN6nP+WEhwKcZOGh4PmYrdL47FNcSVpEi0aWxOaP8sC28dbf+xUTQ6xFxEjDRXOlbyUsnMyFPbo8loAjgrRHqM+3hoQh1b38Uk06rzyBjwpKuXA6476VUkWkej+eCBWskxdRXk2WOTcw/YpqgTgCKQ==

GEThttps://api-dev.cdnsoftwaretech.com/api/v1/merchant/transactions/3a5f04af-fb52-41ce-b9bc-283e72207cd5
⬇️⬇️⬇️
fAzPzziFlwUM3iTO3gw32BzLSLupXaIeXOwVSuohnUY6OpAvZicftGKBYpPXDKzbTn/7sgils0LalukhnAHR0tEG6JHeiHjDh2G+hZeAElxJAnz7tBZ+rlyDlk1YBNvGq1YXHfZSbTCmVWEgHl8fSOdxSTvs2E40iXNvEEFlelUTkH80nX7WbKeTcBvObVW8+jnLBCMi4pp/ddDhnyRmgSGRh0NJzg+62z8NfF0zLOKu8QmRmkjFtmonhE6LAbJ9IYZiSSTSd3NDvL0jCvj+mFyu4d9GyJFwZGH5lZCYjjzvrFzLWV4+KtOpUf2Yo2j03/op6ESacG8QfU+H1CUn2Q==

# Common questions and issues

# Incorrect signature

Make sure you're signing the exact payload you're sending. Try minifying the JSON you're sending by removing all whitespaces (JSON formatting). Check if you've concatenated the method, full URL (of the correct environment) and request body, without using any extra characters (e.g. trailing slashes).

# Incorrect amount (lower or higher than the limits)

If you're using a currency which is not EUR, the rate your system uses may differ from the rate in our system which can result in slight differences between the EUR equivalents. Feel free to contact our integration team to clarify this. In case you use non-EUR currencies, it is recommended to have higher minimum and lower maximum limits than your limits on CDN side to avoid such issues.

# RSA keypair generation example

You can use the following commands:
openssl genrsa -out my-private-key.pem 2048
openssl rsa -in my-private-key.pem -pubout -out my-public-key.pem
Then you need to share the generated public key (my-public-key.pem) with our team.