Authentication
Authentication is crucial for ensuring that only authorized users can access private APIs. This document outlines the authentication mechanisms used for public and private APIs.
Public API
Public APIs do not require authentication. These interfaces are accessible to anyone without the need for any credentials.
No authentication is required for public interfaces.Private API
Private APIs require authentication to ensure that only authorized users can access them. Authentication is achieved using custom headers that include a timestamp and a signature.
Auth Header
The following headers must be included in the request to authenticate access to private APIs:
X-edgeX-Api-Timestamp
header
string
must
The timestamp when the request was made. This helps prevent replay attacks.
X-edgeX-Api-Signature
header
string
must
The signature generated using the private key and request details.
CURL Example
curl --location --request GET 'https://pro.edgex.exchange/api/v1/private/account/getPositionTransactionPage?filterTypeList=SETTLE_FUNDING_FEE&size=10&accountId=544159487963955214' \
--header 'X-edgeX-Api-Signature: 06d28020763542c0afc296dc8743797c6fda8ea9727745b57b671f70326dfed6077cd******************************aff3162e39d05d9df1c3ddf9648650382d6e62ff1076b14c0e6c687088d3917d8490e5412a080a6e9ea940c720ddd' \
--header 'X-edgeX-Api-Timestamp: 1736313025024'Signature Elements
The signature is generated using the following elements:
Signature Element
Description
X-edgeX-Api-Timestamp
The timestamp when the request was made. This is retrieved from the request header.
Request Method (Uppercase)
The HTTP method of the request, converted to uppercase (e.g., GET, POST).
Request Path
The URI path of the request (e.g., /api/v1/resource).
Request Parameter/Body
The query parameters or request body, sorted alphabetically.
Request Parameter To Signature Content
The request parameters are concatenated into a single string that forms the signature content. This string includes the timestamp, HTTP method, request path, and sorted query parameters or request body, ensuring the integrity and authenticity of the request.
For example, the following request parameters are concatenated into a single string:
1735542383256GET/api/v1/private/account/getPositionTransactionPageaccountId=543429922991899150&filterTypeList=SETTLE_FUNDING_FEE&size=10
How To GET Your Private Key
To sign messages, you need to obtain your private key. This key is used to generate signatures that authorize various actions on the platform.

