Skip to main content

Authentication

Sign every request with the current API key flow and EXN-* headers.

How signed requests work

The client signs request metadata with an Ed25519 private key. The server validates the API key, timestamp, signed payload fields, path and query, body hash, signature, and access scope.

Signed request headers

HeaderRequiredPurpose
EXN-API-KEYYesPublic API key identifier. Must match api_key inside EXN-DATA.
EXN-IDEMPOTENCY-KEYYesEmpty for signed GET requests; non-empty for mutating requests.
EXN-TIMESTAMPYesUnix timestamp in milliseconds. Must match timestamp inside EXN-DATA.
EXN-SIGN-VERSIONYesSignature protocol version. Current value: 1.
EXN-DATAYesBase64url-encoded signed payload without = padding.
EXN-SIGNYesEd25519 signature of the decoded EXN-DATA payload bytes, base64url-encoded without = padding.

Decoded EXN-DATA payload

FieldDescription
api_keySame value as EXN-API-KEY.
idempotency_keySame value as EXN-IDEMPOTENCY-KEY; empty string for signed GET requests.
timestampSame value as EXN-TIMESTAMP, in Unix milliseconds.
sign_versionSame value as EXN-SIGN-VERSION.
methodUppercase HTTP method, for example GET or POST.
pathRequest path with query string exactly as sent by the client.
body_hashSHA-256 hash of the exact request body, base64url-encoded without padding.

Signing rules

  • EXN-SIGN signs the decoded EXN-DATA payload bytes, not the base64url string.
  • EXN-DATA and EXN-SIGN must use base64url without = padding.
  • For requests without a body, body_hash is the SHA-256 hash of the empty byte sequence: 47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU.
  • Query strings must be signed exactly as transmitted. Do not reorder, normalize, or re-encode query parameters after signing.
  • Duplicate query parameters are rejected.
  • For signed GET requests, EXN-IDEMPOTENCY-KEY must be present with an empty value.
  • For mutating requests, EXN-IDEMPOTENCY-KEY must be non-empty.
  • Generate a fresh timestamp and signature for every request.

Example

curl -X GET "https://api.exness.com/v1/configuration/accounts/123456/account" \
-H "EXN-API-KEY: exnsk_your_public_api_key" \
-H "EXN-IDEMPOTENCY-KEY:" \
-H "EXN-TIMESTAMP: 1773656070123" \
-H "EXN-SIGN-VERSION: 1" \
-H "EXN-DATA: <base64url_encoded_payload>" \
-H "EXN-SIGN: <base64url_encoded_signature>"
{
"api_key": "exnsk_your_public_api_key",
"idempotency_key": "",
"timestamp": 1773656070123,
"sign_version": 1,
"method": "GET",
"path": "/v1/configuration/accounts/123456/account",
"body_hash": "47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU"
}
Signature helper validation

If you publish a fully runnable Python signing helper, validate the private-key format and serialization rules with API/Auth owners first.

Common auth errors

Codeerror_messageClient action
1000AUTH_INVALID_API_KEYCheck EXN-API-KEY, key expiry, and api_key inside EXN-DATA.
1001AUTH_INVALID_SIGNATURECheck EXN-DATA, EXN-SIGN, private key, payload serialization, body hash, timestamp, and base64url encoding.
1002AUTH_PERMISSION_DENIEDCheck account access, source IP restrictions, and API key permissions.