{"openapi":"3.0.3","info":{"title":"KalqiX API","version":"1.7.0","description":"### Introduction\n\nWelcome to the first ZK-powered exchange with unmatched security, lightning-fast transactions, and complete control of your assets.\n\n**Quick-Start Guide for the KalqiX API** – authenticate, market data, orders, account & portfolio, and user info.\n\n**Authentication:**\n- **Headless / bot bootstrap (no UI required):** sign in with your wallet via `GET /auth/nonce` + `POST /auth/verify` to obtain a short-lived session token, then call `PUT /api-keys` with that token to mint your first `api_key` / `api_secret` pair. See the [Authentication Guide](https://docs.kalqix.com/#/authentication) for an end-to-end sample.\n- **Or from the dashboard:** create keys manually at **Kalqix Settings > API Keys** in the web app.\n- Once you have keys, every private request uses API key + HMAC signature via the `x-api-key`, `x-api-signature`, and `x-api-timestamp` headers. See the [HMAC Signature Guide](https://docs.kalqix.com/#/hmac-signature) for canonicalization details.\n\n**Base URLs:**\n- Testnet: `https://testnet-api.kalqix.com/v1`\n- Mainnet: `https://api.kalqix.com/v1`\n\n**Required Headers for Private Endpoints:**\n- `x-api-key`\n- `x-api-signature`\n- `x-api-timestamp`","contact":{"name":"KalqiX Support","url":"https://docs.kalqix.com/","email":"support@kalqix.com"},"license":{"name":"Proprietary","url":"https://kalqix.com/terms"},"termsOfService":"https://kalqix.com/terms"},"externalDocs":{"description":"Full documentation","url":"https://docs.kalqix.com/"},"servers":[{"url":"https://testnet-api.kalqix.com/v1","description":"Testnet"},{"url":"https://api.kalqix.com/v1","description":"Mainnet"}],"tags":[{"name":"Authentication","description":"KalqiX uses two layers of authentication.\n\n**1. Transport auth — proves *who* you are.**\n\n*API key + HMAC (headless / bot clients):*\n- `GET /auth/nonce` → obtain a single-use nonce (5-minute TTL — fetch fresh, do not cache).\n- `POST /auth/verify` → submit the signed SIWE `message` + `signature`. Returns a session `token` (JWT, 7-day expiry) and your `user` profile. A new account is created automatically on first call.\n- `PUT /api-keys` → pass the token as the `Authorization` header value (raw JWT, **no** `Bearer ` prefix) to mint your first `api_key` / `api_secret` pair. The `api_secret` is shown only once.\n- `POST /auth/logout` → invalidate the session token once your keys are stored.\nOnce you have an `api_key` / `api_secret`, include the `x-api-key`, `x-api-signature`, and `x-api-timestamp` headers on every private request. See the [HMAC Signature Guide](https://docs.kalqix.com/#/hmac-signature) for canonicalization details.\n\n*Session JWT (browser clients):* the `token` from `POST /auth/verify` can also be used directly as `Authorization: <token>` on every private request — same flow the web app uses.\n\n**2. Payload auth — proves *intent*, prevents replay.**\n\n*Schnorr (BIP-340) — the documented signing method:* every state-changing request carries a `signature` field (128 hex / 64 bytes) over a canonicalized JSON payload that includes an `agent_index` slot (0..255). The signing key is a per-device **agent wallet** registered ahead of time via `POST /v1/agent-wallets`. See the [Agent Wallets Guide](https://docs.kalqix.com/#/agent-wallets).\n\n*EIP-191 (deprecated):* the legacy `personal_sign` path against the same canonicalized payload, without `agent_index`. Still accepted on the agent-wallet-linked endpoints for existing integrations.\n\nNo browser visit required for either flow — `GET /auth/nonce` + `POST /auth/verify` work end-to-end from a bot. See the [Authentication Guide](https://docs.kalqix.com/#/authentication) for an end-to-end runnable sample."},{"name":"API Keys","description":"Endpoints for creating and managing API keys."},{"name":"Agent Wallets","description":"Per-device BIP-340 Schnorr signing keys (up to 256 slots per wallet) that authorize state-changing trading actions without a fresh ETH signature on each request. The private key is generated and stored client-side; the server only ever sees the x-only public key. Slots are individually revocable. End-to-end onboarding lives in the [Agent Wallets Guide](https://docs.kalqix.com/#/agent-wallets).\n\n**Slot allocation:**\n- **Slot 0** — reserved (never auto-allocated).\n- **Slots 1..5** — \"ensure\" rotating pool used by the browser auto-onboarding flow. When all 5 are active, the oldest by `created_at` is evicted on the next register (UI confirms with the user first).\n- **Slots 6..255** — \"export\" pool used when generating a key for CLI / bot use. No rotation — exhausted slots must be revoked manually."},{"name":"Markets","description":"Endpoints for market data — markets list, order book, trades, charts, and statistics."},{"name":"Assets","description":"Endpoints for supported asset information."},{"name":"Orders","description":"Endpoints for placing, listing, cancelling orders."},{"name":"Account & Portfolio","description":"Endpoints to view balances, positions, and withdrawals."},{"name":"Withdrawals","description":"Endpoints to withdraw funds to external blockchain addresses and view withdrawal history."},{"name":"Transfers","description":"Endpoints to transfer assets."},{"name":"User & Transaction Info","description":"Endpoints for user profile, trade history, transaction history."}],"x-tagGroups":[{"name":"1. Authentication","tags":["Authentication"]},{"name":"2. API Keys","tags":["API Keys"]},{"name":"3. Agent Wallets","tags":["Agent Wallets"]},{"name":"4. Assets","tags":["Assets"]},{"name":"5. Markets","tags":["Markets"]},{"name":"6. Orders","tags":["Orders"]},{"name":"7. Account & Portfolio","tags":["Account & Portfolio"]},{"name":"8. Withdrawals","tags":["Withdrawals"]},{"name":"9. Transfers","tags":["Transfers"]},{"name":"10. User & Transaction Info","tags":["User & Transaction Info"]}],"security":[{"ApiKeyAuth":[],"HmacAuth":[],"TimestampHeader":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Your API key obtained from the Kalqix Settings > API Keys dashboard. This key identifies your account."},"HmacAuth":{"type":"apiKey","in":"header","name":"x-api-signature","description":"HMAC SHA256 signature of the request. Generated using your API secret key. See [API Signature Guide](https://docs.kalqix.com/) for details."},"TimestampHeader":{"type":"apiKey","in":"header","name":"x-api-timestamp","description":"UNIX timestamp (in milliseconds) of when the request was created. Used to prevent replay attacks. Requests with timestamps older than 5 minutes will be rejected."},"BearerAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Session JWT (7-day expiry) returned by `POST /auth/verify`. Pass the raw token as the `Authorization` header value (do **not** prefix with `Bearer `). Accepted on every authenticated endpoint as an alternative to API key + HMAC."}},"parameters":{"AgentIndexPathParam":{"name":"index","in":"path","required":true,"schema":{"type":"integer","minimum":0,"maximum":255},"description":"Agent-wallet slot index (0..255). Slot 0 is reserved."},"AgentIndexQueryParam":{"name":"agent_index","in":"query","required":true,"schema":{"type":"integer","minimum":0,"maximum":255},"description":"Slot index (0..255) of the agent wallet that produced `signature`. Resolved server-side to the slot's BIP-340 public key via a fast Redis lookup; the signature is then verified against that key. 401 if the slot is unregistered or revoked. Omitted only when signing with the deprecated EIP-191 method."},"TickerParam":{"name":"ticker","in":"path","required":true,"schema":{"type":"string","default":"BTC_USDC"},"description":"Market symbol (e.g. 'BTC_USDC')"},"OrderIdParam":{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Order ID"},"AssetParam":{"name":"asset","in":"path","required":true,"schema":{"type":"string","default":"USDC"},"description":"Asset symbol (e.g. `ETH`, `USDC`)"},"PageParam":{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0},"description":"Page number for pagination (starts from 0)"},"PageSizeParam":{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":25,"default":20},"description":"Number of items per page (max: 25)"},"OrdersPageSizeParam":{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":30,"default":10},"description":"Number of items per page for `GET /orders` (max: 30, default: 10)."},"PartnerIdHeader":{"name":"partner-id","in":"header","required":false,"schema":{"type":"integer","minimum":0,"default":0},"description":"Optional partner identifier used to derive partner-branded `maker_fee` /\n`taker_fee` from the configured tier model (`K1` base + `P1` markup).\nMissing, empty, or unrecognized values default to `0` (KalqiX direct).\n**Unauthenticated** — affects displayed fees only; real fees on order\nplacement use the partner context derived from session/API-key\nauthentication."}},"schemas":{"Market":{"type":"object","description":"Represents a trading market / trading pair on the exchange.","properties":{"market_id":{"type":"number","description":"Unique identifier for the market in the system."},"ticker":{"type":"string","description":"Ticker symbol of the market (e.g. `BTC/USDC`)."},"name":{"type":"string","description":"Human-readable name of the market."},"base_asset":{"type":"string","description":"The base asset symbol of the market (e.g. `BTC`)."},"quote_asset":{"type":"string","description":"The quote asset symbol of the market (e.g. `USDC`)."},"base_asset_id":{"type":"number","description":"Numeric ID of the base asset."},"quote_asset_id":{"type":"number","description":"Numeric ID of the quote asset."},"base_asset_decimals":{"type":"number","description":"Number of decimal places permitted for the base asset in orders."},"quote_asset_decimals":{"type":"number","description":"Number of decimal places permitted for the quote asset in orders."},"tick_size":{"type":"string","description":"Minimum price increment as a formatted decimal string (i.e. human-readable, not base units). Order prices must be a multiple of this value when expressed in base units (the API scales `tick_size` by `quote_asset_decimals` server-side before validation). Example for cbBTC/USDC: `\"0.01\"` means prices like `72500.01`, `72500.02` are valid but `72500.015` is not."},"step_size":{"type":"string","description":"Minimum quantity increment as a formatted decimal string (i.e. human-readable, not base units). Order quantities must be a multiple of this value when expressed in base units (the API scales `step_size` by `base_asset_decimals` server-side before validation). Example for cbBTC/USDC: `\"0.000001\"` means quantities like `0.000001`, `0.000123` are valid but `0.0000015` is not."},"min_price":{"type":"string","description":"Minimum allowed price for orders in this market (base units)."},"min_price_formatted":{"type":"string","description":"Minimum allowed price for orders in this market (formatted)."},"min_quantity":{"type":"string","description":"Minimum allowed quantity for orders in this market (base units)."},"min_quantity_formatted":{"type":"string","description":"Minimum allowed quantity for orders in this market (formatted)."},"min_trade_size":{"type":"string","description":"Minimum total trade size in quote units for this market (base units)."},"min_trade_size_formatted":{"type":"string","description":"Minimum total trade size in quote units for this market (formatted)."},"max_trade_size":{"type":"string","nullable":true,"description":"Maximum total trade size in quote units for this market (base units). `null` means no cap."},"max_trade_size_formatted":{"type":"string","nullable":true,"description":"Maximum total trade size in quote units for this market (formatted). `null` means no cap."},"market_order_margin_percent":{"type":"number","description":"Margin percentage required for market orders in this market."},"max_price_deviation_percent":{"type":"number","description":"Maximum allowed deviation from the mark price, expressed as a percentage."},"maker_fee":{"type":"string","description":"Fee percentage charged to market makers (e.g. `\"0.1\"` = 0.1%)."},"taker_fee":{"type":"string","description":"Fee percentage charged to market takers (e.g. `\"0.2\"` = 0.2%)."},"status":{"type":"string","description":"Current status of the market (e.g. `ACTIVE`, `INACTIVE`)."}}},"MarketDetail":{"allOf":[{"$ref":"#/components/schemas/Market"},{"type":"object","properties":{"price_precision":{"type":"number","description":"Number of decimal places used for price display on the UI."},"quantity_precision":{"type":"number","description":"Number of decimal places used for quantity display on the UI."}}}]},"OrderBook":{"type":"object","description":"Depth data (order book) of a market: current buy and sell orders. All price and quantity values are formatted (human-readable).","properties":{"BUY":{"type":"array","description":"List of buy-side (bid) orders, sorted by price descending.","items":{"type":"object","properties":{"price":{"type":"string","description":"Price level (base units)."},"price_formatted":{"type":"string","description":"Price level (formatted)."},"quantity":{"type":"string","description":"Quantity available (base units)."},"quantity_formatted":{"type":"string","description":"Quantity available (formatted)."}}}},"SELL":{"type":"array","description":"List of sell-side (ask) orders, sorted by price ascending.","items":{"type":"object","properties":{"price":{"type":"string","description":"Price level (base units)."},"price_formatted":{"type":"string","description":"Price level (formatted)."},"quantity":{"type":"string","description":"Quantity available (base units)."},"quantity_formatted":{"type":"string","description":"Quantity available (formatted)."}}}}},"example":{"BUY":[{"price":"72752030000","price_formatted":"72752.030000","quantity":"80900000","quantity_formatted":"0.80900000"}],"SELL":[{"price":"72757890000","price_formatted":"72757.890000","quantity":"10400000","quantity_formatted":"0.10400000"}]}},"Trade":{"type":"object","description":"Paginated list of trades for a market.","properties":{"total":{"type":"integer"},"page":{"type":"integer","description":"Page number for pagination (starts from 0)."},"page_size":{"type":"integer","description":"Number of trades per page."},"data":{"type":"array","items":{"type":"object","properties":{"trade_id":{"type":"string","description":"Unique identifier for the trade."},"maker_order_id":{"type":"string","description":"Order ID of the maker's order in this trade."},"taker_order_id":{"type":"string","description":"Order ID of the taker's order in this trade."},"price":{"type":"string","description":"Trade price in base units."},"price_formatted":{"type":"string","description":"Trade price (formatted)."},"quantity":{"type":"string","description":"Quantity traded in base units."},"quantity_formatted":{"type":"string","description":"Quantity traded (formatted)."},"timestamp":{"type":"integer","description":"UNIX timestamp (in microseconds) when the trade occurred."},"ticker":{"type":"string","description":"Ticker of the market (e.g. `BTC/USDC`)."},"maker_side":{"type":"string","description":"Side of the maker in the trade (`BUY` or `SELL`)."},"maker_fee":{"type":"string","description":"Fee paid by the maker in base units."},"maker_fee_formatted":{"type":"string","description":"Fee paid by the maker (formatted)."},"taker_fee":{"type":"string","description":"Fee paid by the taker in base units."},"taker_fee_formatted":{"type":"string","description":"Fee paid by the taker (formatted)."},"fee":{"type":"string","description":"Fee for the authenticated user (base units). Equals maker_fee or taker_fee based on role."},"fee_formatted":{"type":"string","description":"Fee for the authenticated user (formatted)."},"role":{"type":"string","description":"Authenticated user's role in this trade (`maker` or `taker`). Only present for authenticated requests."}}}}},"example":{"total":100,"page":0,"page_size":20,"data":[{"trade_id":"c24adc4b-6a09-4f16-90ec-d6097968860a","maker_order_id":"019d6d41-3b4a-71dc-8cbc-ac3bf5426dcf","taker_order_id":"019d6d41-62c3-730c-be86-a152d8c67282","price":"72482810000","price_formatted":"72482.810000","quantity":"1900000","quantity_formatted":"0.01900000","timestamp":1775654495054003,"ticker":"BTC/USDC","maker_side":"BUY","maker_fee":"1377173","maker_fee_formatted":"1.377173","taker_fee":"2754346","taker_fee_formatted":"2.754346","fee":"1377173","fee_formatted":"1.377173","role":"maker"}]}},"NewOrder":{"type":"object","description":"Request body for `POST /v1/orders`.\n\n**LIMIT orders:** `price` and `quantity` are required.\n\n**MARKET orders:** `price` is not applicable. For MARKET SELL, `quantity` is required. For MARKET BUY, exactly one of `quantity` or `quote_quantity` must be provided.\n\n**Canonical signing payload** (alphabetical key order, omits any `undefined` field):\n\n```\n{action:'PLACE_ORDER', agent_index, expires_at, order_type, price?,\n quantity?, quote_quantity?, side, ticker, time_in_force, timestamp}\n\n```\n\nWith agent-wallet (Schnorr) signing — the documented method — `agent_index` is included and `signature` is the BIP-340 Schnorr signature (128 hex). With the deprecated EIP-191 method `agent_index` is omitted (drops out via `JSON.stringify`) and `signature` is EIP-191 (132 hex).","required":["ticker","side","order_type","signature","timestamp","time_in_force","expires_at","agent_index"],"properties":{"ticker":{"type":"string","description":"Market ticker (e.g. `BTC/USDC`). Slash format in the body."},"price":{"type":"string","description":"Price in quote asset base units (e.g. `\"65000000000\"` for 65000 USDC with 6 decimals). Required for LIMIT; ignored for MARKET."},"quantity":{"type":"string","description":"Quantity in base asset base units (e.g. `\"1000000\"` for 0.01 BTC with 8 decimals). Required for LIMIT and for MARKET SELL. For MARKET BUY, provide either `quantity` or `quote_quantity`."},"quote_quantity":{"type":"string","description":"Amount to spend in quote asset base units. MARKET BUY only — provide either `quantity` or `quote_quantity`."},"side":{"type":"string","enum":["BUY","SELL"],"description":"Whether this is a buy order or sell order."},"order_type":{"type":"string","enum":["LIMIT","MARKET"],"description":"Type of order: limit or market."},"time_in_force":{"type":"number","enum":[0,1,2],"description":"`0` - Good Til Canceled (GTC): rests on the book until cancelled.\n`1` - Immediate Or Cancel (IOC): fills what it can, cancels the remainder.\n`2` - Fill or Kill (FOK): cancels entirely unless the full quantity can be filled.\n"},"expires_at":{"type":"number","description":"Epoch timestamp (ms) at which an unfilled order auto-cancels. `0` = never expire. Must be in the future and no more than 1 year out."},"agent_index":{"type":"integer","minimum":0,"maximum":255,"description":"Slot of the agent wallet that produced `signature`. Omit only when signing with the deprecated EIP-191 method."},"signature":{"type":"string","description":"BIP-340 Schnorr signature (128 hex chars, optional `0x` prefix) over the canonical payload, using the agent-wallet private key for `agent_index`.\n\n**Deprecated:** EIP-191 signature (132 hex chars, including `0x`) by the user's ETH wallet over the same payload **without** `agent_index`."},"timestamp":{"type":"number","description":"Current time as Unix timestamp in milliseconds. Must be within ±5 minutes of server time (replay protection)."}}},"OrderResponse":{"type":"object","description":"Response returned after placing an order.","properties":{"order_id":{"type":"string","description":"Unique identifier assigned to the newly placed order."}}},"OrderDetail":{"type":"object","description":"Detailed information about an order.","properties":{"order_id":{"type":"string","description":"Unique ID of this order."},"ticker":{"type":"string","description":"Ticker symbol of the market (e.g. `BTC/USDC`)."},"price":{"type":"string","description":"Order price in base units (if limit)."},"price_formatted":{"type":"string","description":"Order price (formatted)."},"quantity":{"type":"string","description":"Original quantity requested (base units)."},"quantity_formatted":{"type":"string","description":"Original quantity requested (formatted)."},"quote_quantity":{"type":"string","description":"Quantity in quote currency (base units)."},"quote_quantity_formatted":{"type":"string","description":"Quantity in quote currency (formatted)."},"remaining_quantity":{"type":"string","description":"Quantity left to fill (base units)."},"remaining_quantity_formatted":{"type":"string","description":"Quantity left to fill (formatted)."},"side":{"type":"string","description":"Order side: BUY or SELL."},"order_type":{"type":"string","description":"Type of order: LIMIT or MARKET."},"time_in_force":{"type":"number","description":"GTC (0), IOC (1), FOK (2)."},"expires_at":{"type":"number","description":"Expiry timestamp in milliseconds. `0` means never expires."},"timestamp":{"type":"number","description":"Order creation time (Unix timestamp in milliseconds)."},"status":{"type":"string","description":"Current status of the order.","enum":["PENDING","PARTIALLY_FILLED","FILLED","CANCELLATION_REQUESTED","CANCELLED","EXPIRED","EXPIRED_IN_MATCH","FAILED"]},"maker_fee_ppm":{"type":"integer","description":"Maker fee rate in **parts per million**, snapshot at order creation. `1 ppm = 0.0001%`, so `1000 ppm = 0.1%` and `1_000_000 ppm = 100%`."},"taker_fee_ppm":{"type":"integer","description":"Taker fee rate in **parts per million**, snapshot at order creation. `1 ppm = 0.0001%`, so `2000 ppm = 0.2%` and `1_000_000 ppm = 100%`."},"base_asset":{"type":"string","description":"Symbol of the base asset in the market."},"quote_asset":{"type":"string","description":"Symbol of the quote asset in the market."},"agent_index":{"type":"integer","nullable":true,"minimum":0,"maximum":255,"description":"Agent-wallet slot that signed this order. `null` / absent for orders placed via the deprecated EIP-191 path."},"agent_public_key":{"type":"string","nullable":true,"description":"BIP-340 x-only public key (64 lowercase hex chars) of the agent wallet that signed this order. Captured at order time so the audit trail survives a later revoke or re-register of the slot. `null` / absent for EIP-191 orders."}}},"OrderDetailOne":{"type":"object","description":"Order detail along with list of executed trades for the order.","properties":{"order_id":{"type":"string","description":"Unique order ID."},"ticker":{"type":"string","description":"Ticker symbol (e.g. `BTC/USDC`)."},"price":{"type":"string","description":"Price per unit in base units (for limit orders)."},"price_formatted":{"type":"string","description":"Price per unit (formatted)."},"quantity":{"type":"string","description":"Original quantity requested (base units)."},"quantity_formatted":{"type":"string","description":"Original quantity requested (formatted)."},"quote_quantity":{"type":"string","description":"Quantity in quote currency (base units)."},"quote_quantity_formatted":{"type":"string","description":"Quantity in quote currency (formatted)."},"remaining_quantity":{"type":"string","description":"Quantity yet to be filled (base units)."},"remaining_quantity_formatted":{"type":"string","description":"Quantity yet to be filled (formatted)."},"side":{"type":"string","description":"Order side, BUY or SELL."},"order_type":{"type":"string","description":"Order type (LIMIT or MARKET)."},"time_in_force":{"type":"number","description":"GTC (0), IOC (1), FOK (2)."},"expires_at":{"type":"number","description":"Expiry timestamp in milliseconds. `0` means never expires."},"timestamp":{"type":"number","description":"Order placement time (Unix timestamp in milliseconds)."},"status":{"type":"string","description":"Current status of the order.","enum":["PENDING","PARTIALLY_FILLED","FILLED","CANCELLATION_REQUESTED","CANCELLED","EXPIRED","EXPIRED_IN_MATCH","FAILED"]},"maker_fee_ppm":{"type":"integer","description":"Maker fee rate in **parts per million**, snapshot at order creation. `1 ppm = 0.0001%`, so `1000 ppm = 0.1%` and `1_000_000 ppm = 100%`."},"taker_fee_ppm":{"type":"integer","description":"Taker fee rate in **parts per million**, snapshot at order creation. `1 ppm = 0.0001%`, so `2000 ppm = 0.2%` and `1_000_000 ppm = 100%`."},"base_asset":{"type":"string","description":"Symbol of base asset."},"quote_asset":{"type":"string","description":"Symbol of quote asset."},"average_price":{"type":"string","description":"Weighted average execution price (base units). Null if no trades."},"average_price_formatted":{"type":"string","description":"Weighted average execution price (formatted). Null if no trades."},"agent_index":{"type":"integer","nullable":true,"minimum":0,"maximum":255,"description":"Agent-wallet slot that signed this order. `null` / absent for EIP-191 orders."},"agent_public_key":{"type":"string","nullable":true,"description":"BIP-340 x-only public key (64 lowercase hex chars) of the signing agent wallet. `null` / absent for EIP-191 orders."}}},"OrderTrade":{"type":"object","description":"A trade execution for an order.","properties":{"trade_id":{"type":"string","description":"Unique ID of the trade execution."},"maker_order_id":{"type":"string","description":"Order ID of the maker."},"taker_order_id":{"type":"string","description":"Order ID of the taker."},"price":{"type":"string","description":"Price at which trade executed (base units)."},"price_formatted":{"type":"string","description":"Price at which trade executed (formatted)."},"quantity":{"type":"string","description":"Quantity traded (base units)."},"quantity_formatted":{"type":"string","description":"Quantity traded (formatted)."},"amount":{"type":"string","description":"Total value of the trade, price * quantity (base units)."},"amount_formatted":{"type":"string","description":"Total value of the trade (formatted)."},"fee":{"type":"string","description":"Fee charged (base units)."},"fee_formatted":{"type":"string","description":"Fee charged (formatted)."},"total":{"type":"string","description":"Total amount including fees (base units)."},"total_formatted":{"type":"string","description":"Total amount including fees (formatted)."},"role":{"type":"string","description":"Role of the user in the trade (`maker` or `taker`)."},"timestamp":{"type":"integer","description":"UNIX timestamp (in microseconds) when the trade occurred."},"ticker":{"type":"string","description":"Ticker of the market (e.g. `BTC/USDC`)."},"maker_side":{"type":"string","description":"Side of the maker (`BUY` or `SELL`)."}}},"Portfolio":{"type":"object","description":"User's portfolio summary (account-level).","properties":{"assets_count":{"type":"integer","description":"Number of different assets held in the portfolio."},"total_value_usd":{"type":"number","description":"Total portfolio value denominated in USD (or equivalent)."},"updated_at":{"type":"string","description":"Timestamp when the portfolio was last updated."}}},"Position":{"type":"object","description":"Details of a user's position in a specific asset.","properties":{"asset_id":{"type":"integer","description":"Internal identifier for this asset."},"asset":{"type":"string","description":"Asset code or symbol used by the platform."},"name":{"type":"string","description":"Name of the asset (e.g. `Bitcoin`)."},"symbol":{"type":"string","description":"Symbol of the asset (e.g. `BTC`). Same as `asset`."},"available":{"type":"string","description":"Amount available for trading / withdrawal (base units)."},"available_formatted":{"type":"string","description":"Amount available for trading / withdrawal (formatted)."},"locked":{"type":"string","description":"Amount locked in orders / margin (base units)."},"locked_formatted":{"type":"string","description":"Amount locked in orders / margin (formatted)."},"total":{"type":"string","description":"Total amount of the asset (available + locked) (base units)."},"total_formatted":{"type":"string","description":"Total amount of the asset (available + locked) (formatted)."},"decimals":{"type":"integer","description":"Number of decimals the asset supports."},"display_decimals":{"type":"integer","description":"Number of decimals to display in the UI / API consumer side."}}},"WithdrawalResponse":{"type":"object","description":"Response after a withdrawal request is made.","properties":{"withdrawal_id":{"type":"string","description":"Unique withdrawal request ID."}}},"WithdrawalClaimResponse":{"type":"object","description":"Response containing withdrawal proof data for on-chain claim.","properties":{"proof_ready":{"type":"boolean","description":"Whether the Merkle proof is ready. Only when true will the other fields be populated."},"amount":{"type":"string","description":"Amount in base units (wei, satoshi, etc.)"},"amount_formatted":{"type":"string","description":"Human-readable amount with decimals"},"local_exit_proof":{"type":"string","description":"Local Merkle proof for the withdrawal"},"global_exit_proof":{"type":"string","description":"Global Merkle proof for the withdrawal"},"global_claim_index":{"type":"string","description":"Index in the global Merkle tree"},"token_address":{"type":"string","description":"Smart contract address of the token on destination chain"},"chain_id":{"type":"number","description":"Blockchain chain ID (e.g., 1 for Ethereum mainnet)"},"network":{"type":"string","description":"Network name (e.g., 'Ethereum', 'Polygon')"},"destination_network_id":{"type":"number","description":"Destination network's ID in Kalqix tree structure"},"destination_address":{"type":"string","description":"Destination wallet address for receiving funds"},"bridge_contract_address":{"type":"string","description":"Bridge contract address on destination chain for claiming"}}},"Withdrawal":{"type":"object","description":"Details of a withdrawal from the exchange.","properties":{"withdrawal_id":{"type":"string","description":"Unique withdrawal request ID (UUID v7)."},"amount_formatted":{"type":"string","description":"Human-readable withdrawal amount."},"network":{"type":"string","description":"Network name for the withdrawal."},"data":{"type":"object","description":"Withdrawal data containing asset and destination details.","properties":{"asset_id":{"type":"number","description":"Internal asset identifier."},"asset":{"type":"string","description":"Asset symbol (e.g., 'USDC', 'ETH')."},"amount":{"type":"string","description":"Withdrawal amount in base units."},"decimals":{"type":"string","description":"Asset decimals as string."},"destination_chain_id":{"type":"number","description":"Destination blockchain chain ID."},"destination_network_id":{"type":"number","description":"Destination network ID in KalqiX tree structure."},"destination_address":{"type":"string","description":"Wallet address to receive the withdrawal."},"token_address":{"type":"string","description":"Token contract address on the destination chain."},"timestamp":{"type":"string","description":"Timestamp when the withdrawal was initiated (as BigInt string)."}}},"status":{"type":"string","description":"Current withdrawal status.","enum":["PENDING","CLAIM_READY","ERROR","CLAIMED","FAILED"]},"signature":{"type":"string","description":"Wallet signature used to authenticate the withdrawal."},"priority_exit":{"type":"boolean","description":"Whether this is a priority exit withdrawal."},"priority_exit_valid":{"type":"boolean","description":"Whether the priority exit has been validated."},"claim_transaction_hash":{"type":"string","description":"Transaction hash of the on-chain claim (populated after claiming)."},"created_at":{"type":"string","description":"Timestamp when the withdrawal was created."},"updated_at":{"type":"string","description":"Timestamp when the withdrawal was last updated."},"agent_index":{"type":"integer","nullable":true,"minimum":0,"maximum":255,"description":"Agent-wallet slot that signed this withdrawal. `null` / absent for EIP-191 withdrawals."},"agent_public_key":{"type":"string","nullable":true,"description":"BIP-340 x-only public key (64 lowercase hex chars) of the signing agent wallet. `null` / absent for EIP-191 withdrawals."}}},"Transfer":{"type":"object","description":"Details of an asset transfer between wallets.","properties":{"asset_id":{"type":"integer","description":"Internal identifier for this asset."},"asset":{"type":"string","description":"Asset code or symbol used by the platform."},"amount":{"type":"string","description":"Amount in base units."},"amount_formatted":{"type":"string","description":"Amount in human-readable units (formatted)."},"to_wallet_address":{"type":"string","description":"Address of the target user in lowercase."},"status":{"type":"string","description":"Transfer status.","enum":["PENDING","PROCESSED","ERROR"]},"transfer_id":{"type":"string","description":"Unique ID for the transfer."},"timestamp":{"type":"number","description":"Time of the transfer request (Unix timestamp in milliseconds)."},"sender":{"type":"boolean","description":"Whether the authenticated user is the sender. Only present in list response."},"receiver":{"type":"boolean","description":"Whether the authenticated user is the receiver. Only present in list response."},"agent_index":{"type":"integer","nullable":true,"minimum":0,"maximum":255,"description":"Agent-wallet slot that signed this transfer. `null` / absent for EIP-191 transfers."},"agent_public_key":{"type":"string","nullable":true,"description":"BIP-340 x-only public key (64 lowercase hex chars) of the signing agent wallet. `null` / absent for EIP-191 transfers."}},"example":{"asset_id":1,"asset":"BTC","amount":"1000000000000","amount_formatted":"10000","to_wallet_address":"0x1111111111111111111111111111111111111111","status":"PROCESSED","transfer_id":"019d636a-1c9d-717e-b228-f7b5b44830c4","timestamp":1767225600000,"sender":true,"receiver":false}},"MarketPrice":{"type":"object","description":"Market price response with raw and formatted values.","properties":{"price":{"type":"string","description":"Raw price value in base units.","example":"45234500000000"},"price_formatted":{"type":"string","description":"Price normalized by quote asset decimals.","example":"45234.50"}}},"Market24hr":{"type":"object","description":"24-hour market statistics with base-unit and formatted values.","properties":{"open":{"type":"string","description":"Opening price 24 hours ago (base units)."},"open_formatted":{"type":"number","description":"Opening price 24 hours ago (formatted)."},"high":{"type":"string","description":"Highest price in the last 24 hours (base units)."},"high_formatted":{"type":"number","description":"Highest price in the last 24 hours (formatted)."},"low":{"type":"string","description":"Lowest price in the last 24 hours (base units)."},"low_formatted":{"type":"number","description":"Lowest price in the last 24 hours (formatted)."},"close":{"type":"string","description":"Current / last price (base units)."},"close_formatted":{"type":"number","description":"Current / last price (formatted)."},"volume":{"type":"string","description":"Base asset volume in the last 24 hours (base units)."},"volume_formatted":{"type":"number","description":"Base asset volume in the last 24 hours (formatted)."},"total_volume":{"type":"string","description":"Quote asset volume in the last 24 hours (base units)."},"total_volume_formatted":{"type":"number","description":"Quote asset volume in the last 24 hours (formatted)."},"trades":{"type":"number","description":"Number of trades in the last 24 hours."},"change":{"type":"string","description":"Absolute price change over 24 hours (base units)."},"change_formatted":{"type":"number","description":"Absolute price change over 24 hours (formatted)."},"percent":{"type":"number","description":"Percentage price change over 24 hours."}}},"MarketVolume":{"type":"object","description":"Market volume statistics with base-unit and formatted values.","properties":{"all_time_low":{"type":"string","description":"All-time low price (base units)."},"all_time_low_formatted":{"type":"number","description":"All-time low price (formatted)."},"all_time_high":{"type":"string","description":"All-time high price (base units)."},"all_time_high_formatted":{"type":"number","description":"All-time high price (formatted)."},"base_asset_volume":{"type":"string","description":"Total base asset volume traded (base units)."},"base_asset_volume_formatted":{"type":"number","description":"Total base asset volume traded (formatted)."},"quote_asset_volume":{"type":"string","description":"Total quote asset volume traded (base units)."},"quote_asset_volume_formatted":{"type":"number","description":"Total quote asset volume traded (formatted)."},"trades":{"type":"number","description":"Total number of trades."}}},"Candle":{"type":"object","description":"A single candlestick data point with base-unit and formatted values.","properties":{"time":{"type":"number","description":"Candle timestamp in seconds.","example":1704067200},"time_in_microseconds":{"type":"number","description":"Candle timestamp in microseconds.","example":1704067200000000},"open":{"type":"string","description":"Opening price (base units)."},"open_formatted":{"type":"number","description":"Opening price (formatted)."},"high":{"type":"string","description":"Highest price (base units)."},"high_formatted":{"type":"number","description":"Highest price (formatted)."},"low":{"type":"string","description":"Lowest price (base units)."},"low_formatted":{"type":"number","description":"Lowest price (formatted)."},"close":{"type":"string","description":"Closing price (base units)."},"close_formatted":{"type":"number","description":"Closing price (formatted)."},"volume":{"type":"string","description":"Base asset volume (base units)."},"volume_formatted":{"type":"number","description":"Base asset volume (formatted)."},"total_volume":{"type":"string","description":"Quote asset volume (base units)."},"total_volume_formatted":{"type":"number","description":"Quote asset volume (formatted)."}}},"CandleResponse":{"type":"object","description":"Paginated candlestick response.","properties":{"total":{"type":"integer","description":"Total number of candles returned."},"data":{"type":"array","items":{"$ref":"#/components/schemas/Candle"}},"page":{"type":"integer","example":0},"page_size":{"type":"integer","example":2000}}},"LineChartPoint":{"type":"object","description":"A single line chart data point with base-unit and formatted values.","properties":{"time":{"type":"number","description":"Timestamp in seconds.","example":1704067200},"time_in_microseconds":{"type":"number","description":"Timestamp in microseconds.","example":1704067200000000},"value":{"type":"string","description":"Closing price (base units)."},"value_formatted":{"type":"number","description":"Closing price (formatted)."}}},"LineChartResponse":{"type":"object","description":"Paginated line chart response.","properties":{"total":{"type":"integer","description":"Total number of data points returned."},"data":{"type":"array","items":{"$ref":"#/components/schemas/LineChartPoint"}},"page":{"type":"integer","example":0},"page_size":{"type":"integer","example":2000}}},"Asset":{"type":"object","description":"A supported asset on the exchange.","properties":{"asset_id":{"type":"integer","description":"Unique numeric identifier for the asset.","example":1},"symbol":{"type":"string","description":"Asset ticker symbol.","example":"BTC"},"name":{"type":"string","description":"Full asset name.","example":"Bitcoin"},"decimals":{"type":"integer","description":"Number of decimal places for the asset.","example":8},"display_decimals":{"type":"integer","description":"Number of decimal places for display.","example":4},"min_deposit":{"type":"string","description":"Minimum deposit amount (base units).","example":"100000000"},"min_deposit_formatted":{"type":"string","description":"Minimum deposit amount (formatted).","example":"1.0000"},"networks":{"type":"array","items":{"type":"string"},"description":"List of supported blockchain networks.","example":["BASE SEPOLIA"]},"contracts":{"type":"array","description":"Network-specific contract details.","items":{"type":"object","properties":{"network":{"type":"string","description":"Blockchain network name.","example":"BASE SEPOLIA"},"chain_id":{"type":"integer","description":"Blockchain chain ID.","example":84532},"network_id":{"type":"integer","description":"KalqiX internal network ID.","example":1},"address":{"type":"string","description":"Token contract address.","example":"0xe58c5488de4d67dfb186ef955d412ff4473451a8"},"bridge_contract_address":{"type":"string","description":"Bridge contract address for deposits.","example":"0x9ad49b53a3c9838da5f581f08f62d10dbc72da04"},"chain_decimals":{"type":"integer","description":"Number of decimal places the token uses on this chain.","example":8},"chain_min_deposit":{"type":"string","description":"Minimum deposit amount on this chain (base units).","example":"100000000"},"chain_min_deposit_formatted":{"type":"string","description":"Minimum deposit amount on this chain (formatted).","example":"1.00000000"},"scaling_factor":{"type":"number","description":"Decimal difference between chain and KalqiX precision (`chain_decimals - decimals`). Used to convert deposit amounts between chain and platform units.","example":0}}}},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the asset was created.","example":"2026-01-19T08:42:18.682Z"},"updated_at":{"type":"string","format":"date-time","description":"Timestamp when the asset was last updated.","example":"2026-01-19T08:42:18.682Z"}}},"AssetResponse":{"type":"object","description":"Paginated asset list response.","properties":{"total":{"type":"integer","description":"Total number of assets."},"data":{"type":"array","items":{"$ref":"#/components/schemas/Asset"}},"page":{"type":"integer"},"page_size":{"type":"integer"}}},"Error":{"type":"object","description":"Standard error response format","required":["message"],"properties":{"message":{"type":"string","description":"Error message describing what went wrong"},"code":{"type":"string","description":"Error code for programmatic handling"}},"example":{"message":"Invalid API key or signature.","code":"AUTH_ERROR"}},"PaginatedResponse":{"type":"object","description":"Standard paginated response wrapper","properties":{"total":{"type":"integer","description":"Total number of items available"},"page":{"type":"integer","description":"Current page number"},"page_size":{"type":"integer","description":"Number of items per page"},"data":{"type":"array","description":"Array of items for the current page","items":{}}}},"UserFeeSchedule":{"type":"object","description":"Authenticated user's effective fee schedule and tier progression.","properties":{"partner_id":{"type":"integer","description":"Partner the fees are computed against. `0` for KalqiX direct."},"tier_label":{"type":"string","nullable":true,"description":"Partner-defined label for the user's current markup tier (e.g. `Pro`). `null` if no label is set."},"manual_override":{"type":"boolean","description":"`true` if an administrator has pinned this user to a specific tier; the tier will not auto-progress with volume."},"is_default_profile":{"type":"boolean","description":"`true` for new users without a profile yet — defaults to base tier `K1` and partner's entry tier `P1`."},"rolling_30d_volume":{"type":"string","description":"User's trailing 30-day USDC volume in **base units** (6 decimals)."},"rolling_30d_volume_formatted":{"type":"string","description":"User's trailing 30-day volume in USDC, formatted with 2 decimals."},"fees":{"type":"object","description":"Effective fee rates for the user on this partner.","properties":{"maker_ppm":{"type":"integer","description":"Effective maker fee rate in **parts per million**. `1 ppm = 0.0001%`."},"taker_ppm":{"type":"integer","description":"Effective taker fee rate in **parts per million**. `1 ppm = 0.0001%`."},"maker_percentage":{"type":"string","description":"Effective maker fee rate as a percent string (e.g. `0.1` = `0.1%`)."},"taker_percentage":{"type":"string","description":"Effective taker fee rate as a percent string (e.g. `0.2` = `0.2%`)."}}},"next_tier":{"type":"object","nullable":true,"description":"Volume threshold and remaining gap for the next tier. `null` when the user is already at the highest tier.","properties":{"min_volume":{"type":"string","description":"Volume threshold for the next tier in USDC base units."},"min_volume_formatted":{"type":"string","description":"Volume threshold for the next tier in USDC, formatted."},"volume_to_next":{"type":"string","description":"Volume the user still needs to accumulate to reach the next tier (USDC base units). `0` if already qualified."},"volume_to_next_formatted":{"type":"string","description":"Same as `volume_to_next`, formatted."}}}}},"AgentWallet":{"type":"object","description":"An active agent-wallet slot for the authenticated user.","properties":{"agent_index":{"type":"integer","minimum":0,"maximum":255,"description":"Slot number this agent wallet occupies for the user."},"agent_public_key":{"type":"string","description":"BIP-340 x-only public key, 64 lowercase hex characters (no `0x` prefix). The all-zero value is reserved as the revoked sentinel and is filtered out of `GET` responses."},"label":{"type":"string","description":"User-facing label (max 24 characters after sanitization). Cosmetic metadata — mutable via `PATCH` without a new signed transaction."},"created_at":{"type":"string","description":"ISO-8601 timestamp when the slot was first registered or last re-registered."},"register_tx_id":{"type":"string","description":"ObjectId of the `Transactions` row that recorded the most recent `REGISTER_AGENT_WALLET` for this slot. Used as the optimistic-concurrency token on rotating registers."}}},"AgentWalletRegisterRequest":{"type":"object","required":["agent_index","agent_public_key","timestamp","signature"],"description":"Body for `POST /v1/agent-wallets`. Both register and revoke share this shape — revoke = register with `agent_public_key` set to 64 hex zeros.\n\nThe canonical signing string is `JSON.stringify({action:'REGISTER_AGENT_WALLET', agent_index, agent_public_key, timestamp, wallet_address}, Object.keys(payload).sort())`. `label` is intentionally **not** in the signed payload (it's UX metadata, mutable via `PATCH`) so the registration signature stays verifiable end-to-end from the `Transactions` row alone.","properties":{"agent_index":{"type":"integer","minimum":0,"maximum":255,"description":"Slot to register at. Slot 0 is reserved."},"agent_public_key":{"type":"string","description":"BIP-340 x-only public key — 64 lowercase hex characters, no `0x` prefix. To revoke a slot, send `'0'.repeat(64)` (64 zeros) — x=0 isn't a valid point on secp256k1, so Schnorr verify against this sentinel always fails, which is the desired \"revoked\" semantic.","example":"a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90"},"label":{"type":"string","description":"Optional human-readable label (max 24 characters after sanitization). Empty string if omitted. Not part of the signed payload.","example":"MacBook"},"timestamp":{"type":"number","description":"Unix timestamp in milliseconds. Must be within ±5 minutes of server time (replay protection)."},"signature":{"type":"string","description":"EIP-191 signature (`personal_sign`) by the user's ETH wallet over the canonical payload. Hex, with or without `0x`."},"expected_register_tx_id":{"type":"string","nullable":true,"description":"Optional optimistic-concurrency token. When rotating an ensure-pool slot (see `GET /v1/agent-wallets?next_agent_index=ensure`), pass the `register_tx_id` you observed in the `displaces` field. If another writer rotated the slot between your read and your write, the upsert misses and the server returns `409 CONFLICT_SLOT_CHANGED` — retry with a fresh allocator lookup. Omit on first-time registers."}}},"AgentWalletRegisterResponse":{"type":"object","description":"Response from `POST /v1/agent-wallets` (register or revoke).","properties":{"agent_index":{"type":"integer","minimum":0,"maximum":255},"agent_public_key":{"type":"string","description":"The pubkey stored at the slot (or 64 zeros if just revoked)."},"label":{"type":"string"},"active":{"type":"boolean","description":"`true` if `agent_public_key` is not the zero sentinel."},"created_at":{"type":"string"},"register_tx_id":{"type":"string"}}},"AgentWalletRenameRequest":{"type":"object","required":["label"],"description":"Body for `PATCH /v1/agent-wallets/{index}`. Session-auth only — no signature, no `Transactions` row, no DA. The label is mutable metadata and renaming does not invalidate prior signatures.","properties":{"label":{"type":"string","description":"New label (max 24 characters after sanitization).","example":"my main laptop"}}},"AgentWalletAllocatorResponse":{"type":"object","description":"Response from `GET /v1/agent-wallets?next_agent_index=ensure|export`. Reports the slot the next register call should target, plus the slot that will be displaced (if any).\n\nFor `ensure` (slots 1..5): `next_agent_index` is always non-null — when the pool is full, the oldest-by-`created_at` row is returned and `displaces` is populated so the UI can confirm with the user before signing.\n\nFor `export` (slots 6..255): `next_agent_index` is `null` when all 250 slots are occupied. `displaces` is always `null` (no rotation).","properties":{"next_agent_index":{"type":"integer","nullable":true,"minimum":1,"maximum":255},"displaces":{"allOf":[{"$ref":"#/components/schemas/AgentWallet"}],"nullable":true,"description":"Slot about to be overwritten on the next register. Only populated when the ensure pool is full."}}}}},"paths":{"/auth/nonce":{"get":{"operationId":"37","tags":["Authentication"],"summary":"Get SIWE nonce","security":[],"description":"Returns a single-use nonce to embed in a [Sign-In with Ethereum (SIWE)](https://docs.siwe.xyz/) message. The nonce is short-lived and expires in 5 minutes. Fetch a fresh nonce immediately before signing — do not cache or reuse.\\n\\nThis endpoint is public and is the first step of the auth flow for users who do not yet have an API key.","responses":{"200":{"description":"Nonce generated successfully","content":{"application/json":{"schema":{"type":"string","description":"Opaque single-use nonce to embed in the SIWE message.","example":"b3c1f8a9d2e7"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\n\nfetch(`${baseUrl}/auth/nonce`)\n  .then((res) => res.json())\n  .then((nonce) => console.log(nonce))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\n\nresponse = requests.get(f\"{base_url}/auth/nonce\")\nprint(response.json())"}]}},"/auth/verify":{"post":{"operationId":"38","tags":["Authentication"],"summary":"Verify SIWE signature and sign in","security":[],"description":"Verify a signed SIWE message and exchange it for a session token. If no account exists for the signing wallet, one is created automatically; otherwise the existing profile is returned. The token is used with `PUT /api-keys` to mint your first API key pair — no dashboard visit required.\\n\\n**Flow:**\\n\\n1. Call `GET /auth/nonce` to obtain a nonce. The nonce is short-lived and expires in 5 minutes — fetch fresh immediately before signing, do not cache or reuse.\\n\\n2. Build a SIWE message that embeds the nonce and sign it with your wallet.\\n\\n3. POST the `message` and `signature` here to receive a session `token` (JWT, 7-day expiry) and `user` profile.\\n\\n4. Pass the token as the `Authorization` header value when calling `PUT /api-keys`. The value is the raw JWT — do **not** prefix it with `Bearer `.\\n\\n**Optional fields:**\\n\\n- `referral_code` — applied only on first-time signup for partner attribution and reward eligibility. Ignored for existing accounts.\\n\\n- `partner-id` header — for white-label integrations only. Attributes the new account (and any keys minted with this session) to the given partner. Omit for KalqiX direct (defaults to `0`).","parameters":[{"name":"partner-id","in":"header","required":false,"schema":{"type":"string"},"description":"Optional white-label partner identifier. Pass this header for partner-attributed login and API key creation flows."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message","signature"],"properties":{"message":{"type":"string","description":"The exact SIWE message string that was signed.","example":"testnet.kalqix.com wants you to sign in with your Ethereum account:\n0xAbC...\n\nSigning in to KalqiX\n\nURI: https://testnet.kalqix.com\nVersion: 1\nChain ID: 8453\nNonce: b3c1f8a9d2e7\nIssued At: 2026-04-21T12:00:00.000Z"},"signature":{"type":"string","description":"Wallet signature of the SIWE message (hex-encoded, `0x`-prefixed).","example":"0xabc123..."},"referral_code":{"type":"string","description":"Optional referral code used to track partner attribution and reward eligibility; applied only when creating a new account on first-time signup.","example":"k5le0452"}}}}}},"responses":{"200":{"description":"Signed in successfully","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Session JWT (7-day expiry). Pass the raw value as the `Authorization` header (no `Bearer ` prefix) to `PUT /api-keys`."},"user":{"type":"object","description":"Authenticated user profile.","properties":{"wallet_address":{"type":"string","description":"User's Ethereum wallet address."},"username":{"type":"string","description":"User's display name."},"api_key_count":{"type":"number","description":"Number of active API keys for this user."}}}}}}}},"400":{"description":"Bad request - malformed SIWE message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized - invalid signature or restricted account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const { SiweMessage } = require(\"siwe\");\nconst { ethers } = require(\"ethers\");\n\nconst baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst wallet = new ethers.Wallet(process.env.WALLET_PRIVATE_KEY);\n\n// 1. Fetch nonce\nconst nonce = await fetch(`${baseUrl}/auth/nonce`)\n  .then((res) => res.json());\n\n// 2. Build and sign SIWE message\nconst siwe = new SiweMessage({\n  scheme: \"https\",\n  domain: \"testnet.kalqix.com\",\n  address: wallet.address,\n  statement: \"Signing in to KalqiX\",\n  uri: \"https://testnet.kalqix.com\",\n  version: \"1\",\n  chainId: 8453,\n  nonce\n});\nconst message = siwe.prepareMessage();\nconst signature = await wallet.signMessage(message);\n\n// 3. Verify signature and sign in\nconst res = await fetch(`${baseUrl}/auth/verify`, {\n  method: \"POST\",\n  headers: { \"Content-Type\": \"application/json\" },\n  body: JSON.stringify({ message, signature })\n});\nconst { token } = await res.json();\nconsole.log(\"Session token:\", token);"},{"lang":"Python","label":"Python","source":"import os\nimport requests\nfrom eth_account import Account\nfrom eth_account.messages import encode_defunct\nfrom siwe import SiweMessage\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\naccount = Account.from_key(os.environ[\"WALLET_PRIVATE_KEY\"])\n\n# 1. Fetch nonce\nnonce = requests.get(f\"{base_url}/auth/nonce\").json()\n\n# 2. Build and sign SIWE message\nsiwe = SiweMessage(\n    scheme=\"https\",\n    domain=\"testnet.kalqix.com\",\n    address=account.address,\n    statement=\"Signing in to KalqiX\",\n    uri=\"https://testnet.kalqix.com\",\n    version=\"1\",\n    chain_id=8453,\n    nonce=nonce,\n)\nmessage = siwe.prepare_message()\nsigned = Account.sign_message(\n    encode_defunct(text=message), account.key\n)\n\n# 3. Verify signature and sign in\nres = requests.post(\n    f\"{base_url}/auth/verify\",\n    json={\"message\": message, \"signature\": signed.signature.hex()},\n)\ntoken = res.json()[\"token\"]\nprint(\"Session token:\", token)"}]}},"/auth/logout":{"post":{"operationId":"39","tags":["Authentication"],"summary":"Logout and invalidate session token","security":[{"BearerAuth":[]}],"description":"Invalidates the current session token obtained from `POST /auth/verify`. Call this after you have created your API keys and no longer need the session token.","responses":{"200":{"description":"Logged out successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"bye bye."}}}}}},"401":{"description":"Unauthorized - missing or invalid session token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\n\nawait fetch(`${baseUrl}/auth/logout`, {\n  method: \"POST\",\n  headers: { \"Authorization\": token }\n});"},{"lang":"Python","label":"Python","source":"import requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\n\nrequests.post(\n    f\"{base_url}/auth/logout\",\n    headers={\"Authorization\": token},\n)"}]}},"/api-keys":{"put":{"operationId":"1","tags":["API Keys"],"summary":"Create API keys","security":[{"BearerAuth":[]}],"description":"Create a new API key pair so your application can access private account endpoints. Store secrets securely and rotate keys periodically.\\n\\n**Auth — two ways to call this endpoint:**\\n\\n- **First key (no existing credentials):** pass the session `token` returned by `POST /auth/verify` as the `Authorization` header value (raw JWT, **no** `Bearer ` prefix). This is the headless / bot bootstrap path — no UI required.\\n\\n- **Additional keys (already have credentials):** authenticate with API key + HMAC signature (`x-api-key`, `x-api-signature`, `x-api-timestamp`) just like any other private endpoint.\\n\\nIf you are integrating as a white-label partner, also pass `partner-id` in headers; the new key is bound to that partner. Keys created without `partner-id` default to `partner_id: 0` (KalqiX direct).\\n\\n`api_secret` is shown only once at creation time and cannot be retrieved again later.\\n\\n**Limits:**\\n- Maximum **3 key creations per hour** per user\\n- Maximum **10 total active keys** per user — revoke an existing key (`DELETE /api-keys/{api_key}`) before creating beyond the limit","parameters":[{"name":"partner-id","in":"header","required":false,"schema":{"type":"string"},"description":"Optional white-label partner identifier. Include this header when creating API keys from a white-label app."}],"responses":{"201":{"description":"API key created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"api_key":{"type":"string","description":"Your API key (store this securely)"},"api_secret":{"type":"string","description":"Your API secret key (store this securely - only shown once)"}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized - Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript (first key — session token)","source":"// Headless / bot bootstrap: use the session token from // POST /auth/verify to mint your first key pair. No UI required.\nconst baseUrl = \"https://testnet-api.kalqix.com/v1\";\n\nconst res = await fetch(`${baseUrl}/api-keys`, {\n  method: \"PUT\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    // Raw JWT from /auth/verify — do NOT prefix with \"Bearer \"\n    Authorization: token\n  }\n});\n\nconst { api_key, api_secret } = await res.json();\n// Store api_secret securely — it is shown only once."},{"lang":"Python","label":"Python (first key — session token)","source":"# Headless / bot bootstrap: use the session token from\n# POST /auth/verify to mint your first key pair. No UI required.\n\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\n\nres = requests.put(\n    f\"{base_url}/api-keys\",\n    headers={\n        \"Content-Type\": \"application/json\",\n        # Raw JWT from /auth/verify — do NOT prefix with \"Bearer \"\n        \"Authorization\": token,\n    },\n)\n\ndata = res.json()\napi_key, api_secret = data[\"api_key\"], data[\"api_secret\"]\n# Store api_secret securely — it is shown only once."},{"lang":"JavaScript","label":"JavaScript (additional key — existing API key)","source":"// Use an existing api_key + api_secret to mint another key pair.\n// Sign the request the same way you sign any private endpoint // (see HMAC Signature Guide).\nconst baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/api-keys`, { method: \"PUT\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python (additional key — existing API key)","source":"# Use an existing api_key + api_secret to mint another key pair.\n# Sign the request the same way you sign any private endpoint\n# (see HMAC Signature Guide).\n\nimport time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.put(f\"{base_url}/api-keys\", headers=headers)\nprint(response.json())"}]},"get":{"operationId":"31","tags":["API Keys"],"summary":"Get all API keys","description":"Retrieve all active API keys for the authenticated account. Results are scoped to the **same `partner_id`** the request is authenticated under: an API-key request only sees keys owned by that key's partner; a session-token request only sees keys for the partner derived from the `partner-id` header (default `0` = KalqiX direct).","responses":{"200":{"description":"API keys retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"integer","description":"Total number of active API keys."},"page":{"type":"integer","description":"Current page number (always 0)."},"page_size":{"type":"integer","description":"Maximum number of keys returned per page."},"data":{"type":"array","items":{"type":"object","properties":{"api_key":{"type":"string","description":"The API key identifier."},"partner_id":{"type":"number","description":"Partner identifier associated with this key."},"status":{"type":"string","enum":["active","revoked"],"description":"Current status of the key. Only `active` keys are returned by this endpoint."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the key was created."}}}}}}}}},"401":{"description":"Unauthorized - Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/api-keys`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/api-keys\", headers=headers)\nprint(response.json())"}]}},"/api-keys/{api_key}":{"delete":{"operationId":"30","tags":["API Keys"],"summary":"Delete an API key","description":"Revokes an active API key. The key will no longer be usable for authentication. This action cannot be undone.","parameters":[{"name":"api_key","in":"path","required":true,"schema":{"type":"string"},"description":"The API key to delete"}],"responses":{"200":{"description":"API key deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"api-key removed successfully"}}}}}},"401":{"description":"Unauthorized - Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"API key not found or already revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/api-keys/KEY_TO_DELETE`, { method: \"DELETE\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.delete(f\"{base_url}/api-keys/KEY_TO_DELETE\", headers=headers)\nprint(response.json())"}]}},"/agent-wallets":{"post":{"operationId":"42","tags":["Agent Wallets"],"summary":"Register or revoke an agent wallet","description":"Single endpoint for **both** register and revoke. Authenticated by the user's ETH wallet via EIP-191 (`personal_sign`); the agent wallet itself cannot self-revoke.\n\n**Revoke** = register with `agent_public_key` set to 64 hex zeros. x=0 is not a valid x-coordinate on secp256k1, so Schnorr verify against the zero sentinel always fails — exactly the desired revoked slot semantic.\n\nOn success the server writes one `Transactions` row (action `REGISTER_AGENT_WALLET`) and upserts the `agent_wallets` row at `(wallet_address, agent_index)`. Re-registering the same public key at the same slot is idempotent.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentWalletRegisterRequest"}}}},"responses":{"200":{"description":"Slot registered or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentWalletRegisterResponse"}}}},"400":{"description":"Bad request — missing field, invalid `agent_index`, invalid `agent_public_key`, label too long, or invalid `expected_register_tx_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Invalid signature. `code: INVALID_SIGNATURE`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Optimistic-concurrency conflict (`code: CONFLICT_SLOT_CHANGED`) — the slot was rotated between your `?next_agent_index=ensure` lookup and this register. Refetch the allocator and retry.\n\nOr, rarely, MongoDB duplicate-key conflict (`code: AGENT_WALLET_CONFLICT`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"// Browser flow. `signer` is your wallet client (e.g. ethers).\nimport { schnorr } from \"@noble/curves/secp256k1\";\n\nconst baseUrl = \"https://testnet-api.kalqix.com/v1\";\n\n// 1. Generate a fresh BIP-340 keypair for this device.\nconst privkey = schnorr.utils.randomPrivateKey();           // 32 bytes\nconst agent_public_key = Buffer.from(schnorr.getPublicKey(privkey)).toString(\"hex\");\n\n// 2. Build canonical payload (sorted keys, `label` excluded).\nconst agent_index = 1;\nconst timestamp = Date.now();\nconst wallet_address = (await signer.getAddress()).toLowerCase();\nconst payload = { action: \"REGISTER_AGENT_WALLET\", agent_index, agent_public_key, timestamp, wallet_address };\nconst signingString = JSON.stringify(payload, Object.keys(payload).sort());\n\n// 3. EIP-191 sign with the user's ETH wallet (MetaMask, etc.).\nconst signature = await signer.signMessage(signingString);\n\n// 4. Persist privkey in IndexedDB keyed by [wallet_address, agent_index].\n//    Then POST to register.\nawait fetch(`${baseUrl}/agent-wallets`, {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": String(Date.now())\n  },\n  body: JSON.stringify({ agent_index, agent_public_key, label: \"MacBook\", timestamp, signature })\n}).then(r => r.json());"},{"lang":"Python","label":"Python (HMAC)","source":"# Python flow with API key + HMAC transport auth and ETH-signed # REGISTER payload. Use this to bootstrap a CLI / bot agent wallet.\nimport json, time from coincurve import PrivateKey from eth_account.messages import encode_defunct from eth_account import Account import requests\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nwallet_address = \"0xYourWalletAddress\".lower() eth_key = Account.from_key(\"YOUR_ETH_PRIVATE_KEY\")\n# 1. Generate BIP-340 keypair (32 bytes; agent_public_key is x-only). agent_priv = PrivateKey() agent_public_key = agent_priv.public_key_xonly.format().hex()\n# 2. Canonical payload (sorted keys, label excluded). agent_index = 6   # export pool timestamp = int(time.time() * 1000) payload = {\n    \"action\": \"REGISTER_AGENT_WALLET\",\n    \"agent_index\": agent_index,\n    \"agent_public_key\": agent_public_key,\n    \"timestamp\": timestamp,\n    \"wallet_address\": wallet_address,\n} signing_string = json.dumps(payload, sort_keys=True, separators=(\", \", \": \"))\n# 3. EIP-191 personal_sign. signature = eth_key.sign_message(encode_defunct(text=signing_string)).signature.hex()\n# 4. POST with API key + HMAC headers (build hmac per the HMAC #    Signature Guide). Store agent_priv securely. body = { \"agent_index\": agent_index, \"agent_public_key\": agent_public_key,\n         \"label\": \"bot-1\", \"timestamp\": timestamp, \"signature\": \"0x\" + signature }\nresponse = requests.post(f\"{base_url}/agent-wallets\", json=body, headers=HMAC_HEADERS) print(response.json())"}]},"get":{"operationId":"43","tags":["Agent Wallets"],"summary":"List or allocate agent-wallet slots","description":"Two modes depending on `next_agent_index`:\n\n- **Allocator mode** (`?next_agent_index=ensure|export`) — returns\n  the slot a fresh register call should target, plus the slot it\n  would displace (ensure-pool rotation only). UI calls this first\n  when onboarding a new device or generating a key.\n\n\n- **List mode** (default) — paginated list of *active* slots for the\n  authenticated user. Revoked rows (pubkey = zero sentinel) are\n  filtered out unconditionally; audit history for revoked slots\n  lives in `Transactions`.","parameters":[{"name":"next_agent_index","in":"query","required":false,"schema":{"type":"string","enum":["ensure","export"]},"description":"When set, returns the next allocator response instead of a paginated list. `ensure` = rotating pool 1..5 (always non-null next slot, may displace oldest). `export` = pool 6..255 (null when full, never rotates)."},{"$ref":"#/components/parameters/PageParam"},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":25,"default":25},"description":"Items per page (default 25, max 25). Ignored when `next_agent_index` is set."}],"responses":{"200":{"description":"Allocator response (when `next_agent_index` is set) OR paginated list of active slots (default).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/AgentWalletAllocatorResponse"},{"allOf":[{"$ref":"#/components/schemas/PaginatedResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AgentWallet"}}}}]}]}}}},"401":{"description":"Unauthorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\n\n// Pre-allocate the next ensure-pool slot before registering.\nconst { next_agent_index, displaces } = await fetch(\n  `${baseUrl}/agent-wallets?next_agent_index=ensure`,\n  { headers }\n).then(r => r.json());\n\nif (displaces) {\n  // Confirm with the user before signing — this register will\n  // revoke `displaces.label`, created `displaces.created_at`.\n}\n\n// Or, plain list view:\nconst { total, data, page, page_size } = await fetch(\n  `${baseUrl}/agent-wallets?page=0&page_size=25`,\n  { headers }\n).then(r => r.json());"}]}},"/agent-wallets/{index}":{"get":{"operationId":"44","tags":["Agent Wallets"],"summary":"Get a single agent-wallet slot","description":"Returns the active slot at `index` for the authenticated user. 404 if the slot is unregistered OR revoked — revoked rows are treated as non-existent (audit history is in `Transactions`).","parameters":[{"$ref":"#/components/parameters/AgentIndexPathParam"}],"responses":{"200":{"description":"Slot found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentWallet"}}}},"400":{"description":"Invalid `agent_index`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No active slot at this index for the authenticated user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"45","tags":["Agent Wallets"],"summary":"Rename an agent-wallet slot","description":"Updates the slot's `label`. Session-auth only — no signature, no `Transactions` row, no DA write. The label is UX metadata and renaming does not invalidate signatures the slot has already produced.","parameters":[{"$ref":"#/components/parameters/AgentIndexPathParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentWalletRenameRequest"}}}},"responses":{"200":{"description":"Updated slot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentWallet"}}}},"400":{"description":"Missing or invalid `label`, or invalid `agent_index`, or label exceeds 24 characters after sanitization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Active slot not found at this index.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nawait fetch(`${baseUrl}/agent-wallets/1`, {\n  method: \"PATCH\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": String(Date.now())\n  },\n  body: JSON.stringify({ label: \"my main laptop\" })\n});"}]}},"/markets":{"get":{"operationId":"2","description":"Plain language: Get the list of tradable markets (for example BTC/USDC) and basic metadata.\\n\\nTechnical details: Public endpoint returning market definitions, precision settings, limits, and status flags used by trading clients.","tags":["Markets"],"summary":"List available markets","security":[],"parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"},{"$ref":"#/components/parameters/PartnerIdHeader"}],"responses":{"200":{"description":"Successfully retrieved list of markets","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PaginatedResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Market"}}}}]}}}},"400":{"description":"Bad request - Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = { \"Content-Type\": \"application/json\" };\nfetch(`${baseUrl}/markets`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\"Content-Type\": \"application/json\"}\nresponse = requests.get(f\"{base_url}/markets\", headers=headers)\nprint(response.json())"}]}},"/markets/{ticker}":{"get":{"operationId":"3","description":"Plain language: View full details for one market using its ticker symbol.\\n\\nTechnical details: Public endpoint that resolves a single market resource by `ticker` and returns its current configuration.","tags":["Markets"],"summary":"Get market details by ticker","security":[],"parameters":[{"$ref":"#/components/parameters/TickerParam"},{"$ref":"#/components/parameters/PartnerIdHeader"}],"responses":{"200":{"description":"Successfully retrieved market details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketDetail"},"example":{"market_id":1,"ticker":"BTC/USDC","name":"Bitcoin","base_asset":"BTC","quote_asset":"USDC","base_asset_id":1,"quote_asset_id":2,"base_asset_decimals":8,"quote_asset_decimals":6,"tick_size":"0.01","step_size":"0.000001","min_price":"60000000000","min_price_formatted":"60000.000000","min_quantity":"40000","min_quantity_formatted":"0.00040000","min_trade_size":"10000000","min_trade_size_formatted":"10.000000","max_trade_size":"3000000000","max_trade_size_formatted":"3000.000000","market_order_margin_percent":5,"max_price_deviation_percent":10,"maker_fee":"0.1","taker_fee":"0.2","status":"ACTIVE","price_precision":2,"quantity_precision":6}}}},"404":{"description":"Market not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = { \"Content-Type\": \"application/json\" };\nfetch(`${baseUrl}/markets/BTC_USDC`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\"Content-Type\": \"application/json\"}\nresponse = requests.get(f\"{base_url}/markets/BTC_USDC\", headers=headers)\nprint(response.json())"}]}},"/markets/{ticker}/order-book":{"get":{"operationId":"4","description":"Plain language: See current buy and sell liquidity for a market.\\n\\nTechnical details: Public endpoint returning aggregated bid/ask levels for the specified market ticker.","tags":["Markets"],"summary":"Get market order book","security":[],"parameters":[{"$ref":"#/components/parameters/TickerParam"},{"name":"tick_size","in":"query","required":false,"schema":{"type":"string","default":"0.01"},"description":"Depth tick size for grouping order book price levels. Any positive numeric string is accepted; common values are `0.01`, `0.1`, `1`, `10`, `50`, `100`. Defaults to `0.01` when omitted."}],"responses":{"200":{"description":"Successfully retrieved order book data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderBook"}}}},"400":{"description":"Bad request - Invalid ticker or tick_size parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Market not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = { \"Content-Type\": \"application/json\" };\nfetch(`${baseUrl}/markets/BTC_USDC/order-book`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\"Content-Type\": \"application/json\"}\nresponse = requests.get(f\"{base_url}/markets/BTC_USDC/order-book\", headers=headers)\nprint(response.json())"}]}},"/markets/{ticker}/trades":{"get":{"operationId":"5","description":"Plain language: Retrieve the latest executed trades for a market.\\n\\nTechnical details: Public endpoint returning recent fills with price, quantity, side, and execution timestamps.","tags":["Markets"],"summary":"Get recent market trades","security":[],"parameters":[{"$ref":"#/components/parameters/TickerParam"},{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Successfully retrieved list of trades","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Trade"}}}},"400":{"description":"Bad request - Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Market not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = { \"Content-Type\": \"application/json\" };\nfetch(`${baseUrl}/markets/BTC_USDC/trades?page=0&page_size=20`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\"Content-Type\": \"application/json\"}\nresponse = requests.get(f\"{base_url}/markets/BTC_USDC/trades\", headers=headers, params={'page': 0, 'page_size': 20})\nprint(response.json())"}]}},"/markets/{ticker}/price":{"get":{"operationId":"22","description":"Returns the latest trade price for a market ticker. Returns both raw base-unit price and formatted value.","tags":["Markets"],"summary":"Get current market price","security":[],"parameters":[{"$ref":"#/components/parameters/TickerParam"}],"responses":{"200":{"description":"Successfully retrieved current price","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketPrice"}}}},"404":{"description":"Market not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = { \"Content-Type\": \"application/json\" };\nfetch(`${baseUrl}/markets/BTC_USDC/price`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\"Content-Type\": \"application/json\"}\nresponse = requests.get(f\"{base_url}/markets/BTC_USDC/price\", headers=headers)\nprint(response.json())"}]}},"/markets/{ticker}/market-price":{"get":{"operationId":"23","description":"Returns the best available market price for a given side. For BUY orders, returns the minimum ask price. For SELL orders, returns the maximum bid price.","tags":["Markets"],"summary":"Get market order price by side","security":[],"parameters":[{"$ref":"#/components/parameters/TickerParam"},{"name":"side","in":"query","required":true,"schema":{"type":"string","enum":["BUY","SELL"]},"description":"Order side — BUY returns the best ask, SELL returns the best bid"}],"responses":{"200":{"description":"Successfully retrieved market price","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketPrice"}}}},"400":{"description":"Bad request - Invalid side parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Market not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = { \"Content-Type\": \"application/json\" };\nfetch(`${baseUrl}/markets/BTC_USDC/market-price?side=BUY`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\"Content-Type\": \"application/json\"}\nresponse = requests.get(f\"{base_url}/markets/BTC_USDC/market-price\", headers=headers, params={\"side\": \"BUY\"})\nprint(response.json())"}]}},"/markets/{ticker}/24hr":{"get":{"operationId":"24","description":"Returns 24-hour market statistics including open, high, low, close prices, volume, trade count, and price change. All values are in formatted (human-readable) units.","tags":["Markets"],"summary":"Get 24-hour market statistics","security":[],"parameters":[{"$ref":"#/components/parameters/TickerParam"}],"responses":{"200":{"description":"Successfully retrieved 24-hour statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Market24hr"}}}},"404":{"description":"Market not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = { \"Content-Type\": \"application/json\" };\nfetch(`${baseUrl}/markets/BTC_USDC/24hr`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\"Content-Type\": \"application/json\"}\nresponse = requests.get(f\"{base_url}/markets/BTC_USDC/24hr\", headers=headers)\nprint(response.json())"}]}},"/markets/{ticker}/volume":{"get":{"operationId":"25","description":"Returns market volume statistics including all-time high/low, base and quote asset volumes, and total trade count. All values are in formatted (human-readable) units.","tags":["Markets"],"summary":"Get market volume statistics","security":[],"parameters":[{"$ref":"#/components/parameters/TickerParam"}],"responses":{"200":{"description":"Successfully retrieved volume statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketVolume"}}}},"404":{"description":"Market not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = { \"Content-Type\": \"application/json\" };\nfetch(`${baseUrl}/markets/BTC_USDC/volume`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\"Content-Type\": \"application/json\"}\nresponse = requests.get(f\"{base_url}/markets/BTC_USDC/volume\", headers=headers)\nprint(response.json())"}]}},"/markets/{ticker}/candles":{"get":{"operationId":"26","description":"Returns candlestick (OHLCV) data for a market. Returns up to 2000 candles sorted oldest first. All values are in formatted (human-readable) units.","tags":["Markets"],"summary":"Get candlestick data","security":[],"parameters":[{"$ref":"#/components/parameters/TickerParam"},{"name":"interval","in":"query","required":false,"schema":{"type":"string","enum":["1m","5m","15m","30m","1h","4h","1d"],"default":"1m"},"description":"Candlestick interval"},{"name":"lastCandle","in":"query","required":false,"schema":{"type":"number"},"description":"Timestamp in microseconds — fetch candles after this time"},{"name":"firstCandle","in":"query","required":false,"schema":{"type":"number"},"description":"Timestamp in microseconds — fetch candles before this time"}],"responses":{"200":{"description":"Successfully retrieved candle data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CandleResponse"}}}},"404":{"description":"Market not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = { \"Content-Type\": \"application/json\" };\nfetch(`${baseUrl}/markets/BTC_USDC/candles?interval=1h`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\"Content-Type\": \"application/json\"}\nresponse = requests.get(f\"{base_url}/markets/BTC_USDC/candles\", headers=headers, params={\"interval\": \"1h\"})\nprint(response.json())"}]}},"/markets/{ticker}/line-chart":{"get":{"operationId":"27","description":"Returns simplified chart data with only closing prices. Returns up to 2000 data points sorted oldest first. All values are in formatted (human-readable) units.","tags":["Markets"],"summary":"Get line chart data","security":[],"parameters":[{"$ref":"#/components/parameters/TickerParam"},{"name":"interval","in":"query","required":false,"schema":{"type":"string","enum":["1m","5m","15m","30m","1h","4h","1d"],"default":"1m"},"description":"Data point interval"},{"name":"lastCandle","in":"query","required":false,"schema":{"type":"number"},"description":"Timestamp in microseconds — fetch data points after this time"},{"name":"firstCandle","in":"query","required":false,"schema":{"type":"number"},"description":"Timestamp in microseconds — fetch data points before this time"}],"responses":{"200":{"description":"Successfully retrieved line chart data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LineChartResponse"}}}},"404":{"description":"Market not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = { \"Content-Type\": \"application/json\" };\nfetch(`${baseUrl}/markets/BTC_USDC/line-chart?interval=1h`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\"Content-Type\": \"application/json\"}\nresponse = requests.get(f\"{base_url}/markets/BTC_USDC/line-chart\", headers=headers, params={\"interval\": \"1h\"})\nprint(response.json())"}]}},"/assets":{"get":{"operationId":"29","description":"Returns a list of all supported assets on the exchange, including token details, decimal precision, and network contract information.","tags":["Assets"],"summary":"List supported assets","security":[],"parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"},{"name":"network","in":"query","required":false,"schema":{"type":"string"},"description":"Filter assets by blockchain network (e.g. `ETHEREUM`, `ARBITRUM`). When specified, response includes network-specific contract details at the top level instead of a contracts array."}],"responses":{"200":{"description":"Successfully retrieved assets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = { \"Content-Type\": \"application/json\" };\nfetch(`${baseUrl}/assets`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\"Content-Type\": \"application/json\"}\nresponse = requests.get(f\"{base_url}/assets\", headers=headers)\nprint(response.json())"}]}},"/assets/{id}":{"get":{"operationId":"32","description":"Plain language: Get details for a specific asset.\n\nTechnical details: Public endpoint that returns a single asset by its numeric ID, including network and contract details.","tags":["Assets"],"summary":"Get asset by ID","security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"Numeric asset ID (e.g., `1` for BTC)"}],"responses":{"200":{"description":"Successfully retrieved asset details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Asset"},"example":{"asset_id":1,"symbol":"BTC","name":"Bitcoin","decimals":8,"display_decimals":4,"min_deposit":"100000000","min_deposit_formatted":"1.0000","networks":["BASE SEPOLIA"],"contracts":[{"network":"BASE SEPOLIA","chain_id":84532,"network_id":1,"address":"0xe58c5488de4d67dfb186ef955d412ff4473451a8","bridge_contract_address":"0x9ad49b53a3c9838da5f581f08f62d10dbc72da04","chain_decimals":8,"chain_min_deposit":"100000000","chain_min_deposit_formatted":"1.00000000","scaling_factor":0}],"created_at":"2026-01-19T08:42:18.682Z","updated_at":"2026-01-19T08:42:18.682Z"}}}},"404":{"description":"Asset not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = { \"Content-Type\": \"application/json\" };\nfetch(`${baseUrl}/assets/1`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\"Content-Type\": \"application/json\"}\nresponse = requests.get(f\"{base_url}/assets/1\", headers=headers)\nprint(response.json())"}]}},"/orders":{"post":{"operationId":"6","description":"Submit a buy or sell order. Validates ticker, side, type, price / quantity / quote_quantity, expiry, and the BIP-340 Schnorr signature for the agent wallet at `agent_index`.\n\nSign with the agent wallet: `agent_index` is required and `signature` is the BIP-340 Schnorr signature (128 hex).\n\n**Deprecated EIP-191 alternative:** omit `agent_index`; `signature` is an EIP-191 signature (132 hex) by the user's ETH wallet.","tags":["Orders"],"summary":"Place a new order","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewOrder"}}}},"responses":{"201":{"description":"Order placed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderResponse"}}}},"400":{"description":"Bad request — missing/invalid field, or `agent_index` outside 0..255, or `signature` wrong length.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — invalid transport auth (API key + HMAC or session JWT), or the agent wallet is not registered at `agent_index` (slot unregistered or revoked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Invalid signature (`code: INVALID_SIGNATURE`), insufficient balance, or wallet restricted from trading (`code: WALLET_ADDRESS_BLOCKED` / `ORDER_PLACEMENT_DENIED`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not Found - Invalid market or position not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"// Pre-req: a registered agent wallet at `agent_index` and its\n// BIP-340 private key in local storage (e.g. IndexedDB).\nimport { schnorr } from \"@noble/curves/secp256k1\";\n\nconst baseUrl = \"https://testnet-api.kalqix.com/v1\";\n\nconst order = {\n  ticker: \"BTC/USDC\",\n  side: \"BUY\",\n  order_type: \"LIMIT\",\n  price: \"65000000000\",\n  quantity: \"1000000\",\n  time_in_force: 0,\n  expires_at: 0,\n  timestamp: Date.now(),\n  agent_index: 1\n};\n\n// Canonical payload (alphabetical key order, omits undefined).\nconst payload = { action: \"PLACE_ORDER\", ...order };\nconst signingString = JSON.stringify(payload, Object.keys(payload).sort());\n\nconst sig = schnorr.sign(new TextEncoder().encode(signingString), AGENT_PRIVKEY);\nconst signature = Buffer.from(sig).toString(\"hex\");\n\nawait fetch(`${baseUrl}/orders`, {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": String(Date.now())\n  },\n  body: JSON.stringify({ ...order, signature })\n}).then(r => r.json());"},{"lang":"Python","label":"Python","source":"import json, time\nfrom coincurve import PrivateKey\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\n\norder = {\n  \"ticker\": \"BTC/USDC\",\n  \"side\": \"BUY\",\n  \"order_type\": \"LIMIT\",\n  \"price\": \"65000000000\",\n  \"quantity\": \"1000000\",\n  \"time_in_force\": 0,\n  \"expires_at\": 0,\n  \"timestamp\": int(time.time() * 1000),\n  \"agent_index\": 1,\n}\n\npayload = { \"action\": \"PLACE_ORDER\", **order }\nsigning_string = json.dumps(payload, sort_keys=True, separators=(\", \", \": \"))\n\nagent_priv = PrivateKey.from_hex(AGENT_PRIVKEY_HEX)\nsignature = agent_priv.sign_schnorr(signing_string.encode(\"utf-8\")).hex()\n\nresponse = requests.post(\n  f\"{base_url}/orders\",\n  headers={ \"Content-Type\": \"application/json\", **HMAC_HEADERS },\n  json={ **order, \"signature\": signature },\n)\nprint(response.json())"}]},"get":{"operationId":"17","description":"Plain language: View your open and recent orders with optional filters.\\n\\nTechnical details: Authenticated endpoint returning paginated order resources for the current account context.","tags":["Orders"],"summary":"List current user orders","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/OrdersPageSizeParam"},{"name":"ticker","in":"query","required":false,"schema":{"type":"string"},"description":"Market symbol (e.g. `BTC_USDC`)"},{"name":"open","in":"query","required":false,"schema":{"type":"string"},"description":"Use value `true` to fetch open orders."},{"name":"side","in":"query","required":false,"schema":{"type":"string","enum":["BUY","SELL"]},"description":"Filter orders by side."},{"name":"order_type","in":"query","required":false,"schema":{"type":"string","enum":["LIMIT","MARKET"]},"description":"Filter orders by order type."},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["PENDING","PARTIALLY_FILLED","FILLED","CANCELLATION_REQUESTED","CANCELLED","EXPIRED","EXPIRED_IN_MATCH","FAILED"]},"description":"Filter orders by status."}],"responses":{"200":{"description":"Successfully retrieved list of user's orders","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PaginatedResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OrderDetail"}}}}]}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/orders?page=0&page_size=20`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/orders\", headers=headers, params={'page': 0, 'page_size': 20})\nprint(response.json())"}]}},"/orders/{id}":{"get":{"operationId":"7","description":"Plain language: Check the status and details of a specific order.\\n\\nTechnical details: Authenticated endpoint that fetches one order by identifier and returns lifecycle state and metadata. Use GET /orders/{id}/trades for trade executions.","tags":["Orders"],"summary":"Get order details","parameters":[{"$ref":"#/components/parameters/OrderIdParam"}],"responses":{"200":{"description":"Successfully retrieved order details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderDetailOne"}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/orders/ORDER_ID`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/orders/ORDER_ID\", headers=headers)\nprint(response.json())"}]},"delete":{"operationId":"8","description":"Request cancellation of a live order. The order must be in `PENDING` or `PARTIALLY_FILLED` status; FILLED / CANCELLED / EXPIRED orders return 400.\n\nSign with the agent wallet: include `agent_index` and a Schnorr `signature` in the query string.\n\n**Deprecated EIP-191 alternative:** omit `agent_index`; `signature` is an EIP-191 signature.\n\n**Canonical signing payload** (alphabetical order): `{action:'CANCEL_ORDER', agent_index, order_id, timestamp}`. On /v1 `agent_index` is `undefined` and drops out via `JSON.stringify`.","tags":["Orders"],"summary":"Cancel an order","parameters":[{"$ref":"#/components/parameters/OrderIdParam"},{"$ref":"#/components/parameters/AgentIndexQueryParam"},{"name":"signature","in":"query","required":true,"schema":{"type":"string"},"description":"BIP-340 Schnorr signature (128 hex, optional `0x` prefix) over the canonical `CANCEL_ORDER` payload using the agent-wallet private key for `agent_index`.\n\n**Deprecated:** EIP-191 signature (132 hex)."},{"name":"timestamp","in":"query","required":true,"schema":{"type":"number"},"description":"Unix timestamp in milliseconds. Must be within ±5 minutes of server time."}],"responses":{"200":{"description":"Cancellation request received.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","default":"Your cancellation request is received."}}}}}},"400":{"description":"Missing required field, duplicate cancellation (`Your cancellation request is already received.`), order is not in a cancellable state, or agent-wallet middleware errors (invalid `agent_index` / `signature`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — invalid transport auth, or the agent wallet is not registered at `agent_index`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Invalid signature (`code: INVALID_SIGNATURE`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Order not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"import { schnorr } from \"@noble/curves/secp256k1\";\n\nconst baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst order_id = \"ORDER_UUID\";\nconst agent_index = 1;\nconst timestamp = Date.now();\n\nconst payload = { action: \"CANCEL_ORDER\", agent_index, order_id, timestamp };\nconst signingString = JSON.stringify(payload, Object.keys(payload).sort());\nconst signature = Buffer.from(\n  schnorr.sign(new TextEncoder().encode(signingString), AGENT_PRIVKEY)\n).toString(\"hex\");\n\nconst qs = new URLSearchParams({ agent_index, signature, timestamp });\nawait fetch(`${baseUrl}/orders/${order_id}?${qs}`, {\n  method: \"DELETE\",\n  headers: {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": String(Date.now())\n  }\n}).then(r => r.json());"},{"lang":"Python","label":"Python","source":"import json, time\nfrom coincurve import PrivateKey\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\norder_id = \"ORDER_UUID\"\nagent_index = 1\ntimestamp = int(time.time() * 1000)\n\npayload = { \"action\": \"CANCEL_ORDER\", \"agent_index\": agent_index,\n            \"order_id\": order_id, \"timestamp\": timestamp }\nsigning_string = json.dumps(payload, sort_keys=True, separators=(\", \", \": \"))\n\nagent_priv = PrivateKey.from_hex(AGENT_PRIVKEY_HEX)\nsignature = agent_priv.sign_schnorr(signing_string.encode(\"utf-8\")).hex()\n\nresponse = requests.delete(\n  f\"{base_url}/orders/{order_id}\",\n  params={ \"agent_index\": agent_index, \"signature\": signature, \"timestamp\": timestamp },\n  headers=HMAC_HEADERS,\n)\nprint(response.json())"}]}},"/orders/{id}/average-price":{"get":{"operationId":"40","tags":["Orders"],"summary":"Get order average price","description":"Returns the average execution price for the specified order.","parameters":[{"$ref":"#/components/parameters/OrderIdParam"}],"responses":{"200":{"description":"Successfully retrieved order average price","content":{"application/json":{"schema":{"type":"object","properties":{"average_price":{"type":"string","description":"Average execution price in base units."},"average_price_formatted":{"type":"string","description":"Average execution price in human-readable format."}}}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/orders/ORDER_ID/average-price`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(\n    f\"{base_url}/orders/ORDER_ID/average-price\",\n    headers=headers,\n)\nprint(response.json())"}]}},"/orders/{id}/transaction":{"get":{"operationId":"41","tags":["Orders"],"summary":"Get order transaction hash","description":"Returns the transaction hash associated with the specified order.","parameters":[{"$ref":"#/components/parameters/OrderIdParam"}],"responses":{"200":{"description":"Successfully retrieved order transaction","content":{"application/json":{"schema":{"type":"object","properties":{"transaction":{"type":"string","description":"Blockchain transaction hash for the order."}}}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/orders/ORDER_ID/transaction`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(\n    f\"{base_url}/orders/ORDER_ID/transaction\",\n    headers=headers,\n)\nprint(response.json())"}]}},"/orders/{id}/trades":{"get":{"operationId":"36","description":"Returns paginated trade executions for a specific order. Each trade includes price, quantity, fee, role (maker/taker), and total.","tags":["Orders"],"summary":"Get order trades","parameters":[{"$ref":"#/components/parameters/OrderIdParam"},{"$ref":"#/components/parameters/PageParam"},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":10},"description":"Number of trades per page (max: 50)"}],"responses":{"200":{"description":"Successfully retrieved order trades","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PaginatedResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OrderTrade"}}}}]}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/orders/ORDER_ID/trades?page=0&page_size=10`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/orders/ORDER_ID/trades\", headers=headers, params={'page': 0, 'page_size': 10})\nprint(response.json())"}]}},"/users/me/cancel-all-orders":{"delete":{"operationId":"9","description":"Cancel every active order for the caller in the specified market. Affects only orders created **before** this request — orders placed after will not be cancelled.\n\nThe URL segment `me` is decorative; any value (the wallet address, `me`, or anything else) routes to the authenticated user — the user is always resolved from auth context, never from the path.\n\nSign with the agent wallet: include `agent_index` + a Schnorr `signature` in the query.\n**Deprecated EIP-191 alternative:** omit `agent_index`; `signature` is an EIP-191 signature.\n\n**Canonical signing payload** (alphabetical order): `{action:'CANCEL_ALL_ORDERS', agent_index, market, timestamp}`.","tags":["Orders"],"summary":"Cancel all orders in a market","parameters":[{"name":"market","in":"query","required":true,"schema":{"type":"integer","minimum":1},"description":"Market ID (integer) from `GET /markets`. Not the ticker — pass `1`, not `BTC_USDC`."},{"$ref":"#/components/parameters/AgentIndexQueryParam"},{"name":"signature","in":"query","required":true,"schema":{"type":"string"},"description":"BIP-340 Schnorr signature (128 hex, optional `0x`).\n\n**Deprecated:** EIP-191 signature (132 hex)."},{"name":"timestamp","in":"query","required":true,"schema":{"type":"number"},"description":"Unix timestamp in milliseconds. Within ±5 minutes of server time."}],"responses":{"200":{"description":"Cancellation request accepted.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","default":"Your request to cancel all open orders is received."},"request_id":{"type":"string","default":"694248bb394d0876ba7eb4c0"}}}}}},"400":{"description":"Missing required field, invalid `market` (not a positive integer), or agent-wallet middleware errors.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — invalid transport auth, or the agent wallet is not registered at `agent_index`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Invalid signature (`code: INVALID_SIGNATURE`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Market not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"import { schnorr } from \"@noble/curves/secp256k1\";\n\nconst baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst market = 1;          // numeric market id, not ticker\nconst agent_index = 1;\nconst timestamp = Date.now();\n\nconst payload = { action: \"CANCEL_ALL_ORDERS\", agent_index, market, timestamp };\nconst signingString = JSON.stringify(payload, Object.keys(payload).sort());\nconst signature = Buffer.from(\n  schnorr.sign(new TextEncoder().encode(signingString), AGENT_PRIVKEY)\n).toString(\"hex\");\n\nconst qs = new URLSearchParams({ market, agent_index, signature, timestamp });\nawait fetch(`${baseUrl}/users/me/cancel-all-orders?${qs}`, {\n  method: \"DELETE\",\n  headers: {\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": String(Date.now())\n  }\n}).then(r => r.json());"},{"lang":"Python","label":"Python","source":"import json, time\nfrom coincurve import PrivateKey\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nmarket = 1\nagent_index = 1\ntimestamp = int(time.time() * 1000)\n\npayload = { \"action\": \"CANCEL_ALL_ORDERS\", \"agent_index\": agent_index,\n            \"market\": market, \"timestamp\": timestamp }\nsigning_string = json.dumps(payload, sort_keys=True, separators=(\", \", \": \"))\n\nagent_priv = PrivateKey.from_hex(AGENT_PRIVKEY_HEX)\nsignature = agent_priv.sign_schnorr(signing_string.encode(\"utf-8\")).hex()\n\nresponse = requests.delete(\n  f\"{base_url}/users/me/cancel-all-orders\",\n  params={ \"market\": market, \"agent_index\": agent_index,\n           \"signature\": signature, \"timestamp\": timestamp },\n  headers=HMAC_HEADERS,\n)\nprint(response.json())"}]}},"/portfolios/me":{"get":{"operationId":"10","description":"Plain language: View your account balances and portfolio totals.\\n\\nTechnical details: Authenticated endpoint returning wallet and exchange balance breakdowns for the current account.","tags":["Account & Portfolio"],"summary":"Get portfolio balances","responses":{"200":{"description":"Successfully retrieved portfolio overview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Portfolio"}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/portfolios/me`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/portfolios/me\", headers=headers)\nprint(response.json())"}]}},"/positions":{"get":{"operationId":"11","description":"Plain language: Get all your asset positions in one response.\\n\\nTechnical details: Authenticated endpoint returning current per-asset position objects including available and locked amounts.","tags":["Account & Portfolio"],"summary":"List all positions","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Successfully retrieved list of positions","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PaginatedResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Position"}}}}]}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/positions`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/positions\", headers=headers)\nprint(response.json())"}]}},"/positions/{asset}":{"get":{"operationId":"12","description":"Plain language: Check your position for a specific asset, such as USDC or ETH.\\n\\nTechnical details: Authenticated endpoint that resolves one position resource by asset symbol.","tags":["Account & Portfolio"],"summary":"Get position by asset","parameters":[{"$ref":"#/components/parameters/AssetParam"}],"responses":{"200":{"description":"Successfully retrieved position for asset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Position"}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Position not found for the specified asset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/positions/USDC`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/positions/USDC\", headers=headers)\nprint(response.json())"}]}},"/withdrawals":{"post":{"operationId":"13","description":"Initiate a withdrawal to the user's wallet on `chain_id`. Locks the requested amount on the position; the on-chain Merkle proof is fetched separately via `GET /withdrawals/{id}/claim` once it's ready.\n\nSign with the agent wallet: include `agent_index` in the body and a Schnorr `signature`.\n**Deprecated EIP-191 alternative:** omit `agent_index`; `signature` is an EIP-191 signature.\n\n**Canonical signing payload** (alphabetical order): `{action:'WITHDRAW', agent_index, amount, asset, chain_id, timestamp}`.","tags":["Withdrawals"],"summary":"Initiate a withdrawal","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["asset","amount","chain_id","timestamp","signature","agent_index"],"properties":{"asset":{"type":"string","description":"Asset symbol (e.g. `USDC`, `BTC`).","example":"USDC"},"amount":{"type":"string","description":"Amount in base units (e.g. `\"100000000\"` for 100 USDC with 6 decimals).","example":"100000000"},"chain_id":{"type":"number","description":"Destination chain ID. Must equal the server's configured `BASE_CHAIN_ID` (currently Base — `8453`).","example":8453},"agent_index":{"type":"integer","minimum":0,"maximum":255,"description":"Agent-wallet slot of the agent wallet that signed this request. Omit only when using the deprecated EIP-191 signature."},"signature":{"type":"string","description":"BIP-340 Schnorr signature (128 hex, optional `0x`).\n\n**Deprecated:** EIP-191 signature (132 hex).","example":"0x..."},"timestamp":{"type":"number","description":"Unix timestamp in milliseconds. Within ±5 minutes of server time.","example":1767225600000}}}}}},"responses":{"200":{"description":"Withdrawal initiated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WithdrawalResponse"}}}},"400":{"description":"Missing/invalid field, invalid amount, unsupported asset, `chain_id` does not match `BASE_CHAIN_ID`, or below `min_withdrawal` (`code: INVALID_MIN_WITHDRAWAL_AMOUNT`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — invalid transport auth, or the agent wallet is not registered at `agent_index`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Invalid signature (`code: INVALID_SIGNATURE`), insufficient balance, or system-wallet min-balance violation (`code: SYSTEM_WALLET_MIN_BALANCE`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Asset or position not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error, or asset misconfigured (`code: MISSING_MIN_WITHDRAWAL_CONFIG`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"import { schnorr } from \"@noble/curves/secp256k1\";\n\nconst baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst body = {\n  asset: \"USDC\",\n  amount: \"100000000\",   // base units\n  chain_id: 8453,\n  agent_index: 1,\n  timestamp: Date.now(),\n};\n\nconst payload = { action: \"WITHDRAW\", ...body };\nconst signingString = JSON.stringify(payload, Object.keys(payload).sort());\nconst signature = Buffer.from(\n  schnorr.sign(new TextEncoder().encode(signingString), AGENT_PRIVKEY)\n).toString(\"hex\");\n\nawait fetch(`${baseUrl}/withdrawals`, {\n  method: \"POST\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": String(Date.now())\n  },\n  body: JSON.stringify({ ...body, signature }),\n}).then(r => r.json());"},{"lang":"Python","label":"Python","source":"import json, time\nfrom coincurve import PrivateKey\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\n\nbody = {\n  \"asset\": \"USDC\",\n  \"amount\": \"100000000\",\n  \"chain_id\": 8453,\n  \"agent_index\": 1,\n  \"timestamp\": int(time.time() * 1000),\n}\npayload = { \"action\": \"WITHDRAW\", **body }\nsigning_string = json.dumps(payload, sort_keys=True, separators=(\", \", \": \"))\n\nagent_priv = PrivateKey.from_hex(AGENT_PRIVKEY_HEX)\nsignature = agent_priv.sign_schnorr(signing_string.encode(\"utf-8\")).hex()\n\nresponse = requests.post(\n  f\"{base_url}/withdrawals\",\n  json={ **body, \"signature\": signature },\n  headers=HMAC_HEADERS,\n)\nprint(response.json())"}]},"get":{"operationId":"33","description":"Plain language: View your withdrawal history and statuses.\n\nTechnical details: Authenticated paginated endpoint returning withdrawal records for the current account.","tags":["Withdrawals"],"summary":"List withdrawals","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Successfully retrieved list of withdrawals","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PaginatedResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Withdrawal"}}}}]}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/withdrawals?page=0&page_size=25`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/withdrawals\", headers=headers, params={'page': 0, 'page_size': 25})\nprint(response.json())"}]}},"/withdrawals/{id}":{"get":{"operationId":"34","description":"Plain language: Check details and status for a specific withdrawal.\n\nTechnical details: Authenticated endpoint that returns a withdrawal resource by its ID or withdrawal_id.","tags":["Withdrawals"],"summary":"Get withdrawal details","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Withdrawal ID (MongoDB ObjectId or withdrawal_id UUID)"}],"responses":{"200":{"description":"Successfully retrieved withdrawal details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Withdrawal"}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Withdrawal not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/withdrawals/WITHDRAWAL_ID`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/withdrawals/WITHDRAWAL_ID\", headers=headers)\nprint(response.json())"}]}},"/withdrawals/{id}/claim":{"get":{"operationId":"18","description":"Plain language: Retrieve the proof payload needed to finalize or claim a withdrawal.\\n\\nTechnical details: Authenticated endpoint (step 2) that returns claim details for a previously initiated withdrawal ID.","tags":["Withdrawals"],"summary":"Get withdrawal claim proof","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Withdrawal ID"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WithdrawalClaimResponse"}}}},"400":{"description":"Bad request - Invalid withdrawal ID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden - Withdrawal not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Withdrawal request not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/withdrawals/WITHDRAWAL_ID/claim`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/withdrawals/WITHDRAWAL_ID/claim\", headers=headers)\nprint(response.json())"}]}},"/transfers":{"put":{"operationId":"19","description":"Move an asset to another wallet address on the platform (no on-chain transaction; both balances update in place).\n\nSign with the agent wallet: include `agent_index` in the body and a Schnorr `signature`.\n**Deprecated EIP-191 alternative:** omit `agent_index`; `signature` is an EIP-191 signature.\n\n**Canonical signing payload** (alphabetical order): `{action:'TRANSFER', agent_index, amount, asset, timestamp, to_wallet_address}`. Note `to_wallet_address` in the signing string is the **lowercased** form — the handler normalizes any valid checksum address to lowercase before canonicalizing.\n\n`user_transfer_id` is optional and **not** part of the signed payload — it's an idempotency token (UUIDv7) that the server uses to dedupe retries.","tags":["Transfers"],"summary":"Initiate an internal transfer","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["asset","amount","to_wallet_address","signature","timestamp","agent_index"],"properties":{"asset":{"type":"string","description":"Asset symbol (e.g. `USDC`, `ETH`).","example":"USDC"},"amount":{"type":"string","description":"Amount in base units (e.g. `\"100000000\"` for 100 USDC with 6 decimals).","example":"100000000"},"to_wallet_address":{"type":"string","description":"Destination wallet address. Any valid checksum or lowercase form is accepted; the server lowercases it before signature verification."},"agent_index":{"type":"integer","minimum":0,"maximum":255,"description":"Agent-wallet slot of the agent wallet that signed this request. Omit only when using the deprecated EIP-191 signature."},"signature":{"type":"string","description":"BIP-340 Schnorr signature (128 hex, optional `0x`).\n\n**Deprecated:** EIP-191 signature (132 hex).","example":"0x..."},"timestamp":{"type":"number","description":"Unix timestamp in milliseconds. Within ±5 minutes of server time.","example":1767225600000},"user_transfer_id":{"type":"string","description":"Optional idempotency token (UUIDv7). Duplicate requests with the same `user_transfer_id` for this user return `400 DUPLICATE_TRANSFER_ID`. Invalid format returns `400 INVALID_USER_TRANSFER_ID`. Not part of the signed payload.","example":"019d636a-1c9d-717e-b228-f7b5b44830c4"}}}}}},"responses":{"200":{"description":"Transfer initiated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transfer"}}}},"400":{"description":"Missing/invalid field, invalid amount, unsupported asset, invalid `to_wallet_address` (`code: INVALID_WALLET_ADDRESS`), invalid / duplicate `user_transfer_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — invalid transport auth, or the agent wallet is not registered at `agent_index`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Invalid signature (`code: INVALID_SIGNATURE`) or insufficient balance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Asset or position not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"import { schnorr } from \"@noble/curves/secp256k1\";\n\nconst baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst body = {\n  asset: \"USDC\",\n  amount: \"50000000\",   // base units\n  to_wallet_address: \"0x1111111111111111111111111111111111111111\",\n  agent_index: 1,\n  timestamp: Date.now(),\n};\n\nconst payload = { action: \"TRANSFER\", ...body };\nconst signingString = JSON.stringify(payload, Object.keys(payload).sort());\nconst signature = Buffer.from(\n  schnorr.sign(new TextEncoder().encode(signingString), AGENT_PRIVKEY)\n).toString(\"hex\");\n\nawait fetch(`${baseUrl}/transfers`, {\n  method: \"PUT\",\n  headers: {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": String(Date.now())\n  },\n  body: JSON.stringify({ ...body, signature }),\n}).then(r => r.json());"},{"lang":"Python","label":"Python","source":"import json, time\nfrom coincurve import PrivateKey\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\n\nbody = {\n  \"asset\": \"USDC\",\n  \"amount\": \"50000000\",\n  \"to_wallet_address\": \"0x1111111111111111111111111111111111111111\",\n  \"agent_index\": 1,\n  \"timestamp\": int(time.time() * 1000),\n}\npayload = { \"action\": \"TRANSFER\", **body }\nsigning_string = json.dumps(payload, sort_keys=True, separators=(\", \", \": \"))\n\nagent_priv = PrivateKey.from_hex(AGENT_PRIVKEY_HEX)\nsignature = agent_priv.sign_schnorr(signing_string.encode(\"utf-8\")).hex()\n\nresponse = requests.put(\n  f\"{base_url}/transfers\",\n  json={ **body, \"signature\": signature },\n  headers=HMAC_HEADERS,\n)\nprint(response.json())"}]},"get":{"operationId":"20","description":"Plain language: View your transfer history and statuses.\\n\\nTechnical details: Authenticated paginated endpoint returning transfer records for the current account.","tags":["Transfers"],"summary":"List transfers","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Successfully retrieved list of user's transfers","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PaginatedResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Transfer"}}}}]}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/transfers?page=0&page_size=20`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/transfers\", headers=headers, params={'page': 0, 'page_size': 20})\nprint(response.json())"}]}},"/transfers/{transfer_id}":{"get":{"operationId":"21","description":"Plain language: Check details and status for a specific transfer.\\n\\nTechnical details: Authenticated endpoint that returns a transfer resource by `transfer_id`.","tags":["Transfers"],"summary":"Get transfer details","parameters":[{"name":"transfer_id","in":"path","required":true,"schema":{"type":"string"},"description":"Transfer ID"}],"responses":{"200":{"description":"Successfully retrieved transfer details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transfer"}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Transfer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/transfers/TRANSFER_ID`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/transfers/TRANSFER_ID\", headers=headers)\nprint(response.json())"}]}},"/users/me":{"get":{"operationId":"35","description":"Returns profile information for the authenticated user.","tags":["User & Transaction Info"],"summary":"Get current user profile","responses":{"200":{"description":"Successfully retrieved user profile","content":{"application/json":{"schema":{"type":"object","properties":{"wallet_address":{"type":"string","description":"User's Ethereum wallet address."},"username":{"type":"string","description":"User's display name."},"api_key_count":{"type":"number","description":"Number of active API keys for this user."}}},"example":{"wallet_address":"0x1234567890abcdef1234567890abcdef12345678","username":"trader1","api_key_count":2}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/users/me`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/users/me\", headers=headers)\nprint(response.json())"}]}},"/users/me/fees":{"get":{"operationId":"14","description":"Plain language: See your current trading fee tier and how close you are to the next tier.\n\nTechnical details: Authenticated endpoint returning the caller's effective `maker_ppm` / `taker_ppm` rates, current 30-day rolling USDC volume, and the volume gap to the next tier.","tags":["User & Transaction Info"],"summary":"Get current user fee schedule","responses":{"200":{"description":"Successfully retrieved user fee schedule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserFeeSchedule"},"example":{"partner_id":0,"tier_label":"Pro","manual_override":false,"is_default_profile":false,"rolling_30d_volume":"1234567000000","rolling_30d_volume_formatted":"1234567.00","fees":{"maker_ppm":1000,"taker_ppm":2000,"maker_percentage":"0.1","taker_percentage":"0.2"},"next_tier":{"min_volume":"5000000000000","min_volume_formatted":"5000000.00","volume_to_next":"3765433000000","volume_to_next_formatted":"3765433.00"}}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service Unavailable - Tier configuration not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/users/me/fees`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/users/me/fees\", headers=headers)\nprint(response.json())"}]}},"/users/me/trades":{"get":{"operationId":"16","description":"Plain language: Retrieve your historical executed trades.\\n\\nTechnical details: Authenticated paginated endpoint returning fills/trades for the current user account.","tags":["User & Transaction Info"],"summary":"List user trade history","parameters":[{"name":"ticker","in":"query","required":true,"schema":{"type":"string","default":"BTC_USDC"},"description":"Market symbol (e.g. `BTC_USDC`)"},{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Successfully retrieved trade history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Trade"}}}},"401":{"description":"Unauthorized - Invalid API key or signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests - Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-codeSamples":[{"lang":"JavaScript","label":"JavaScript","source":"const baseUrl = \"https://testnet-api.kalqix.com/v1\";\nconst headers = {\n  \"Content-Type\": \"application/json\",\n  \"x-api-key\": \"YOUR_API_KEY\",\n  \"x-api-signature\": \"GENERATED_SIGNATURE\",\n  \"x-api-timestamp\": String(Date.now())\n};\nfetch(`${baseUrl}/users/me/trades?page=0&page_size=20`, { method: \"GET\", headers })\n  .then((res) => res.json())\n  .then((data) => console.log(data))\n  .catch((err) => console.error(err));"},{"lang":"Python","label":"Python","source":"import time\nimport requests\n\nbase_url = \"https://testnet-api.kalqix.com/v1\"\nheaders = {\n    \"Content-Type\": \"application/json\",\n    \"x-api-key\": \"YOUR_API_KEY\",\n    \"x-api-signature\": \"GENERATED_SIGNATURE\",\n    \"x-api-timestamp\": str(int(time.time() * 1000))\n}\nresponse = requests.get(f\"{base_url}/users/me/trades\", headers=headers, params={'page': 0, 'page_size': 20})\nprint(response.json())"}]}}}}