Send a request
In this article, you can learn how to send a request to Fiat API.
General flow of sending a request
The section contains a general flow of sending a request based on Node.js.
-
Find a module that supports an RSA signature generation with the SHA256 hashing algorithm. For Node.js, it is a
cryptomodule. -
Find a module that allows sending HTTP requests. For Node.js, it is a
node-fetchmodule. -
Install the necessary modules in any convenient way. For example, with npm:
npm install crypto
npm install node-fetch
- Import the modules to your code:
const crypto = require('crypto');
const fetch = require('node-fetch');
- Define the variables for your private and public keys:
const API_PUBLIC_KEY = '<Your public API key>';
const API_PRIVATE_KEY = '<Your private API key>';
- Create a private key object with the following type, format, and encoding:
const privateKeyObject = crypto.createPrivateKey({
key: API_PRIVATE_KEY,
type: 'pkcs1',
format: 'pem',
encoding: 'base64',
});
- Define the variables for the URL and body message of the API method you want to request:
const path = 'https://fiat-api.changelly.com/v1/validate-address';
const message = {
"currency": "XRP",
"walletAddress": "rwpMvfxood******************WDwQyHUW",
"walletExtraId": "1234hg"
};
To provide path or query request parameters, specify them in the path variable:
const path = 'https://fiat-api.changelly.com/v1/currencies?type=crypto';
This message example is applied to the POST request. If you want to send GET request, you should make the message empty:
const message = {};
If you delete the message variable, you encounter an error.
- Concatenate the
pathand themessageobject into one string:
const payload = path + JSON.stringify(message);
- Create a signature used as
X-Api-Signatureheader:
const signature = crypto.sign('sha256', Buffer.from(payload), privateKeyObject).toString('base64');
crypto.sign takes as input 3 parameters:
- hashing algorithm –
sha256. - request data –
Buffer.from(payload). - private key object in the desired format –
privateKeyObject.
crypto.sign returns signature in a buffer. You need to convert it to base64 format.
- Create an
optionsobject that contains info for an API request, such as a HTTP method, headers, and body:
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': API_PUBLIC_KEY,
'X-Api-Signature': signature,
},
body: JSON.stringify(message),
};
- Send a request:
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);
});
Full Node.js sample
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": "rwpMvfxood******************WDwQyHUW",
"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);
});
Samples for sending a request
Feel free to copy the following PHP, Python, and Java samples.
- PHP
- Python
- Java
Requires PHP 8.
<?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" => "rwpMvfxood******************WDwQyHUW",
"walletExtraId" => "1234hg"
];
$json_body = json_encode($message, JSON_FORCE_OBJECT | JSON_UNESCAPED_SLASHES);
$payload = $path . $json_body;
$request_body = $json_body;
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 = 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;
}
?>
Requires Python 3.11.
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='rwpMvfxood******************WDwQyHUW',
extra_id='1234hg',
)
Requires Java >= 8.
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", "rwpMvfxood******************WDwQyHUW");
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();
}
}
}