Warning: Keep your private key secure and never share it with anyone. Anyone with access to your private key can sign messages on your behalf.
Private API Example
Private API Auth Signature: This is used for authentication. We do not want the hash computation to consume excessive CPU resources. Therefore, this will use SHA3 to hash the request body string before signing.
We provide SDKs in multiple languages to help you get started quickly.
Java Example
Below is a Java implementation of the Ecdsa signature algorithm. This example demonstrates how to sign a GET request using a private key.
import java.math.BigInteger;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.time.Duration;
import org.web3j.abi.TypeEncoder;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.crypto.Hash;
import org.web3j.utils.Numeric;
import org.web3j.abi.datatypes.generated.Uint256;
import com.starkbank.ellipticcurve.utils.RandomInteger;
import com.starkbank.ellipticcurve.PrivateKey;
import com.starkbank.ellipticcurve.Curve;
import com.starkbank.ellipticcurve.Signature;
import com.starkbank.ellipticcurve.Math;
import com.starkbank.ellipticcurve.Point;
public class EcdsaSignatureDemo {
private static final BigInteger K_MODULUS = Numeric
.toBigInt("0x0800000000000010ffffffffffffffffb781126dcae7b2321e66a241adc64d2f");
private static Curve secp256k1 = new Curve(BigInteger.ONE,
new BigInteger("3141592653589793238462643383279502884197169399375105820974944592307816406665"),
new BigInteger("3618502788666131213697322783095070105623107215331596699973092056135872020481"),
new BigInteger("3618502788666131213697322783095070105526743751716087489154079457884512865583"),
new BigInteger("874739451078007766457464989774322083649278607533249481151382481072868806602"),
new BigInteger("152666792071518830868575557812948353041420400780739481342941381225525861407"),
"secp256k1", new long[] { 1L, 3L, 132L, 0L, 10L });
// replace with your account id and private key
private static final String AccountID = "****";
private static final String PrivateKey = "****";
public static void main(String[] args) {
String host = "https://pro.edgex.exchange";
String path = "/api/v1/private/account/getAccountById";
String method = "GET";
String param = "accountId=" + AccountID;
long timestamp = System.currentTimeMillis();
String message = timestamp + method + path + param;
String signature = signParams(message);
String requestUrl = host + path + "?" + param;
try {
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(30))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(requestUrl))
.timeout(Duration.ofSeconds(30))
.header("X-edgeX-Api-Signature", signature)
.header("X-edgeX-Api-Timestamp", String.valueOf(timestamp))
.header("Content-Type", "application/json")
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Response Status: " + response.statusCode());
System.out.println("Response Body: " + response.body());
} catch (Exception e) {
System.err.println("Request failed: " + e.getMessage());
e.printStackTrace();
}
}
private static String signParams(String message) {
String msg = TypeEncoder.encodePacked(new Utf8String(message));
BigInteger msgHash = Numeric.toBigInt(Hash.sha3(Numeric.hexStringToByteArray(msg)));
msgHash = msgHash.mod(K_MODULUS);
// Please replace it with a real private key when actually using
String privateKeyHex = PrivateKey;
if (privateKeyHex.startsWith("0x")) {
privateKeyHex = privateKeyHex.substring(2);
}
BigInteger mySecretKey = new BigInteger(privateKeyHex, 16);
PrivateKey privateKey = new PrivateKey(secp256k1, mySecretKey);
Signature signature = sign(msgHash, privateKey);
return TypeEncoder.encodePacked(new Uint256(signature.r)) +
TypeEncoder.encodePacked(new Uint256(signature.s)) +
TypeEncoder.encodePacked(new Uint256(privateKey.publicKey().point.y));
}
private static Signature sign(BigInteger numberMessage, PrivateKey privateKey) {
Curve curve = privateKey.curve;
BigInteger randNum = RandomInteger.between(BigInteger.ONE, curve.N);
Point randomSignPoint = Math.multiply(curve.G, randNum, curve.N, curve.A, curve.P);
BigInteger r = randomSignPoint.x.mod(curve.N);
BigInteger s = numberMessage.add(r.multiply(privateKey.secret)).multiply(Math.inv(randNum, curve.N))
.mod(curve.N);
return new Signature(r, s);
}
}<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>4.10.3</version>
</dependency>
<dependency>
<groupId>com.starkbank.ellipticcurve</groupId>
<artifactId>starkbank-ecdsa</artifactId>
<version>1.0.2</version>
</dependency>Request Body To Body String Code Example
The following Java code example demonstrates how to convert a JSON request body into a sorted string format suitable for signature generation:
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import java.util.stream.Collectors;
public class RequestBodyToString {
private static final String EMPTY_STRING = "";
private static String getValue(JsonElement valueJson) {
if (valueJson.isJsonNull()) {
return EMPTY_STRING;
} else if (valueJson.isJsonPrimitive()) {
return valueJson.getAsString();
} else if (valueJson.isJsonArray()) {
JsonArray valueArray = valueJson.getAsJsonArray();
if (valueArray.isEmpty()) {
return EMPTY_STRING;
}
List<String> values = new ArrayList<>();
for (JsonElement itemValue : valueArray) {
values.add(getValue(itemValue));
}
return String.join("&", values);
} else if (valueJson.isJsonObject()) {
TreeMap<String, String> sortedDataMap = new TreeMap<>();
JsonObject valueJsonObj = valueJson.getAsJsonObject();
for (String key : valueJsonObj.keySet()) {
sortedDataMap.put(key, getValue(valueJsonObj.get(key)));
}
return sortedDataMap.keySet().stream()
.map(key -> key + "=" + sortedDataMap.get(key))
.collect(Collectors.joining("&"));
}
return EMPTY_STRING;
}
}Signature Algorithm
The signature algorithm used is Ecdsa (Elliptic Curve Digital Signature Algorithm).
Last updated