curl --request POST \
--url https://external-api.kalshi.com/trade-api/v2/api_keys \
--header 'Content-Type: application/json' \
--header 'KALSHI-ACCESS-KEY: <api-key>' \
--header 'KALSHI-ACCESS-SIGNATURE: <api-key>' \
--header 'KALSHI-ACCESS-TIMESTAMP: <api-key>' \
--data '
{
"name": "<string>",
"public_key": "<string>",
"scopes": [],
"subaccount": 31,
"fcm_subtrader_id": "<string>"
}
'import requests
url = "https://external-api.kalshi.com/trade-api/v2/api_keys"
payload = {
"name": "<string>",
"public_key": "<string>",
"scopes": [],
"subaccount": 31,
"fcm_subtrader_id": "<string>"
}
headers = {
"KALSHI-ACCESS-KEY": "<api-key>",
"KALSHI-ACCESS-SIGNATURE": "<api-key>",
"KALSHI-ACCESS-TIMESTAMP": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'KALSHI-ACCESS-KEY': '<api-key>',
'KALSHI-ACCESS-SIGNATURE': '<api-key>',
'KALSHI-ACCESS-TIMESTAMP': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: '<string>',
public_key: '<string>',
scopes: [],
subaccount: 31,
fcm_subtrader_id: '<string>'
})
};
fetch('https://external-api.kalshi.com/trade-api/v2/api_keys', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://external-api.kalshi.com/trade-api/v2/api_keys",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'public_key' => '<string>',
'scopes' => [
],
'subaccount' => 31,
'fcm_subtrader_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"KALSHI-ACCESS-KEY: <api-key>",
"KALSHI-ACCESS-SIGNATURE: <api-key>",
"KALSHI-ACCESS-TIMESTAMP: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://external-api.kalshi.com/trade-api/v2/api_keys"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"public_key\": \"<string>\",\n \"scopes\": [],\n \"subaccount\": 31,\n \"fcm_subtrader_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("KALSHI-ACCESS-KEY", "<api-key>")
req.Header.Add("KALSHI-ACCESS-SIGNATURE", "<api-key>")
req.Header.Add("KALSHI-ACCESS-TIMESTAMP", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://external-api.kalshi.com/trade-api/v2/api_keys")
.header("KALSHI-ACCESS-KEY", "<api-key>")
.header("KALSHI-ACCESS-SIGNATURE", "<api-key>")
.header("KALSHI-ACCESS-TIMESTAMP", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"public_key\": \"<string>\",\n \"scopes\": [],\n \"subaccount\": 31,\n \"fcm_subtrader_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://external-api.kalshi.com/trade-api/v2/api_keys")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["KALSHI-ACCESS-KEY"] = '<api-key>'
request["KALSHI-ACCESS-SIGNATURE"] = '<api-key>'
request["KALSHI-ACCESS-TIMESTAMP"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"public_key\": \"<string>\",\n \"scopes\": [],\n \"subaccount\": 31,\n \"fcm_subtrader_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"api_key_id": "<string>",
"warning": "<string>"
}Create API Key
Endpoint for creating a new API key with a user-provided public key. This endpoint allows users with Premier or Market Maker API usage levels to create API keys by providing their own RSA public key. The platform will use this public key to verify signatures on API requests.
curl --request POST \
--url https://external-api.kalshi.com/trade-api/v2/api_keys \
--header 'Content-Type: application/json' \
--header 'KALSHI-ACCESS-KEY: <api-key>' \
--header 'KALSHI-ACCESS-SIGNATURE: <api-key>' \
--header 'KALSHI-ACCESS-TIMESTAMP: <api-key>' \
--data '
{
"name": "<string>",
"public_key": "<string>",
"scopes": [],
"subaccount": 31,
"fcm_subtrader_id": "<string>"
}
'import requests
url = "https://external-api.kalshi.com/trade-api/v2/api_keys"
payload = {
"name": "<string>",
"public_key": "<string>",
"scopes": [],
"subaccount": 31,
"fcm_subtrader_id": "<string>"
}
headers = {
"KALSHI-ACCESS-KEY": "<api-key>",
"KALSHI-ACCESS-SIGNATURE": "<api-key>",
"KALSHI-ACCESS-TIMESTAMP": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'KALSHI-ACCESS-KEY': '<api-key>',
'KALSHI-ACCESS-SIGNATURE': '<api-key>',
'KALSHI-ACCESS-TIMESTAMP': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: '<string>',
public_key: '<string>',
scopes: [],
subaccount: 31,
fcm_subtrader_id: '<string>'
})
};
fetch('https://external-api.kalshi.com/trade-api/v2/api_keys', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://external-api.kalshi.com/trade-api/v2/api_keys",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'public_key' => '<string>',
'scopes' => [
],
'subaccount' => 31,
'fcm_subtrader_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"KALSHI-ACCESS-KEY: <api-key>",
"KALSHI-ACCESS-SIGNATURE: <api-key>",
"KALSHI-ACCESS-TIMESTAMP: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://external-api.kalshi.com/trade-api/v2/api_keys"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"public_key\": \"<string>\",\n \"scopes\": [],\n \"subaccount\": 31,\n \"fcm_subtrader_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("KALSHI-ACCESS-KEY", "<api-key>")
req.Header.Add("KALSHI-ACCESS-SIGNATURE", "<api-key>")
req.Header.Add("KALSHI-ACCESS-TIMESTAMP", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://external-api.kalshi.com/trade-api/v2/api_keys")
.header("KALSHI-ACCESS-KEY", "<api-key>")
.header("KALSHI-ACCESS-SIGNATURE", "<api-key>")
.header("KALSHI-ACCESS-TIMESTAMP", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"public_key\": \"<string>\",\n \"scopes\": [],\n \"subaccount\": 31,\n \"fcm_subtrader_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://external-api.kalshi.com/trade-api/v2/api_keys")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["KALSHI-ACCESS-KEY"] = '<api-key>'
request["KALSHI-ACCESS-SIGNATURE"] = '<api-key>'
request["KALSHI-ACCESS-TIMESTAMP"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"public_key\": \"<string>\",\n \"scopes\": [],\n \"subaccount\": 31,\n \"fcm_subtrader_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"api_key_id": "<string>",
"warning": "<string>"
}Authorizations
Your API key ID
RSA-PSS signature of the request
Request timestamp in milliseconds
Body
Name for the API key. This helps identify the key's purpose
RSA public key in PEM format. This will be used to verify signatures on API requests
List of scopes to grant to the API key. If the broad write parent scope is included, read must also be included. Child scopes may be granted without the broad parent scope. Defaults to full access (read, write) if not provided.
Scope granted to an API key. Parent scopes grant broad access; for example, read grants all read endpoints and write grants all write endpoints. Child scopes such as read::block_trade_accept, read::portfolio_balance, write::trade, write::transfer, and write::block_trade_accept grant only their specific endpoint group and can be granted without the parent scope.
read, write, read::block_trade_accept, read::portfolio_balance, write::trade, write::transfer, write::block_trade_accept If set, restricts the API key to a single sub-account (0-63) that you own. A restricted key may only read and trade on that sub-account; it cannot act on other sub-accounts, transfer funds between sub-accounts, or create sub-accounts. Omit to leave the key unrestricted. Mutually exclusive with fcm_subtrader_id.
0 <= x <= 63FCM members only. If set, binds the API key to a single FCM subtrader that you own, spelled {your_user_id}_{suffix} with a suffix of 1-16 lowercase alphanumeric characters. The subtrader must already exist. A bound key is the institution's trading credential for that subtrader - FIX order-entry and market-data sessions, plus margin WebSocket sessions scoped to the subtrader's own data - and is denied on every REST endpoint, including key management. Mutually exclusive with subaccount.
Response
API key created successfully
Unique identifier for the newly created API key
Present only when the minted key is bound to an FCM subtrader that has no initial-margin cap at any scope. The mint still succeeds; once SMA enforcement is enabled, the subtrader's orders will be rejected until a cap is set.