API Key usage
Important: Trading Election Markets
Election markets can ONLY be traded with the new url. All endpoints remain the same. Please authenticate again as tokens cannot be shared.
Election Markets:
api.elections.kalshi.com/trade-api/v2
Other Markets:trading-api.kalshi.com/trade-api/v2
Generating an API Key
Access the Account Settings Page:
Log in to your account and navigate to the “Account Settings” page. You can typically find this option by clicking on your profile picture or account icon in the top-right corner of the application.
Generate a New API Key:
In the “Profile Settings” page https://kalshi.com/account/profile, locate the “API Keys” section. Click on the “Create New API Key” button. This action will generate a new API key in the RSA_PRIVATE_KEY format.
Store Your API Key and Key ID:
After generating the key, you will be presented with:
• Private Key: This is your secret key in RSA_PRIVATE_KEY format.
• Key ID: This is a unique identifier associated with your private key.
Important: For security reasons, the private key will not be stored by our service, and you will not be able to retrieve it again once this page is closed. Please make sure to securely copy and save the private key immediately. The key will also be downloaded as txt file with the name provided.
Using a API Key
Each request to Kalshi trading api will need to be signed with the private key generated above.
The following header values will need to be provided with each request:
KALSHI-ACCESS-KEY
- the Key ID
KALSHI-ACCESS-TIMESTAMP
- the request timestamp in ms
KALSHI-ACCESS-SIGNATURE
- request hash signed with private key
The above signature is generated by signing a concatenation of the timestamp, the HTTP method and the path.
Sample code for generating the required headers is below (alternatively use our starter code here):
Python
Load the private key stored in a file
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
def load_private_key_from_file(file_path):
with open(file_path, "rb") as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None, # or provide a password if your key is encrypted
backend=default_backend()
)
return private_key
Sign text with private key
import base64
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.exceptions import InvalidSignature
def sign_pss_text(private_key: rsa.RSAPrivateKey, text: str) -> str:
# Before signing, we need to hash our message.
# The hash is what we actually sign.
# Convert the text to bytes
message = text.encode('utf-8')
try:
signature = private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.DIGEST_LENGTH
),
hashes.SHA256()
)
return base64.b64encode(signature).decode('utf-8')
except InvalidSignature as e:
raise ValueError("RSA sign PSS failed") from e
Send request
import requests
import datetime
# Get the current time
current_time = datetime.datetime.now()
# Convert the time to a timestamp (seconds since the epoch)
timestamp = current_time.timestamp()
# Convert the timestamp to milliseconds
current_time_milliseconds = int(timestamp * 1000)
timestampt_str = str(current_time_milliseconds)
# Load the RSA private key
private_key = load_private_key_from_file('kalshi-key-2.key')
method = "GET"
base_url = 'https://demo-api.kalshi.co'
path='/trade-api/v2/portfolio/balance'
msg_string = timestampt_str + method + path
sig = sign_pss_text(private_key, msg_string)
headers = {
'KALSHI-ACCESS-KEY': 'a952bafb-12dd-4955-9e7c-3895265e812d',
'KALSHI-ACCESS-SIGNATURE': sig,
'KALSHI-ACCESS-TIMESTAMP': timestampt_str
}
response = requests.get(base_url + path, headers=headers)
print("Status Code:", response.status_code)
print("Response Body:", response.text)
JS
const fs = require('fs');
const crypto = require('crypto');
const axios = require('axios');
function loadPrivateKeyFromFile(filePath) {
const keyData = fs.readFileSync(filePath, 'utf8');
const privateKey = crypto.createPrivateKey({
key: keyData,
format: 'pem',
// If your key is encrypted, you'd need to provide a passphrase here
// passphrase: 'your-passphrase'
});
return privateKey;
}
function signPssText(privateKey, text) {
// Before signing, we need to hash our message.
// The hash is what we actually sign.
// Convert the text to bytes
const message = Buffer.from(text, 'utf-8');
try {
const signature = crypto.sign(
'sha256',
message,
{
key: privateKey,
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST
}
);
return signature.toString('base64');
} catch (error) {
throw new Error("RSA sign PSS failed: " + error.message);
}
}
// Get the current time
const currentTime = new Date();
// Convert the time to a timestamp (milliseconds since the epoch)
const currentTimeMilliseconds = currentTime.getTime();
const timestampStr = currentTimeMilliseconds.toString();
// Load the RSA private key
const privateKey = loadPrivateKeyFromFile('baseKey.txt');
const method = "POST";
const baseUrl = 'https://demo-api.kalshi.co';
const path = '/trade-api/v2/portfolio/orders';
const body = {"action": "buy", "client_order_id": "1fa1be86-3f8e-49be-8c1e-1e46ea490d59", "count": 3, "side": "yes", "ticker": "HOMEUSY-24-T4", "type": "limit", "yes_price": 30};
const msgString = timestampStr + method + path;
console.log(msgString);
const sig = signPssText(privateKey, msgString);
const headers = {
'KALSHI-ACCESS-KEY': '164c4e3e-f653-4847-b962-bc4975b91ddc',
'KALSHI-ACCESS-SIGNATURE': sig,
'KALSHI-ACCESS-TIMESTAMP': timestampStr,
'Content-Type': 'application/json'
};
axios.post(baseUrl + path, body, { headers })
.then(response => {
console.log("Status Code:", response.status);
console.log("Response Body:", response.data);
})
.catch(error => {
console.error("Error:", error.message);
console.log(error.response.data);
});