How to Get a Kalshi API Key (2026)

The Short Answer
To get a Kalshi API key, log in, open the API Keys section of your profile settings at kalshi.com/account/profile, and create a key. Kalshi generates an RSA key pair, shows you the private key once in PEM format and downloads it as a file, and gives you a Key ID shaped like a UUID. There is no bearer token to copy: the Key ID rides in a plaintext header and your code signs every request with the private key, so the credential itself never crosses the wire. Kalshi documents no application, approval or minimum balance for a standard generated key, and the demo environment at demo.kalshi.co issues its own separate keys.
Every other API hands over a long secret string you paste into a header and can copy again from a dashboard next month. Kalshi hands you half of an RSA key pair, shows it exactly once, and expects your code to sign every request with it. Anyone working out how to get a Kalshi API key can finish the click path in about two minutes. What comes after it is what costs an afternoon.
This page covers key creation and getting one authenticated request to return 200, then stops. Our complete Kalshi API guide maps the wider surface. Everything below was checked against Kalshi's official API keys documentation in August 2026.
Key Takeaways
- Scopes are fixed at creation. No endpoint edits them afterwards, so decide what the key may do before you click create.
- Three headers authenticate every request: your Key ID, a millisecond timestamp, and a signature over the timestamp, method and path.
- Rotation means create then delete. No rotate endpoint exists, so plan for two live keys during a cutover.
How to Get a Kalshi API Key, Step by Step
Log in, then head for your profile settings. Kalshi's docs give two routes to the same destination, which is a small but real annoyance: the API Keys page describes opening Account Settings from the account icon at top right and landing on Profile Settings at kalshi.com/account/profile, while the Quick Start page says Account & security, then API Keys. Aim at the destination rather than the breadcrumb. Find the API Keys section, click the create button (the docs label it both Create New API Key and Create Key), and name the key. Name it carefully: the name, the scopes and the subaccount are everything GET /trade-api/v2/api_keys hands back, with no creation date and no last-used field to help you work out which key is which.
On confirmation Kalshi displays the private key in PEM format, downloads it as a file, and shows a Key ID formatted as a UUID. Save both before you close the page. For a standard generated key there is no documented prerequisite beyond being logged in: no application, no approval queue, no funding minimum, no volume threshold. Usage tiers mostly govern rate limits, but they do gate one thing. Uploading your own public key, rather than using the pair Kalshi mints, requires an elevated usage level, and Kalshi's rate limits page says those levels are earned on trailing 30 day volume, assigned by Kalshi, or granted on request to support. Using the API also binds you to Kalshi's Developer Agreement, accepted by continued use rather than by a click-through. If you would rather not click at all, POST /trade-api/v2/api_keys/generate does the same job from code.
What You Actually Receive, and What Kalshi Keeps
Kalshi stores the public key. The private key is returned to you and, in the documentation's own words, will not be stored by the service, and you will not be able to retrieve it again once the page is closed. No dashboard can show it to you twice and no support agent can either. The Key ID, meanwhile, is not a secret at all: it travels in the clear in the KALSHI-ACCESS-KEY header on every request, which is exactly why that header name misleads people. The access key identifies you. The credential is the file on your disk.
Public REST market data genuinely needs no key. The WebSocket is where that catches people out: it requires the same three signed headers described below during the handshake, even for public channels, so wanting prices only is not a reason to skip this page. If the category itself is new to you, our primer on what a prediction market API is covers the vocabulary.
Kalshi RSA Key Generation: Two Paths
There are two ways to end up with a key pair, and most readers want the first: let Kalshi generate it. The web button and POST /trade-api/v2/api_keys/generate both mint the pair server side, keep the public half and return the private half in PEM. You never touch openssl. Kalshi is inconsistent about what comes back: the API keys page calls it RSA_PRIVATE_KEY format, which is the PKCS#1 header, while the generate endpoint reference says only PEM. So your file may open with -----BEGIN RSA PRIVATE KEY----- or with -----BEGIN PRIVATE KEY-----. Both load without special handling in Python's cryptography and Node's crypto, so use a loader that accepts either rather than hard-coding one.
The second path is uploading your own public key through POST /trade-api/v2/api_keys. The endpoint reference restricts this to Premier or Market Maker usage levels and returns 403 Forbidden to everyone else, which is what the docs said in August 2026. Treat that wording carefully. The rate limits page names seven levels, Basic through Prestige, with no Market Maker among them, so read your own level off that page before assuming you qualify. If you do, or you are setting up FIX, the institutional order entry protocol, the documented commands are openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out kalshi.key then openssl rsa -in kalshi.key -pubout -out kalshi.pub. The FIX page is the only place Kalshi states a size, and it says 2048-bit. That same pair serves FIX, where the Key ID doubles as your SenderCompID.
Scopes, Subaccounts and Storing the Key
A key created without specifying scopes gets full access, read and write, which is rarely what a data collector or a first bot needs. Scopes are set at creation only: there is no PATCH endpoint on /api_keys, so narrowing a key later means making a new one. Kalshi's published changelog begins in February 2026, so the original read and write scopes cannot be dated from it. The narrow child scopes all landed in June 2026. As of August 2026 the list is:
| Scope | Grants | Added |
|---|---|---|
read | Read access | Predates changelog |
write | Full write, requires read | Predates changelog |
write::transfer | Fund transfers | 2 Jun 2026 |
read::portfolio_balance | Balance reads only | 18 Jun 2026 |
read::block_trade_accept | Block trade reads | 18 Jun 2026 |
write::block_trade_accept | Accepting block trades | 18 Jun 2026 |
write::trade | Orders, order groups, quote requests | 30 Jun 2026 |
Dates come from Kalshi's API changelog; the scope list itself is documented on the generate API key reference.
Include the parent write scope and you must include read too, though child scopes can be granted on their own. Since the end of June 2026, write::trade has been the sensible default for a bot, covering orders, order groups and requests for quote without the power to move money out. Since 2 July 2026 you can also pin a key to one subaccount by passing subaccount with a value from 0 to 63 at creation, but that capability moved fast in its first month: restricted keys could not open WebSocket sessions until 23 July 2026, so check the changelog before you build on it.
Then store the file properly: out of your repository and your container image, referenced by an environment variable holding a path rather than the contents, and chmod 600 it. Kalshi returns the private key unencrypted and documents no passphrase option at creation, so if you want one, re-encrypt the PEM yourself and pass the password when your code loads it. A key carrying write scope can place orders against real money on a CFTC regulated exchange, which makes this a compliance problem as much as a security one, and none of it is financial or legal advice.
Testing Your First Signed Request
Three headers go on every authenticated request: KALSHI-ACCESS-KEY with your Key ID, KALSHI-ACCESS-TIMESTAMP with the current time in milliseconds since the epoch, and KALSHI-ACCESS-SIGNATURE with a base64 signature. The string you sign is a plain concatenation with no delimiters: timestamp, then HTTP method in capitals, then path. Kalshi's worked example is 1703123456789GET/trade-api/v2/portfolio/balance. Sign it with RSA-PSS using SHA-256, MGF1 with SHA-256, and a salt length equal to the digest length.
In Python, with cryptography and requests installed, the whole exchange looks like this:
import base64, time, requests
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
with open("kalshi-key.pem", "rb") as f:
key = serialization.load_pem_private_key(f.read(), password=None)
ts = str(int(time.time() * 1000))
method, path = "GET", "/trade-api/v2/portfolio/balance"
signature = base64.b64encode(key.sign(
(ts + method + path).encode(),
padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
salt_length=hashes.SHA256().digest_size),
hashes.SHA256(),
)).decode()
r = requests.get("https://external-api.kalshi.com" + path, headers={
"KALSHI-ACCESS-KEY": "your-key-id",
"KALSHI-ACCESS-TIMESTAMP": ts,
"KALSHI-ACCESS-SIGNATURE": signature,
})
print(r.status_code, r.text)
Point it at the file you downloaded, paste in your Key ID, and run it. A 200 with a balance in cents means the credential works, and our Kalshi Python tutorial picks up from there. If it does not, the failures cluster in a few predictable places.
The path is the full path from the API root, including the /trade-api/v2 prefix. Query parameters are stripped before signing, so /trade-api/v2/portfolio/orders?limit=5 signs as /trade-api/v2/portfolio/orders. The hostname is not part of the payload. And the request body never appears in any documented example, though Kalshi stops short of stating that as a rule. Seconds instead of milliseconds is a frequent cause of signature failures, and the REST docs publish no clock skew tolerance at all (the 30 second window is documented for FIX only), so a synced machine clock is worth checking.
The documented smoke test is GET /trade-api/v2/portfolio/balance against https://external-api.kalshi.com, with the balance returned in cents. Diagnosis is easy, because unauthenticated that endpoint returns 401 while exchange status returns 200: if status works and balance does not, the fault is yours rather than Kalshi's. A 401 points at the Key ID or the path to your private key. A path-not-found usually means you double-prefixed /trade-api/v2 onto a base URL that already had it. Once the balance comes back, the trading bot walkthrough takes over.
The Demo Environment Key Track
The demo environment is a separate account with separate keys, and nothing crosses over. Sign up at demo.kalshi.co, and mind the .co: the help centre goes out of its way to say the .com version is not a valid Kalshi domain. Key creation there is identical to production and the docs say so outright, so follow the same route to the profile page on the demo domain rather than the kalshi.com link the docs hardcode. Signup needs no real identity details either: Kalshi says mock ones are fine as long as the email works, and reusing your production email causes no conflict.
Demo accounts start empty; the help centre lists test card numbers and Plaid sandbox credentials if you need a balance. Point the key at https://external-api.demo.kalshi.co/trade-api/v2 for REST and wss://external-api-ws.demo.kalshi.co/trade-api/ws/v2 for WebSocket. A demo key aimed at a production host is a common first-run failure on this track.
Losing, Rotating and Revoking a Key
Lose the private key and the only remedy is to create a new key and delete the old one, which is also the entire rotation story, because no rotate or regenerate operation exists. Since GET /trade-api/v2/api_keys returns a list and Kalshi publishes no cap on how many keys you can hold, you can rotate without downtime by creating the new key, cutting traffic over, then deleting the old one.
Revocation is DELETE /trade-api/v2/api_keys/{api_key}, which returns 204 and cannot be undone. Whether the web interface exposes an equivalent button is not documented anywhere we could find, so plan on the API call. Keys carry no published expiry and no forced rotation. That is convenient, and it also means nothing will ever remind you to change one. Kalshi does not document whether deletion drops in-flight WebSocket or FIX sessions, so drain your connections before you delete.
Frequently Asked Questions
How do I get a Kalshi API key?
Log in to Kalshi, open the API Keys section of your profile settings at kalshi.com/account/profile, click the create button, name the key, and save the private key and Key ID it shows you. Kalshi documents no application, approval step, funding minimum or volume threshold for a standard generated key. Uploading your own public key instead is a separate, tier-gated path.
Can I have multiple Kalshi API keys?
Yes. GET /trade-api/v2/api_keys returns an array, and Kalshi publishes no limit on how many keys an account can hold at the time of writing. Multiple keys are also the only way to rotate without downtime, since no rotate operation exists: create a new key, cut traffic over, then delete the old one.
Where do I find my Kalshi API key after I create it?
The Key ID is retrievable, from the API Keys section of your profile and from GET /trade-api/v2/api_keys, which returns each key's name, scopes and subaccount alongside it. The private key is not. Kalshi stores only your public key and states plainly that the private key cannot be retrieved once the creation page is closed: no reveal button, no support recovery, only delete and recreate.
Does Kalshi API key generation require me to create my own RSA key?
No, not for a standard key. The web button and POST /trade-api/v2/api_keys/generate both mint the RSA pair for you, keep the public half and return the private half in PEM format. Uploading your own public key uses a different endpoint, POST /trade-api/v2/api_keys, which the endpoint reference restricts to Premier or Market Maker usage levels, returning 403 Forbidden to everyone else. That wording does not match the seven levels listed on Kalshi's rate limits page, so check your own level there before assuming you qualify.
What kind of RSA key does Kalshi use?
A PEM formatted RSA pair used for signing rather than for bearer authentication. Every request carries a base64 RSA-PSS signature computed with SHA-256, MGF1 with SHA-256 and a salt length equal to the digest length, over the millisecond timestamp, the HTTP method and the request path concatenated together. Kalshi's FIX documentation tells you to generate a 2048-bit pair when you supply your own, and does not publish the size of the keys it generates for you.
Conclusion
What trips people up is the shape of the credential, not the steps. Save the private key the instant it appears, scope the key down to what your code actually does, and get the balance endpoint returning 200 before you write anything else. If you wanted a key for market data rather than for trading, it is worth asking whether you need one at all: Predictefy serves normalised prediction market data across venues, and our survey of prediction market data sources lays out the options, including the ones that are not us. Kalshi ships changes to this area often, so check the official documentation before building around any specific detail above.