Examples of sending a request
There are the Node.js, PHP, Python, and Java code examples which are easy to copy. You can find the detailed manual of sending the signed request here.
- Node.js
- PHP
- Python
- Java
note
Node.js >= 15 is required.
const crypto = require('crypto');
const fetch = require('node-fetch');
const API_PUBLIC_KEY = '<Your public API key>';
const API_PRIVATE_KEY = '<Your private API key>';
const privateKeyObject = crypto.createPrivateKey({
key: API_PRIVATE_KEY,
type: 'pkcs1',
format: 'pem',
encoding: 'base64',
});
const path = 'https://fiat-api.changelly.com/v1/validate-address';
const message = {
"currency": "XRP",
"walletAddress": "rwpMvfxoodXggJ1g4qv6MWAPQqWDwQyHUW",
"walletExtraId": "1234hg"
};
const payload = path + JSON.stringify(message);
const signature = crypto.sign('sha256', Buffer.from(payload), privateKeyObject).toString('base64');
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': API_PUBLIC_KEY,
'X-Api-Signature': signature,
},
body: JSON.stringify(message),
};
fetch(path, options).then(response => {
if (response.ok) {
return response.json();
}
throw new Error(`Request error: ${response.status} ${response.statusText}`);
}).then((response) => {
console.log('Successful response: ', response);
}).catch(error => {
console.error(error);
});
note
PHP 8 is required.
<?php
$API_PUBLIC_KEY = '<Your public API key>';
$API_PRIVATE_KEY = '<Your private API key>';
$private_key_object = base64_decode($API_PRIVATE_KEY);
$private_key_object = openssl_pkey_get_private($private_key_object);
$path = 'https://fiat-api.changelly.com/v1/validate-address';
$message = [
"currency" => "XRP",
"walletAddress" => "rwpMvfxoodXggJ1g4qv6MWAPQqWDwQyHUW",
"walletExtraId" => "1234hg"
];
$payload = $path . json_encode($message, JSON_FORCE_OBJECT);
openssl_sign($payload, $signature, $private_key_object, OPENSSL_ALGO_SHA256);
$signature = base64_encode($signature);
$request_headers = [
'Content-Type: application/json',
'X-Api-Key: ' . $API_PUBLIC_KEY,
'X-Api-Signature: ' . $signature,
];
$request_body = json_encode($message, JSON_FORCE_OBJECT);
$request = curl_init($path);
curl_setopt($request, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($request, CURLOPT_POSTFIELDS, $request_body);
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_HTTPHEADER, $request_headers);
$response = curl_exec($request);
$http_status = curl_getinfo($request, CURLINFO_HTTP_CODE);
curl_close($request);
if ($http_status >= 200 && $http_status < 300) {
echo 'Successful response: ' . $response;
} else {
echo 'Request error: ' . $http_status . ' ' . $response;
}
?>
note
Python version 3.11 is recommended.
import base64
import json
import logging
from typing import Any, Optional, cast
import requests
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
logging.basicConfig(level='INFO', format='%(asctime)s %(levelname)s (%(levelno)s) %(message)s')
class ChangellyFiatApiClient:
BASE_URL = 'https://fiat-api.changelly.com'
def __init__(
self,
public_key: str,
private_key: str,
api_version: str = 'v1',
) -> None:
self._api_version = api_version
self._public_key = public_key
self._private_key = self._load_private_key(private_key)
def _load_private_key(self, private_key_base64: str) -> RSAPrivateKey:
return cast(
RSAPrivateKey,
serialization.load_pem_private_key(
base64.b64decode(private_key_base64),
password=None,
),
)
def _request(self, method: str, message: dict[str, Any]) -> dict:
path = f'{self.BASE_URL}/{self._api_version}/{method}'
headers = self._get_headers(path, message)
response = requests.post(path, headers=headers, json=message)
if response.ok:
response_data = response.json()
logging.info(f'Response for {method}: {response_data}')
return response_data
raise Exception(f'Changelly Fiat Api request error for method {method}: {response.status_code} {response.text}')
def _get_headers(self, path: str, message: dict[str, Any]) -> dict:
payload = path + json.dumps(message, separators=(',', ':'))
return {
'Content-Type': 'application/json',
'X-Api-Key': self._public_key,
'X-Api-Signature': self._get_signature(payload),
}
def _get_signature(self, payload: str) -> str:
signature = self._private_key.sign(
payload.encode(),
padding.PKCS1v15(),
hashes.SHA256(),
)
return base64.b64encode(signature).decode()
def validate_address(self, currency: str, address: str, extra_id: Optional[str] = None) -> dict:
message = {
'currency': currency,
'walletAddress': address,
}
if extra_id: # extra_id is required for wallet addresses of currencies that use an additional ID for transaction processing (XRP, XLM, EOS, BNB)
message['walletExtraId'] = extra_id
return self._request('validate-address', message)
api = ChangellyFiatApiClient(
public_key='<Your public API key>',
private_key='<Your private API key>',
)
response = api.validate_address(
currency='XRP',
address='rwpMvfxoodXggJ1g4qv6MWAPQqWDwQyHUW',
extra_id='1234hg',
)
note
Java version >= 8 is required.
Before using the Java example code, you should transform a private key from pkcs1 to pkcs8 and then work with this transformed key.
To transform, you can use such a console command:
openssl pkcs8 -topk8 -inform PEM -in private_key_pkcs1.pem \
-outform PEM -nocrypt -out private_key_pkcs8.pem
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.JSONObject;
public class Example {
private static final String API_PUBLIC_KEY = "API_PUBLIC_KEY";
private static final String API_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" +
"API_PRIVATE_KEY\n" +
"-----END PRIVATE KEY-----\n";
private static final String PATH = "https://fiat-api.changelly.com/v1/validate-address";
public static void main(String[] args) {
try {
// Convert the private key from PEM format
String privateKeyPEM = API_PRIVATE_KEY.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\s+", "");
byte[] decodedKey = Base64.getDecoder().decode(privateKeyPEM);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
// Prepare the message
JSONObject message = new JSONObject();
message.put("currency", "XRP");
message.put("walletAddress", "rwpMvfxoodXggJ1g4qv6MWAPQqWDwQyHUW");
message.put("walletExtraId", "1234hg");
String payload = PATH + message.toString();
// Sign the payload
Signature signer = Signature.getInstance("SHA256withRSA");
signer.initSign(privateKey);
signer.update(payload.getBytes());
byte[] signatureBytes = signer.sign();
String signature = Base64.getEncoder().encodeToString(signatureBytes);
// Prepare the request
URL url = new URL(PATH);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("X-Api-Key", API_PUBLIC_KEY);
connection.setRequestProperty("X-Api-Signature", signature);
connection.setDoOutput(true);
// Write the request body
try (OutputStream os = connection.getOutputStream()) {
os.write(message.toString().getBytes());
}
// Get the response
int responseCode = connection.getResponseCode();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED) {
System.out.println("Successful response: " + response);
} else {
System.err.println("Request error: " + responseCode + " " + connection.getResponseMessage());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Important! See paragraphs 7 and 8 in the Manual of sending a request for advice on signing API requests.