This guide talks about the Access token feature.
Access tokens allow Affiliate Partners to securely connect to and interact with key parts of their account through our trusted API. Partners can create and manage tokens directly in their Affiliate account, giving them controlled, flexible access based on the permissions (scopes) they choose.
To create an Access token:
Log in to your Affiliate account.
Go to the Hub section.
Open the Access Token tab.
Click Create a new token and choose the scopes (permissions).
Copy and paste it into your integration.
Each Partner can have up to 4 active tokens at the same time.
For security reasons, the token is displayed only once, immediately after it’s generated.
Important: We do not store it in plaintext or send it via email, so you should copy and save your token right away.
Make sure your token is stored securely in your system and never exposed in public repositories.
If you have several accounts, you will need to generate separate Access tokens for each one. Tokens are unique and only work with the specific account they were created in.
Tokens are stored in our database in an encrypted form. When an API request is made using a token, the system performs the following checks:
Is the token present in the database?
Is the token still active?
If all checks pass, the request is executed.
If any check fails, the API returns an authentication error.
When creating a token, choose one or several scopes:
Create payouts: Create withdrawal requests for your Affiliate rewards.
Read payouts: View your withdrawal request history.
Read exchanges: Access exchange data and statistics.
Read balance: View your Affiliate account balance.
Here is how you can manage your tokens:
You can name each token to keep things organized. Use the token ID and custom name to identify tokens in your account.
Delete tokens if you no longer use them or if their security has been compromised.
Choose each token’s expiration date. Once expired, tokens cannot be renewed; simply generate a new one with the scopes you need.
This section provides tools and guidance for generating signatures. Use the provided scripts or manual steps to create the required headers. If something doesn’t work, follow the debugging tips and validation checks below.
Important: The private key is provided in Base64 format without a PEM wrapper. Store it in a secure place!
Step 1: Prepare the data
For each request, you need the following:
Timestamp - current Unix time in milliseconds
Nonce - a random 16-character string (hex is recommended: 0–9, a–f)
Method - HTTP method in uppercase (GET, POST, PUT, DELETE)
Path - request path without query parameters or domain
Step 2: Create the string to sign
Concatenate the data without separators in the following order:
METHOD + PATH + TIMESTAMP + NONCE + ACCESS_TOKEN_PUBLIC_ID
Example:
Method: GET
Path: /api/v1/payouts
Timestamp: 1703001234567 (milliseconds)
Nonce: a1b2c3d4e5f67890 (16 symbols)
Public ID: token_abc123
The result:
GET/api/v1/payouts1703001234567a1b2c3d4e5f67890token_abc123
Step 3: Create the signature
Decode the private key from Base64 to binary;
Sign the string using ECDSA with the P-256 curve and SHA-256 hash;
Convert the signature from DER format to JOSE format (if necessary);
Encode the result in Base64.
Step 4: Send the request
Add the following headers to your HTTP request:
x-access-token-key: your Public ID;
x-timestamp: timestamp from step 1;
x-nonce: nonce from step 1;
x-signature: signature from step 3.
Before you begin, make sure the required tools are installed:
Ubuntu/Debian:
bash
sudo apt-get update
sudo apt-get install openssl curl coreutils
CentOS/RHEL/Rocky:
bash
sudo yum install openssl curl coreutils
Or for the newer versions:
sudo dnf install openssl curl coreutils
Alpine Linux:
bash
apk add openssl curl coreutils
macOS:
bash
It is usually installed, but if not:
brew install openssl curl coreutils
bash
# Check if all required commands are available
check_dependencies() {
local missing=""
command -v openssl >/dev/null 2>&1 || missing="$missing openssl"
command -v curl >/dev/null 2>&1 || missing="$missing curl"
command -v fold >/dev/null 2>&1 || missing="$missing fold"
command -v base64 >/dev/null 2>&1 || missing="$missing base64"
if [ -n "$missing" ]; then
echo ":x: Missing commands:$missing"
echo "Install them as described above"
return 1
else
echo ":white_check_mark: All required utilities are installed"
return 0
fi
}
check_dependencies
bash
# Store your credentials in environment variables
export PUBLIC_ID="your_public_id_here"
export PRIVATE_KEY_BASE64="your_private_key_base64_here"
Create a file named sign_request.sh:
bash
#!/bin/bash
# Function to split a Base64 string into lines of 64 characters (alternative to fold)
split_base64() {
local input="$1"
local i=0
while [ $i -lt ${#input} ]; do
echo "${input:$i:64}"
i=$((i + 64))
done
}
# Function to generate a random hex string (alternative to openssl rand)
generate_nonce() {
if command -v openssl >/dev/null 2>&1; then
openssl rand -hex 16
elif [ -f /dev/urandom ]; then
# Alternative method using /dev/urandom
od -An -N16 -tx1 /dev/urandom | tr -d ' \n'
else
# Basic (less secure) alternative
echo "$(date +%s)$(echo $)" | sha256sum | cut -c1-32
fi
}
# Check for required dependencies
check_deps() {
local missing=""
command -v openssl >/dev/null 2>&1 || missing="$missing openssl"
command -v curl >/dev/null 2>&1 || missing="$missing curl"
if [ -n "$missing" ]; then
echo ":x: Missing critical commands:$missing"
echo "Install OpenSSL and cURL to use this script"
exit 1
fi
}
check_deps
# Request parameters
METHOD=${1:-"GET"}
PATH=${2:-"/api/v1/payouts"}
API_BASE_URL=${3:-"https://api.example.com"}
# Validate required variables
if [ -z "$PUBLIC_ID" ] || [ -z "$PRIVATE_KEY_BASE64" ]; then
echo ":x: Error: PUBLIC_ID and PRIVATE_KEY_BASE64 must be set"
echo "export PUBLIC_ID=\"your_public_id\""
echo "export PRIVATE_KEY_BASE64=\"your_private_key_base64\""
exit 1
Fi
# Step 1: Prepare data
TIMESTAMP=$(date +%s)000 # Current time in milliseconds
NONCE=$(generate_nonce) # Random 16-character string
# Step 2: Create string to sign
STRING_TO_SIGN="${METHOD}${PATH}${TIMESTAMP}${NONCE}${PUBLIC_ID}"
echo "=== Debugging Info ==="
echo "Method: $METHOD"
echo "Path: $PATH"
echo "Timestamp: $TIMESTAMP"
echo "Nonce: $NONCE"
echo "Public ID: $PUBLIC_ID"
echo "String to sign: $STRING_TO_SIGN"
echo "=========================="
# Create a temporary PEM file
TEMP_KEY="/tmp/temp_private_key_$.pem"
echo "-----BEGIN PRIVATE KEY-----" > "$TEMP_KEY"
# Split Base64 string into 64-character lines
if command -v fold >/dev/null 2>&1; then
echo "$PRIVATE_KEY_BASE64" | fold -w 64 >> "$TEMP_KEY"
else
split_base64 "$PRIVATE_KEY_BASE64" >> "$TEMP_KEY"
fi
echo "-----END PRIVATE KEY-----" >> "$TEMP_KEY"
# Step 3: Generate signature
if command -v openssl >/dev/null 2>&1 && command -v base64 >/dev/null 2>&1; then
SIGNATURE=$(echo -n "$STRING_TO_SIGN" | openssl dgst -sha256 -sign "$TEMP_KEY" 2>/dev/null | base64 -w 0 2>/dev/null || base64)
else
echo ":x: Error: OpenSSL or base64 not available"
rm -f "$TEMP_KEY" 2>/dev/null
exit 1
fi
# Delete temporary file
rm -f "$TEMP_KEY" 2>/dev/null
if [ -z "$SIGNATURE" ]; then
echo ":x: Failed to generate signature"
exit 1
fi
echo "Signature: $SIGNATURE"
echo "=========================="
# Step 4: Send the request
if command -v curl >/dev/null 2>&1; then
curl -X "$METHOD" "${API_BASE_URL}${PATH}" \
-H "x-access-token-key: $PUBLIC_ID" \
-H "x-timestamp: $TIMESTAMP" \
-H "x-nonce: $NONCE" \
-H "x-signature: $SIGNATURE" \
-H "Content-Type: application/json" \
-v
else
echo ":x: cURL not available. Use the following headers in your request:"
echo "x-access-token-key: $PUBLIC_ID"
echo "x-timestamp: $TIMESTAMP"
echo "x-nonce: $NONCE"
echo "x-signature: $SIGNATURE"
fi
If you only need to generate a signature without sending a request:
bash
#!/bin/bash
# sign_only.sh - generates only the signature
METHOD=${1:-"GET"}
PATH=${2:-"/api/v1/payouts"}
if [ -z "$PUBLIC_ID" ] || [ -z "$PRIVATE_KEY_BASE64" ]; then
echo "Set PUBLIC_ID and PRIVATE_KEY_BASE64"
exit 1
fi
TIMESTAMP=$(date +%s)000
NONCE=$(openssl rand -hex 16 2>/dev/null || echo "$(date +%s)$" | sha256sum | cut -c1-32)
STRING_TO_SIGN="${METHOD}${PATH}${TIMESTAMP}${NONCE}${PUBLIC_ID}"
# Create a temporary key
TEMP_KEY="/tmp/key_$.pem"
echo "-----BEGIN PRIVATE KEY-----" > "$TEMP_KEY"
echo "$PRIVATE_KEY_BASE64" | fold -w 64 >> "$TEMP_KEY" 2>/dev/null || {
# Alternative to using fold
echo "$PRIVATE_KEY_BASE64" | sed 's/.\{64\}/&\n/g' >> "$TEMP_KEY"
}
echo "-----END PRIVATE KEY-----" >> "$TEMP_KEY"
SIGNATURE=$(echo -n "$STRING_TO_SIGN" | openssl dgst -sha256 -sign "$TEMP_KEY" | base64 -w 0)
rm -f "$TEMP_KEY"
echo "Headers for your HTTP client:"
echo "x-access-token-key: $PUBLIC_ID"
echo "x-timestamp: $TIMESTAMP"
echo "x-nonce: $NONCE"
echo "x-signature: $SIGNATURE"
bash
# Make the script executable:
chmod +x sign_request.sh
# Check for dependencies:
./sign_request.sh
# GET request
./sign_request.sh GET "/api/v1/payouts"
# POST request
./sign_request.sh POST "/api/v1/payouts" "https://api.example.com"
# Signature only (with no request):
chmod +x sign_only.sh
./sign_only.sh GET "/api/v1/payouts"
bash
# 1. Set your variables
PUBLIC_ID="your_public_id"
PRIVATE_KEY_BASE64="your_private_key_base64"
METHOD="GET"
PATH="/api/v1/payouts"
# 2. Prepare data
TIMESTAMP=$(date +%s)000
NONCE="a1b2c3d4e5f67890" # 16 random hex characters
# 3. Create the string to sign
STRING_TO_SIGN="${METHOD}${PATH}${TIMESTAMP}${NONCE}${PUBLIC_ID}"
echo "String to sign: $STRING_TO_SIGN"
# 4. Create the PEM file
echo "-----BEGIN PRIVATE KEY-----" > key.pem
echo "$PRIVATE_KEY_BASE64" | sed 's/.\{64\}/&\n/g' >> key.pem
echo "-----END PRIVATE KEY-----" >> key.pem
# 5. Generate the signature
echo -n "$STRING_TO_SIGN" | openssl dgst -sha256 -sign key.pem | base64 -w 0
# The result is your signature for the x-signature header
# 6. Clean up the temporary file
rm key.pem
Regardless of programming language, follow this pipeline:
Base64 key → Decode → Binary data → Load as ECDSA P-256 key
2. Data Preparation
Current time → Convert to milliseconds (timestamp)
Random bytes → Convert to hex string (nonce)
3. Create the String
METHOD + PATH + TIMESTAMP + NONCE + PUBLIC_ID
(No separators; one continuous string)
4. Signature
String → UTF-8 bytes → ECDSA-SHA256 signature → DER format → JOSE format → Base64
5. HTTP Headers
x-access-token-key: [PUBLIC_ID]
x-timestamp: [TIMESTAMP]
x-nonce: [NONCE]
x-signature: [BASE64_SIGNATURE]
Verification of the String to Sign
Ensure the string is correctly formed, as this is a common source of issues:
bash
#Example of a correct string:
# GET/api/v1/payouts1703001234567a1b2c3d4e5f67890token_abc123
#Common mistakes:
#:x: GET /api/v1/payouts 1703001234567 a1b2c3d4e5f67890 token_abc123 (contains spaces)
#:x: get/api/v1/payouts1703001234567a1b2c3d4e5f67890token_abc123 (method in lowercase)
#:x: GET/api/v1/payouts?limit=101703001234567a1b2c3d4e5f67890token_abc123 (contains query parameters)
Validation of the Timestamp
bash
# Ensure the timestamp is in the correct format
TIMESTAMP=$(date +%s)000
echo "Current timestamp: $TIMESTAMP"
# Timestamp must not be older than 5 minutes
CURRENT_TIME=$(date +%s)000
TIME_DIFF=$((CURRENT_TIME - TIMESTAMP))
if [ $TIME_DIFF -gt 300000 ]; then
echo ":warning: Timestamp is too old"
fi
Validation of the Key Format
bash
# Check if the Base64 key is valid
echo "$PRIVATE_KEY_BASE64" | base64 -d > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo ":white_check_mark: Base64 key is valid"
else
echo ":x: Invalid Base64 key"
fi
timestamp_is_absent: Missing x-timestamp header;
timestamp_is_old: Timestamp is older than 5 minutes;
nonce_is_absent: Missing x-nonce header;
signature_is_absent: Missing x-signature header;
invalid_signature: Invalid signature (check the algorithm);
timestamp_already_used: This timestamp+nonce combination has been used before.
If you have any questions about the Access token, do not hesitate to reach out to our support team.
You might also be interested in our guides on account verification and webhooks.
Share on: