Short answer: The Kraken Futures API is Kraken's Derivatives interface: REST at futures.kraken.com/derivatives/api/v3 and a streaming-only WebSocket at wss://futures.kraken.com/ws/v1, signed with a separate Derivatives key. On 5 November 2026 its public endpoints listed 209 PF_ perpetuals and 10 FF_ fixed-maturity futures but no inverse contracts, and the self-service demo host redirected to a Kraken web page.
On 5 November 2026 Kraken's Derivatives pages disagreed with each other and with the live endpoints, so each claim here was tested against them. Spot and nonces are in the Kraken API Python guide.
What ran. On 5 November 2026, Python 3.11.3 with requests 2.31 and websockets 13.1 called public REST endpoints and the public WebSocket; signing was checked offline. No key was used and no order sent, so authenticated calls and private feeds are untested.
This is a technical guide, not a recommendation of Kraken or of derivatives trading. Futures are leveraged and positions can be liquidated, so losses can be fast and large (see the liquidation price calculator). Availability depends on your jurisdiction and Kraken's terms. For readers in Turkey: Article 99/A of Capital Markets Law No. 6362 treats activity by foreign crypto-asset platforms directed at Turkish residents as unauthorized.
Kraken Futures API documentation: hosts, keys and REST map
Derivatives has its own hosts, keys and cost-based rate limit, separate from Spot.
- Hosts. History (
/api/history/v2/) and charts (/api/charts/v1/) share the REST host. - Keys. Created in the Derivatives account settings, up to 50, each with its own nonce. General API access stops short of withdrawals, which have a separate switch to leave off (API key security).
- Fees need Spot. Since 22 June 2026 the Futures fee-schedule endpoints no longer show the fees charged; Kraken points to Spot
GetTradeVolumewith a Spot key.
| Endpoint | Purpose | Cost |
|---|---|---|
POST /sendorder | lmt, post, mkt, ioc, fok, stp, take_profit, trailing_stop | 10 |
POST /editorder | Change size or prices | 10 |
POST /cancelorder | By order_id or cliOrdId | 10 |
POST /batchorder | Up to 500 send, edit and cancel instructions | 9 + batch size |
POST /cancelallordersafter | Dead man's switch | 25 |
GET /openorders, /openpositions, /accounts | Orders, positions, cash, flex and margin accounts | 2 each |
GET /instruments, /tickers, /instruments/status | Public data | None |
Private calls share 500 per 10 seconds, history calls 100 tokens per 10 minutes. The error list calls apiLimitExceeded per IP; the rate-limit guide is silent, so assume bots on one address share it.
Kraken futures symbols: PF_, FF_, OF_ and the end of PI_
On 5 November 2026 the live symbols were PF_ perpetuals and FF_ fixed-maturity futures, plus OF_ options on request; no inverse symbol answered.
| Prefix | API type | Count | Example |
|---|---|---|---|
PF_ | flexible_futures, perpetual | 209 | PF_XBTUSD |
FF_ | flexible_futures, expiring 6 Nov 2026 to 26 Mar 2027 | 10 | FF_ETHUSD_261225 |
OF_ | options, only with contractType=options or all | 146 | OF_XBTUSD_261106_79500_P |
PI_, FI_ | futures_inverse | 0 | PI_XBTUSD: contractNotFound |
A banner on Kraken's inverse contract page, updated 30 October 2026, says inverse futures are delisted on 30 October, with BTC, ETH, LTC and XRP contracts settling at 16:00 UTC and leftover collateral moving to spot after 15 November, 08:00 UTC. It gives no year, but /instruments?expired=true lists FI_XBTUSD_261030, last trading 30 October 2026.
Kraken's pages lag: the WebSocket guide subscribes to PI_XBTUSD, the OpenAPI examples use PF_BTCUSD (contractNotFound), and the CLI page counts 317 perpetuals. Load symbols from /instruments at startup.
PF_XBTUSDreports pairBTC:USDon/instrumentsbutXBT:USDon its ticker; lookups ignore case.tradeableis alwaystrueon/instruments, expired markets included (OpenAPI file); checksuspended,postOnlyandisExpired.
Kraken futures API status: instruments versus platform
Market-level status is public, but the Derivatives OpenAPI file read on 5 November 2026 has no public platform-status endpoint.
| Question | Source | Key |
|---|---|---|
| Halted or post-only? | suspended, postOnly on /instruments, /tickers | No |
| Price dislocated, volatility extreme? | /instruments/status | No |
| Maintenance or incident? | Spot SystemStatus advisories for futures_* or all | No |
| Account notices? | /notifications; maintenance with priority high means downtime | Read-only |
In Spot's SystemStatus, emergency lists open incidents and upcoming_maintenance lists work due within 72 hours, dropped once it starts (MaintenanceSchedule shows 7 days); match affected_services on futures_* or all. This market check needs no key:
from decimal import Decimal, InvalidOperation, ROUND_DOWN
import requests
BASE = "https://futures.kraken.com/derivatives/api/v3"
def get(path):
r = requests.get(BASE + path, timeout=10)
try:
body = r.json()
except ValueError: # HTML after a redirect
body = {}
if not (r.status_code == 200 and body.get("result") == "success"):
raise RuntimeError(f"{path}: HTTP {r.status_code}, {body.get('error', 'no JSON')}")
return body
def check_market(symbol):
rows = [i for i in get("/instruments")["instruments"] if i["symbol"].upper() == symbol.upper()]
if len(rows) == 0 or len(rows) > 1: # unknown or delisted, or ambiguous
raise LookupError(f"{symbol}: {len(rows)} instruments match")
flags = {**rows[0], **get(f"/instruments/{rows[0]['symbol']}/status")}
problems = [k for k in ("suspended", "postOnly", "isExpired", "experiencingDislocation",
"experiencingExtremeVolatility") if flags.get(k)]
return rows[0], problems
def to_wire(value, step, upper):
try:
d = Decimal(str(value)).quantize(step, rounding=ROUND_DOWN)
except InvalidOperation:
d = Decimal("NaN")
if not d.is_finite() or d <= 0 or d > upper: # inf, nan, text, zero after rounding
raise ValueError("rejected " + repr(value))
return format(d, "f")
inst, problems = check_market("pf_xbtusd")
step = Decimal(1).scaleb(-inst["contractValueTradePrecision"])
cap = Decimal(str(inst["maxPositionSize"]))
print(inst["symbol"], inst["tickSize"], step, inst.get("makerProtectionMillis", 0), problems)
for size in ("0.00012345", float("1e400"), float("1e-400"), "abc"): # hypothetical
try:
print(to_wire(size, step, cap))
except ValueError as e:
print(e)
for sym in ("PI_XBTUSD", "PF_BTCUSD"):
try:
check_market(sym)
except LookupError as e:
print(e)
Output on 5 November 2026:
PF_XBTUSD 1 0.0001 0 []
0.0001
rejected inf
rejected 0.0
rejected 'abc'
PI_XBTUSD: 0 instruments match
PF_BTCUSD: 0 instruments match
float("1e400")(inf) andfloat("1e-400")(0.0) are rejected before sending; a missingmakerProtectionMillismeans zero.- Unknown symbols returned HTTP 404 with
contractNotFound, absent from the documented error list. The status endpoint returnedinvalidArgumentfor invented names but success, every flag false, for the delistedPI_XBTUSD, so check/instrumentsfirst. Match error codes by prefix. /openpositionswithout a key returned HTTP 200 withauthenticationError, so checkresult, not only the HTTP code.
Kraken futures API authentication: Authent and challenge
REST Authent and the WebSocket signed_challenge share one recipe, SHA-256 and then HMAC-SHA-512 with the Base64-decoded secret; Kraken publishes a challenge test vector.
The REST message is postData + nonce + path, the path starting at /api/v3; the nonce is optional. Since 20 February 2024 Kraken wants parameters hashed URL-encoded, as sent; its REST guide, read 5 November 2026, still says it aims to retire the old method on 1 October 2025, not whether it did.
import base64, hashlib, hmac, json, urllib.parse, uuid
def kf_sign(message, secret):
key = base64.b64decode(secret, validate=True) # a bad secret fails here, offline
digest = hashlib.sha256(message.encode()).digest()
return base64.b64encode(hmac.new(key, digest, hashlib.sha512).digest()).decode()
# Kraken's published challenge example, Derivatives WebSocket guide
print(kf_sign("c100b894-1729-464d-ace1-52dbce11db42",
"7zxMEF5p/Z8l2p2U7Ghv6x14Af+Fx+92tPgUdVQ748FOIrEoT9bgT+bTRfXc5pz8na+hL/QdrCVG7bh9KpT0eMTm")
== "4JEpF3ix66GA2B+ooK128Ift4XQVtc137N9yeg4Kqsn9PI0Kpzbysl9M1IeCEdjg0zl00wkVqcsnG4bmnlMb3A==")
def batch_body(instructions):
sends = [i for i in instructions if i["order"] == "send"]
ids = [i.setdefault("cliOrdId", str(uuid.uuid4())) for i in sends] # added in place
if not all(ids):
raise ValueError("empty cliOrdId")
if len(set(ids)) < len(ids):
raise ValueError("repeated cliOrdId")
if not all(i[k] > 0 for i in instructions
for k in ("size", "limitPrice", "stopPrice") if k in i): # 0.0, nan
raise ValueError("size and prices must be above 0")
payload = json.dumps({"batchOrder": instructions}, separators=(",", ":"),
allow_nan=False) # inf from 1e400 raises
return urllib.parse.urlencode({"json": payload}, quote_via=urllib.parse.quote)
secret = base64.b64encode(b"throwaway, never registered").decode()
order = {"order": "send", "order_tag": "1", "orderType": "post", "symbol": "PF_XBTUSD",
"side": "buy", "size": 0.0001, "limitPrice": 50000} # hypothetical
body = batch_body([order])
authent = kf_sign(body + "/api/v3/batchorder", secret) # postData + nonce ("") + path
old_style = kf_sign(urllib.parse.unquote(body) + "/api/v3/batchorder", secret)
print(body[:40], len(authent), authent == old_style)
for bad in ([dict(order, cliOrdId="")], [order, dict(order)],
[dict(order, limitPrice=float("1e-400"))], [dict(order, size=float("1e400"))]):
try:
batch_body(bad)
except ValueError as e:
print(e)
Output on 5 November 2026:
True
json=%7B%22batchOrder%22%3A%5B%7B%22orde 88 False
empty cliOrdId
repeated cliOrdId
size and prices must be above 0
Out of range float values are not JSON compliant
True reproduces Kraken's example; False shows that hashing decoded JSON changes Authent. On four inputs the function matched sign_message in CryptoFacilities' REST-v3-Python, a client from September 2021 that signs batch JSON unencoded. Private subscribes need api_key, original_challenge and signed_challenge (not run here); an unsigned open_orders subscribe got an alert.
Kraken futures sendorder: statuses that mean rejection
In Kraken's REST guide, result: success only means the request was assessed; whether the order was placed is in sendStatus.status.
- Allow-list statuses. The enum has 33 values, such as
insufficientAvailableFundsandwouldCauseLiquidation, and its description disagrees (clientOrderIdTooLongversusclientOrderIdTooBig), so treat unknown values as rejections. - Maker Protection. Since 24 September 2026, selected markets hold liquidity-taking orders and edits for
makerProtectionMillis(20 ms at launch, at most 100 ms) while post-only orders and cancels pass at once, so a batch need not run in listed order; 152 of 219 futures listed 20 ms on 5 November 2026. - Dead man's switch. Kraken suggests
cancelallordersafterevery 15 to 20 seconds with a 60-second timeout, about 17 of the 500 per 10 seconds at 15-second calls. - Client IDs.
cliOrdIdis unique and at most 100 characters;/orders/statuskeeps finished orders 5 seconds only, so fall back to open orders and fills (client order IDs, reduce-only orders).
Hypothetical example: editing size. An order for 0.0100 BTC has filled 0.0040, leaving 0.0060 open. An edit to size=0.0050 in the default qtyMode, RELATIVE, leaves 0.0050 open, 0.0090 in total. With qtyMode=ABSOLUTE the total becomes 0.0050, leaving 0.0010 open.
Kraken futures WebSocket API: feeds and alerts
The Derivatives WebSocket only streams: public feeds such as ticker and book need no key, private feeds need the signed challenge, and orders go through REST or FIX.
import asyncio, json
import websockets
async def ticker(product):
async with websockets.connect("wss://futures.kraken.com/ws/v1") as ws:
await ws.send(json.dumps({"event": "subscribe", "feed": "ticker",
"product_ids": [product]}))
while True:
msg = json.loads(await asyncio.wait_for(ws.recv(), 15))
if "event" in msg:
print(msg)
if msg["event"] in ("alert", "error"):
return
elif msg.get("feed") == "ticker":
print(msg["product_id"], msg["bid"], msg["ask"], msg["markPrice"],
msg.get("funding_rate"), msg["post_only"], msg["suspended"])
return
asyncio.run(ticker("PF_XBTUSD"))
asyncio.run(ticker("PI_XBTUSD"))
Output on 5 November 2026:
{'event': 'info', 'version': 1}
{'event': 'subscribed', 'feed': 'ticker', 'product_ids': ['PF_XBTUSD']}
PF_XBTUSD 76105.0 76106.0 76109.40445531809 3.500396284565308 False False
{'event': 'info', 'version': 1}
{'event': 'alert', 'message': "Couldn't subscribe to invalid product `PI_XBTUSD`"}
- An invalid product returns an
alert, even alongside a valid one, so check each product. - Field styles mix:
funding_rate(perpetuals only) andpost_onlysit besidemarkPrice; REST saysfundingRate. For funding, see perpetual futures and funding rate and the funding rate calculator. - Ping at least every 60 seconds (websockets pings every 20 by default) and resubscribe after reconnecting; limits are 100 connections and 100 requests per connection per second. For depth, see the order book guide.
Kraken futures demo API: what is left for testing
No self-service Derivatives sandbox answered on 5 November 2026, and Kraken's pages disagree on whether one exists.
| Source | What it says |
|---|---|
| Support article 360024809011, updated 29 October 2026 | Demo decommissioned at 13 UTC on Monday, 14 July, year not given (a Monday in 2025); testing for qualified clients via the API team; old sign-up steps still shown |
| Derivatives introduction, Exchange overview, quickstart | demo-futures.kraken.com is self-service |
| Test at 19:09 UTC | HTTP 301 to a Kraken futures page for REST and WebSocket; REST then ended on the Kraken Pro web app (HTML) |
What remains:
- Kraken's qualified-client environment, via the API team; criteria are not published.
- Kraken's CLI paper trading simulates futures orders on live prices without a key; Kraken recommends it, but it cannot test your signing or Kraken's order checks.
- Small live orders, which are real trades: set hard limits and kill switches first (trading bot risk management).
For integration work in general, see exchange API integration; naming Kraken here does not mean Fincode integrates it or has built on it.
Frequently asked questions
Does Kraken Futures have a testnet or demo API?
Not a self-service one: on 5 November 2026 demo-futures.kraken.com redirected to a Kraken web page. Kraken's support article says the demo was decommissioned and offers testing to qualified clients.
Can I use my Kraken Spot API key for futures?
No. Derivatives keys come from the Derivatives account settings and sign with APIKey and Authent headers; Spot keys use API-Key and API-Sign.
How do I check the Kraken Futures API status?
Use /instruments/status and /tickers for markets, and the advisories in Spot's public SystemStatus, filtered for futures services or all, for maintenance and incidents.
Why does PI_XBTUSD return contractNotFound?
Kraken delisted inverse futures on 30 October 2026, and on 5 November no PI_ or FI_ symbol answered. Perpetuals use PF_, such as PF_XBTUSD.
Sources
- Kraken: Derivatives REST (Authent, URL-encoding change, responses) (opens in a new tab)
- Kraken: Derivatives Rate Limits (costs, history pool, WebSocket limits) (opens in a new tab)
- Kraken: Derivatives WebSocket (challenge signing example) (opens in a new tab)
- Kraken: Derivatives WebSocket reference (feeds) (opens in a new tab)
- Kraken: Derivatives introduction (hosts, keys, demo text) (opens in a new tab)
- Kraken: Futures REST OpenAPI file (endpoints, statuses, errors) (opens in a new tab)
- Kraken: Maker Protection (Derivatives) (opens in a new tab)
- Kraken Support: API Testing Environment, Derivatives (updated 29 October 2026) (opens in a new tab)
- Kraken Support: Inverse Coin-M contract specifications and delisting notice (updated 30 October 2026) (opens in a new tab)
- Kraken: Exchange overview (sandbox row) (opens in a new tab)
- Kraken: Quickstart (futures sandbox text) (opens in a new tab)
- Kraken: kraken-cli (paper trading, separate futures keys) (opens in a new tab)
- CryptoFacilities: REST-v3-Python reference client (opens in a new tab)
- Kraken Status (opens in a new tab)
- Capital Markets Law No. 6362 (consolidated text, Article 99/A, Turkish) (opens in a new tab)
This guide is general information about software and markets, not investment, legal or tax advice. Automated trading can lose money, past or backtested performance does not guarantee future results, and the rules that apply depend on your jurisdiction and your exchange's terms. Sources, checks and corrections: see the editorial policy.