Three schemes. Pick by use case. Sandbox and production share the same schemes, the same sk_live_* prefix, and the same host — capability is differentiated by the key's tier flag.
| Scheme | Use case | Header(s) | Prefix |
|---|---|---|---|
| API Key | Machine-to-machine, creator profiles, aggregators | X-Api-Key |
sk_live_* (tier-flagged) |
| HMAC (5-header) | High-security trading bots, request-signing partners | 4 × PAX-* + Content-Type |
Same as API Key |
| Session Bearer | Browser / mobile client flows | Authorization: Bearer <token> |
Session-scoped |
Send the key in the X-Api-Key header. No signing. Rate-limited per key.
curl https://api.predictasiax.com/v1/account \
-H "X-Api-Key: sk_live_YOUR_KEY_HERE"
Via the dashboard (Settings → API Keys → Mint new key) or via REST:
curl -X POST https://api.predictasiax.com/v1/keys \
-H "Authorization: Bearer <session_token>" \
-H "Content-Type: application/json" \
-d '{
"label": "my-arb-bot",
"permissions": ["read", "trade"]
}'
Response (shown once — cannot be retrieved again):
{
"ok": true,
"data": {
"key_id": "sk_live_ABC123",
"secret": "<32-bytes-hex>",
"passphrase": "<human-readable>",
"permissions": ["read", "trade"],
"created_at_ms": 1786190400000
}
}
Every sk_live_* key carries a tier flag that controls its capabilities and rate limits — enforced server-side on every request:
| Tier | Capability | Rate multiplier |
|---|---|---|
self_serve SANDBOX | Simulated fills at mid-price, $10 per-order + $100 daily notional caps. Zero real-money risk. | 1× baseline |
read_live LIVE | Auto-graduated production tier — reached at $100 30-day attributed volume. Real-money trading with tier-native limits. | 1× baseline |
trade_capped LIVE | Real-money trading with per-order + daily notional ceilings. | 1× baseline |
trade_full LIVE | Unrestricted real-money trading, MM-tier order sizes. | 1× baseline |
genesis LIVE | Inaugural cohort — early access to unreleased endpoints, custom bursts. | 10× baseline |
partner / institutional | Signed agreement — dedicated infra, co-marketing, negotiated fee splits. | up to 20× (negotiable per contract) |
Mismatched credentials return 401 WRONG_ENV_KEY.
For higher-security trading bots. Every request is signed with your secret. Server verifies signature + timestamp within 30-second skew window.
| Header | Value |
|---|---|
PAX-ADDRESS | Your key_id (e.g., sk_live_ABC123) |
PAX-TIMESTAMP | UNIX ms epoch, must be within 30s of server time |
PAX-NONCE | Your passphrase from key mint |
PAX-SIGNATURE | base64(HMAC-SHA256(secret, message)) |
Content-Type | application/json for POST/PUT/PATCH |
message = timestamp + method + path + body
# Examples:
# GET /v1/markets?category=crypto (no body) → "1786190400000GET/v1/markets?category=crypto"
# POST /v1/orders {"market_id":"m_abc"} → "1786190400000POST/v1/orders{\"market_id\":\"m_abc\"}"
import hmac, hashlib, base64, time, json, requests
KEY_ID = "sk_live_ABC123"
SECRET = "<32-bytes-hex>"
PASSPHRASE = "correct-horse-battery-staple"
BASE = "https://api.predictasiax.com"
def sign(method, path, body=""):
ts = str(int(time.time() * 1000))
message = ts + method + path + body
sig = base64.b64encode(
hmac.new(SECRET.encode(), message.encode(), hashlib.sha256).digest()
).decode()
return {
"PAX-ADDRESS": KEY_ID,
"PAX-TIMESTAMP": ts,
"PAX-NONCE": PASSPHRASE,
"PAX-SIGNATURE": sig,
"Content-Type": "application/json",
}
# GET
r = requests.get(BASE + "/v1/account", headers=sign("GET", "/v1/account"))
# POST
body = json.dumps({"market_id": "m_abc", "outcome_id": "yes",
"side": "buy", "order_type": "market", "size": "100"})
r = requests.post(BASE + "/v1/orders", headers=sign("POST", "/v1/orders", body), data=body)
print(r.json())
import crypto from "node:crypto";
const KEY_ID = "sk_live_ABC123";
const SECRET = "<32-bytes-hex>";
const PASSPHRASE = "correct-horse-battery-staple";
const BASE = "https://api.predictasiax.com";
function sign(method, path, body = "") {
const ts = Date.now().toString();
const message = ts + method + path + body;
const sig = crypto.createHmac("sha256", SECRET).update(message).digest("base64");
return {
"PAX-ADDRESS": KEY_ID,
"PAX-TIMESTAMP": ts,
"PAX-NONCE": PASSPHRASE,
"PAX-SIGNATURE": sig,
"Content-Type": "application/json",
};
}
// GET
const r1 = await fetch(BASE + "/v1/account", { headers: sign("GET", "/v1/account") });
// POST
const body = JSON.stringify({ market_id: "m_abc", outcome_id: "yes",
side: "buy", order_type: "market", size: "100" });
const r2 = await fetch(BASE + "/v1/orders", {
method: "POST", body, headers: sign("POST", "/v1/orders", body),
});
console.log(await r2.json());
#!/bin/bash
KEY_ID="sk_live_ABC123"
SECRET="<32-bytes-hex>"
PASSPHRASE="correct-horse-battery-staple"
BASE="https://api.predictasiax.com"
sign() {
local method="$1" path="$2" body="$3"
local ts=$(date +%s%3N)
local message="${ts}${method}${path}${body}"
local sig=$(printf '%s' "$message" | openssl dgst -sha256 -hmac "$SECRET" -binary | base64)
echo "-H PAX-ADDRESS:${KEY_ID} -H PAX-TIMESTAMP:${ts} -H PAX-NONCE:${PASSPHRASE} -H PAX-SIGNATURE:${sig}"
}
# GET
curl "${BASE}/v1/account" $(sign GET /v1/account)
# POST
body='{"market_id":"m_abc","outcome_id":"yes","side":"buy","order_type":"market","size":"100"}'
curl -X POST "${BASE}/v1/orders" -H "Content-Type:application/json" $(sign POST /v1/orders "$body") -d "$body"
Server rejects with 401 INVALID_SIGNATURE if any of:
PAX-SIGNATUREDELETE /v1/keys/{id} called earlier)/v1/audit/* endpoints, and client-side inclusion-proof reconstruction.
Not intended for machine partners. Browser client obtains a bearer token from POST /api/auth/login, sends on every request:
curl https://api.predictasiax.com/v1/account \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Session tokens expire after 7 days idle (24h if refresh not performed). Machine partners should always prefer API Key + HMAC.
The WS connection accepts anonymous connections for public channels (fast_tick, ticker, orderbook, markets_snapshot). To subscribe to private channels (account, deposit, etc.), send an AUTH message after connect:
wscat -c wss://predictasiax.com/ws
> {"method":"AUTH","token":"sk_live_ABC123"}
< {"type":"authenticated","email":"[email protected]"}
> {"method":"SUBSCRIBE","params":["account","fast_round_settled"]}
You can pass either the API key or a session bearer as token — server handles both.
curl -X DELETE https://api.predictasiax.com/v1/keys/sk_live_ABC123 \
-H "Authorization: Bearer <session_token>"
Effective within 5 seconds across our backend fleet. All subsequent requests using the revoked key return 401 KEY_REVOKED.
SECRET and PASSPHRASE in a secret manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault). Rotate on any suspicion of leak — old key can be revoked via DELETE /v1/keys/{id}.