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:
- 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).
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: vcDrflw2QAYr0x7zT6HFNhyDYz2Jqex0xSN7htHoY0ggvEkyNsgSXBEgXuYEU9Gy90IFXtES9OGknI0yo1cl9Q==
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:
- 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"
- 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.
Minimal (no error checking) but fully functional examples of generating an API authentication signature for the TradeBalance API endpoint are as follows:
# 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())
//Import required NodeJS libraries const crypto = require('crypto') // Decode API private key from base64 format displayed in account management var api_secret = Buffer.from('FRs+gtq09rR7OFtKj9BGhyOGS3u5vtY/EdiIBO9kD8NFtRX7w7LeJDSrX6cq1D8zmQmGkWFjksuhBvKOAWJohQ==', 'base64') // Variables (API endpoint, nonce, and HTTP POST data) var api_path = "/0/private/TradeBalance" var api_nonce = Date.now().toString() var api_post = "nonce=" + api_nonce + "&asset=xbt" // Cryptographic hash algorithms var api_sha256 = crypto.createHash('sha256').update(api_nonce + api_post).digest() var api_sha512 = crypto.createHmac('sha512', api_secret).update(api_path).update(api_sha256).digest() // Encode signature into base64 format used in API-Sign value api_signature = api_sha512.toString('base64') // API authentication signature for use in API-Sign HTTP header console.log(api_signature)