For information on changes for our US clients, please visit our Support Center article.

What is the authentication algorithm for private endpoints?
API authentication is required whenever an API call accesses an account via one of the private API methods.
For example, the account management methods like Balance, TradeBalance and OpenOrders; the trading methods AddOrder and CancelOrder; and the funding methods like DepositAddresses and WithdrawInfo, are all private API methods that would require API authentication.

API Keys and Cryptographic Signatures

API authentication is based upon a public/private key pair (collectively known as an API key) and a cryptographic signature using hash algorithms such as SHA256 and HMAC SHA512.
An example API key would consist of a public and private key similar to the following:
text

Plaintext

Public Key: CJbfPw4tnbf/9en/ZmpewCTKEwmmzO18LXZcHQcu7HPLWre4l8+V9I3y
 
 Private Key: FRs+gtq09rR7OFtKj9BGhyOGS3u5vtY/EdiIBO9kD8NFtRX7w7LeJDSrX6cq1D8zmQmGkWFjksuhBvKOAWJohQ==
Note that these examples cannot be used as they are not associated with any Kraken account.
Cryptographic signatures are created in real time by the API client code. The data for the API call is passed through a series of hash and message authentication algorithms which securely signs the data using the API secret (the private part of the API key).

HTTP Headers

The API key and signature are provided to the API via the custom HTTP headers API-Key and API-Sign.
The API key is used to identify which account is being accessed, hence the key value is identical for every API call. The cryptographic signature is used to authenticate the API call and is calculated using variable values (such as the nonce), hence the signature value is different for every API call.
Examples of the API-Key and API-Sign HTTP headers are as follows:
  • API-Key: CJbfPw4tnbf/9en/ZmpewCTKEwmmzO18LXZcHQcu7HPLWre4l8+V9I3y
  • API-Sign: RdQzoXRC83TPmbERpFj0XFVArq0Hfadm0eLolmXTuN2R24hzIqtAnF/f7vSfW1tGt7xQOn8bjm+Ht+X0KrMwlA==
Note that the API-Key value is exactly the same as the public key shown above, but that the API-Sign value (the signature) is different to the private key shown above and will change to a new value for each API call.

Signature Pseudo Code

Our API documentation states that the API-Sign value is a "message signature using HMAC-SHA512 of (URI path + SHA256(nonce + POST data)) and base64 decoded secret API key", which can be separated into several distinct parts as follows:
Variables
  • URI path = URL of API call without 'https://api.kraken.com'.
  • nonce = A unique identifier which must increase in value with each API call (often a UNIX timestamp, which is the current time in seconds (or milliseconds for higher resolution) since January 1st 1970).
  • POST data = Form encoded name/value pairs of the nonce and the API method parameters.
Examples of the variables for a call to the TradeBalance method are as follows (note that all of the values are string values regardless of what the values represent):
  • URI path = "/0/private/TradeBalance"
  • nonce = "1540973848000"
  • POST data = "nonce=1540973848000&asset=xbt"
Algorithm
  • Calculate the SHA256 of the nonce and the POST data.
  • Decode the API secret (the private part of the API key) from base64.
  • Calculate the HMAC of the URI path and the SHA256, using SHA512 as the HMAC hash and the decoded API secret as the HMAC key.
  • Encode the HMAC into base64.
An example of the algorithm using the variables shown above is as follows:
  • Base64Encode(HMAC-SHA512 of ("/0/private/TradeBalance" + SHA256("1540973848000nonce=1540973848000&asset=xbt")) using Base64Decode("FRs+gtq09rR7OFtKj9BGhyOGS3u5vtY/EdiIBO9kD8NFtRX7w7LeJDSrX6cq1D8zmQmGkWFjksuhBvKOAWJohQ==") as the HMAC key
The result is the API-Sign value.

Example Code

Minimal (no error checking) but fully functional examples of generating an API authentication signature for the TradeBalance API endpoint are as follows:
python

Python

# Import required Python libraries
import time
import base64
import hashlib
import hmac

# Decode API private key from base64 format displayed in account management
api_secret = base64.b64decode(
    "FRs+gtq09rR7OFtKj9BGhyOGS3u5vtY/EdiIBO9kD8NFtRX7w7LeJDSrX6cq1D8zmQmGkWFjksuhBvKOAWJohQ=="
)

# Variables (API endpoint, nonce and HTTP POST data)
api_path = "/0/private/TradeBalance"
api_nonce = str(int(time.time() * 1000))
api_post = "nonce=" + api_nonce + "&asset=xbt"

# Cryptographic hash algorithms
api_sha256 = hashlib.sha256(api_nonce.encode('utf-8') + api_post.encode('utf-8'))
api_hmac = hmac.new(
    api_secret,
    api_path.encode('utf-8') + api_sha256.digest(),
    hashlib.sha512
)

# Encode signature into base64 format used in API-Sign value
api_signature = base64.b64encode(api_hmac.digest())

# API authentication signature for use in API-Sign HTTP header
print(api_signature.decode())

NodeJS
javascript

Javascript

// Import required NodeJS libraries
const crypto = require('crypto');

// Decode API private key from base64 format displayed in account management
const apiSecret = Buffer.from(
  'FRs+gtq09rR7OFtKj9BGhyOGS3u5vtY/EdiIBO9kD8NFtRX7w7LeJDSrX6cq1D8zmQmGkWFjksuhBvKOAWJohQ==',
  'base64'
);

// Variables (API endpoint, nonce and HTTP POST data)
const apiPath = '/0/private/TradeBalance';
const apiNonce = Date.now().toString();
const apiPost = `nonce=${apiNonce}&asset=xbt`;

// Cryptographic hash algorithms
const apiSha256 = crypto.createHash('sha256').update(`${apiNonce}${apiPost}`).digest();
const apiSha512 = crypto.createHmac('sha512', apiSecret).update(apiPath).update(apiSha256).digest();

// Encode signature into base64 format used in API-Sign value
const apiSignature = apiSha512.toString('base64');

// API authentication signature for use in API-Sign HTTP header
console.log(apiSignature);

PHP
php

PHP

// Decode API private key from base64 format displayed in account management
$apiSecret = base64_decode('FRs+gtq09rR7OFtKj9BGhyOGS3u5vtY/EdiIBO9kD8NFtRX7w7LeJDSrX6cq1D8zmQmGkWFjksuhBvKOAWJohQ==');

// Variables (API endpoint, nonce and HTTP POST data)
$apiPath = '/0/private/TradeBalance';
$apiNonce = explode(' ', microtime());
$apiNonce = $apiNonce[1] . substr($apiNonce[0], 2, 3);
$apiPost = "nonce={$apiNonce}&asset=xbt";

// Cryptographic hash algorithms
$apiSha256 = hash('sha256', $apiNonce . $apiPost, true);
$apiSha512 = hash_hmac('sha512', $apiPath . $apiSha256, $apiSecret, true);

// Encode signature into base64 format used in API-Sign value
$apiSignature = base64_encode($apiSha512);

// API authentication signature for use in API-Sign HTTP header
print $apiSignature;