API Reference

API Key usage

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);
    });