API Changelog
Kyan API Changelog
All notable changes to the Kyan API will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[1.11.0] - 2025-10-21
Added
-
New
instrumentsWebSocket channel for real-time instrument list updates- Purpose: Receive immediate notifications when trading instruments are added or expire, keeping your application synchronized with available markets
- Benefits: Eliminates need for polling
/instrumentsendpoint, instant awareness of new trading opportunities, automatic cleanup of expired instruments - New capabilities: Subscribe to specific markets (BTC, ETH, ARB) or all markets, receive initial snapshot on subscription, get update timestamp with each event
Example subscription (single market):
{ "type": "subscribe", "subscriptions": [ { "channel": "instruments", "query": { "market": "BTC" } } ] }Example subscription (all markets):
{ "type": "subscribe", "subscriptions": [ { "channel": "instruments", "query": {} } ] }Event data received:
{ "kind": "event", "type": "instruments", "timestamp_ms": 1677721600000, "data": { "updated_at": 1677721600000, "instruments": [ "BTC_USDC-PERPETUAL", "BTC_USDC-31OCT25-130000-C", "BTC_USDC-31OCT25-130000-P", "BTC_USDC-31OCT25-135000-C", "BTC_USDC-31OCT25-135000-P" ] }, "subscription": { "channel": "instruments", "query": { "market": "BTC" } } }Data fields:
updated_at: Unix timestamp in millisecondsinstruments: Array of instrument names currently available for trading
Query parameters:
market(optional): Base token (BTC, ETH, or ARB). If omitted, subscribes to all markets
Use cases:
- Trading applications dynamically updating available instruments
- Automated trading systems detecting new option expirations
- Market monitoring tools tracking instrument lifecycle
- Risk management systems responding to expired instruments
Changed
-
Breaking Change: Endpoint
GET /instrumentsnow returns object with timestamp instead of arrayBefore:
// Old response format const response = await fetch('/instruments?market=BTC'); const instruments: string[] = await response.json(); // Returns: ["BTC_USDC-PERPETUAL", "BTC_USDC-31OCT25-130000-C", ...]After:
// New response format const response = await fetch('/instruments?market=BTC'); const data: { updated_at: number; // Unix timestamp in milliseconds instruments: string[]; } = await response.json(); // Returns: { // updated_at: 1677721600000, // instruments: ["BTC_USDC-PERPETUAL", "BTC_USDC-31OCT25-130000-C", ...] // } // Access instruments array const instruments = data.instruments; // Use timestamp for caching/change detection const lastUpdate = new Date(data.updated_at); // Convert to Date objectBenefits:
- Cache optimization: Use
updated_attimestamp (milliseconds) to implement efficient caching strategies - Change detection: Compare timestamps to determine if instrument list has changed
- Synchronization: Coordinate REST API data with WebSocket
instrumentschannel updates using the same timestamp - Better performance: Avoid unnecessary processing when instrument list hasn't changed
Migration:
- Update response type to expect object instead of array
- Access instruments via
data.instrumentsproperty - Optionally implement caching using
data.updated_attimestamp - Consider migrating to WebSocket
instrumentschannel for real-time updates
- Cache optimization: Use
-
Breaking Change: Endpoint
POST /limitresponse format simplified -matchedfield removedBefore:
// Old response format const response = await fetch('/limit', { method: 'POST', body: JSON.stringify([/* orders */]) }); const result: { posted: Array<Order>; matched: Array<Order>; // Separate array for matched orders rejected: Array<Order>; } = await response.json();After:
// New response format const response = await fetch('/limit', { method: 'POST', body: JSON.stringify([/* orders */]) }); const result: { posted: Array<Order>; // Now includes both posted AND matched orders rejected: Array<Order>; } = await response.json(); // Note: matched field no longer exists - matched orders are merged into 'posted' arrayBenefits:
- Simplified response structure: Easier to process all successful orders in one array
- Reduced complexity: No need to merge
postedandmatchedarrays client-side - Clearer semantics: All successfully processed orders (whether posted to orderbook or immediately matched) are in
posted
Migration:
- Update response type to remove
matchedfield - Process all successful orders from the
postedarray (includes both posted and matched orders) - If you need to distinguish matched orders, check the
order_statefield (will befilledoropen) - Remove any client-side code that separately processed the
matchedarray
Documentation
-
Complete REST API documentation updates
- Updated
/instrumentsendpoint OpenAPI schema with newInstrumentsDataresponse type - Added detailed field descriptions for
updated_atandinstrumentsproperties - Updated endpoint description to highlight new timestamp functionality
- Updated
-
Complete WebSocket API documentation updates
- Added detailed channel description for
instrumentschannel - Added event data structures with field descriptions
- Added subscription examples for both single market and all markets scenarios
- Updated Available Channels table with new
instrumentsentry - Updated Event Types table with
instrumentsevent - Added comprehensive use cases and implementation notes
- Added detailed channel description for
[1.10.0] - 2025-10-14
Added
-
New
mmpWebSocket channel for Market Maker Protection events- Purpose: Monitor when MMP (Market Maker Protection) is triggered, temporarily freezing an account's trading when risk thresholds are exceeded
- Benefits: Real-time notifications of risk threshold violations, proactive risk management, automated trading pause awareness
- New capabilities: Track freeze status, monitor freeze duration, filter by account or trading pair
Example subscription:
{ "channel": "mmp", "query": { "smart_account_address": "0x1234567890abcdef1234567890abcdef12345678", "pair": "BTC_USDC" // optional } }Event data received:
{ "kind": "event", "type": "mmp_triggered", "timestamp_ms": 1677721600000, "data": { "smart_account_address": "0xabCDEF1234567890ABcDEF1234567890aBCDeF12", "pair_symbol": "ETH_USDC", "frozen_until": 1677721660000, "frozen_duration_seconds": 60 } }Query parameters:
smart_account_address(optional): Filter events for a specific smart accountpair(optional): Filter events for a specific trading pair (BTC_USDC, ETH_USDC, or ARB_USDC)
Use cases:
- Market makers monitoring their own MMP status
- Risk management systems tracking protection triggers
- Automated trading bots pausing operations during freeze periods
-
New
bankruptcyWebSocket channel for account bankruptcy events- Purpose: Monitor when account equity becomes negative after liquidation attempts, representing losses absorbed by the insurance fund
- Benefits: Real-time bankruptcy notifications, insurance fund impact tracking, systemic risk monitoring
- New capabilities: Track bankruptcy events by market, monitor insurance fund utilization
Example subscription:
{ "channel": "bankruptcy", "query": { "market": "ETH_USDC" // optional } }Event data received:
{ "kind": "event", "type": "bankruptcy", "timestamp_ms": 1677721600000, "data": { "marginAccountId": "550e8400-e29b-41d4-a716-446655440000", "market": "ETH_USDC" } }Query parameters:
market(optional): Filter events by trading pair (BTC_USDC, ETH_USDC, ARB_USDC, or USDC_USDC)
Use cases:
- Risk managers monitoring systemic risk indicators
- Insurance fund tracking and analysis
- Market health monitoring and alerting
Documentation
- Complete WebSocket API documentation updates
- Added detailed channel descriptions for
mmpandbankruptcychannels - Added event data structures with field descriptions
- Added subscription examples with multiple query parameter combinations
- Updated Available Channels table with new entries
- Updated Event Types table with
mmp_triggeredandbankruptcyevents
- Added detailed channel descriptions for
[1.9.0] - 2025-09-29
Added
-
Future settlement projections in risk calculations (
POST /calculate_user_risk)- New field:
future_settlement_projectionsobject containing risk metrics for future expiration dates - Benefits: Evaluate how portfolio risk evolves as options approach expiration, better risk planning for future scenarios
- Capabilities: Each settlement date includes projected margin requirements (
im,mm), risk components (matrix_risk,delta_risk,roll_risk), and complete Greeks
Example response:
{ "status": "success", "data": { "pair": "ETH_USDC", "im": 1200.00, "mm": 1000.00, "greeks": { /* current greeks */ }, "future_settlement_projections": { "2025-10-31": { "im": 1440.00, "mm": 1200.00, "matrix_risk": 960.00, "delta_risk": 180.00, "roll_risk": 60.00, "greeks": { "delta": 1.8, "gamma": 0.008, "vega": 90.0, "theta": -12.0, "rho": 4.5 } } } } } - New field:
-
New
orderbook_makerWebSocket channel for market makers- Purpose: Dedicated channel for market makers to monitor their own orders efficiently
- Benefits: Initial snapshot of all maker's active orders, real-time updates for only that maker's activity, reduced bandwidth and processing overhead
- Migration: Replaces the
makerfilter previously available inorderbook_optionsandorderbook_perpschannels
Example subscription:
{ "channel": "orderbook_maker", "query": { "maker": "0x1234567890abcdef1234567890abcdef12345678", "pair": "BTC_USDC" // optional } }Events received:
- Initial:
ob_maker_ordersevent with all active orders - Ongoing:
post_orderandcancel_orderevents for that maker only
-
Session revocation enhancements (
DELETE /session)- New capability: Delete all one-click trading sessions for an API key by omitting the
x-one-clickheader - Benefits: Bulk session cleanup, simplified session management for applications with multiple sessions
- Response: Returns count of revoked sessions
Example - Revoke all sessions:
// Without x-one-click header - revokes ALL sessions const response = await fetch('/session', { method: 'DELETE', headers: { 'x-apikey': 'your-api-key' // No x-one-click header } }); // Response: { "revokedSessions": 5 } - New capability: Delete all one-click trading sessions for an API key by omitting the
-
User tracking field in market order responses
- New field:
user_idadded to POST market order responses for analytics and tracking - Benefits: Better order attribution, enhanced analytics capabilities, improved debugging
- Location: Returned in response body after successful market order submission
- New field:
Changed
-
Breaking Change: WebSocket
makerfiltering moved to dedicated channel- Removed:
makerparameter no longer available inorderbook_optionsandorderbook_perpschannels - Replacement: Use the new
orderbook_makerchannel for maker-specific filtering
Before (deprecated):
{ "channel": "orderbook_options", "query": { "pair": "BTC_USDC", "maker": "0x1234..." // No longer supported } }After (required):
{ "channel": "orderbook_maker", "query": { "maker": "0x1234...", // Now in dedicated channel "pair": "BTC_USDC" } }Benefits: Better performance isolation, cleaner API design, optimized for market maker use cases
- Removed:
Updated
- RFQ response requirements clarified
- Clarification: RFQ responses must contain either all option orders OR exactly one perpetual order
- Validation: Cannot mix options and perpetuals in the same RFQ response
- Documentation: Enhanced examples and constraints in RFQ documentation
[1.8.1] - 2025-09-02
Added
- WebSocket trade events now include order size and fill information
- New fields:
order_sizeandfilled_amountadded to all trade events - Benefits: Track partial fills and order completion status in real-time
- Use case: Monitor order execution progress without additional API calls
ws.on('message', (msg) => { if (msg.type === 'trade') { const trade = msg.data; console.log(`Order ${trade.order_id}:`); console.log(` Filled: ${trade.filled_amount} / ${trade.order_size}`); console.log(` Completion: ${(trade.filled_amount / trade.order_size * 100).toFixed(2)}%`); if (trade.filled_amount === trade.order_size) { console.log('Order fully filled!'); } } }); - New fields:
[1.8.0] - 2025-08-30
Added
-
WebSocket orderbook subscription filtering by maker address
- New capability: Filter orderbook events (
post_order,cancel_order,trade) by specific market maker address - Benefits: Reduces bandwidth usage by receiving only relevant orderbook updates, enables tracking specific market makers
- Channels affected:
orderbook_options,orderbook_perps
Example:
// Subscribe to orderbook events from a specific maker only const subscription = { channel: 'orderbook_options', query: { pair: 'BTC_USDC', maker: '0x1234567890abcdef1234567890abcdef12345678' } }; - New capability: Filter orderbook events (
-
WebSocket orderbook snapshot skipping option
- New capability: Skip initial orderbook snapshot when subscribing to orderbook channels
- Benefits: Faster subscription initialization, reduced initial data transfer for clients that only need incremental updates
- Use case: Ideal for applications that maintain their own orderbook state or only need real-time updates
Example:
// Subscribe without receiving initial orderbook state const subscription = { channel: 'orderbook_perps', query: { instrument_name: 'BTC_USDC-PERPETUAL', options: { skip_snapshot: true // Only receive incremental updates } } };
Changed
-
WebSocket orderbook subscriptions now support optional
pairparameter- Breaking Change: The
pairparameter is now optional fororderbook_optionsandorderbook_perpschannels - Benefits: Subscribe to all instruments across all markets in a single subscription, simplified market-wide monitoring
Before:
// Previously required to specify a pair const subscription = { channel: 'orderbook_options', query: { pair: 'BTC_USDC', // Was required maturity: '29AUG25' } };After:
// Now can subscribe to all markets at once const subscription = { channel: 'orderbook_options', query: { // pair is now optional - omit to receive all markets maturity: '29AUG25' // Can filter by maturity across all pairs } }; // Or subscribe to absolutely everything const subscribeToAll = { channel: 'orderbook_perps', query: {} // Receives all perpetual orderbook events };Migration Guide:
- Existing subscriptions with
pairspecified will continue to work unchanged - To subscribe to all markets, simply omit the
pairparameter - Consider using the new
makerfilter orskip_snapshotoption to manage data volume when subscribing broadly
- Breaking Change: The
[1.7.0] - 2025-08-27
🔄 Changed - RFQ Response Event Improvements
Breaking Change: WebSocket rfq_response Event Split into Two Distinct Events
rfq_response Event Split into Two Distinct EventsThe single rfq_response WebSocket event has been split into two semantically distinct events for improved clarity and event handling:
rfq_post_response: Emitted when a market maker posts a new response to an RFQ request with pricingrfq_cancel_response: Emitted when a market maker cancels a previously posted RFQ response
Before:
// Single event type for both posting and cancelling
ws.on('message', (msg) => {
if (msg.type === 'rfq_response') {
// Had to check fills array to determine if it was a post or cancel
if (msg.data.fills && msg.data.fills.length > 0) {
// Handle new response
} else {
// Handle cancellation
}
}
});After:
// Distinct event types for clearer handling
ws.on('message', (msg) => {
if (msg.type === 'rfq_post_response') {
// Handle new RFQ response with pricing
const fills = msg.data.fills; // Always contains pricing data
processPricing(fills);
} else if (msg.type === 'rfq_cancel_response') {
// Handle RFQ response cancellation
const responseId = msg.data.response_id;
removePricing(responseId);
}
});Benefits:
- Clearer semantics: Event type immediately indicates the action without checking payload
- Improved type safety: TypeScript users get better type inference for each event
- Simplified event handling: No need to check fills array to determine event intent
- Better observability: Easier to track and monitor different RFQ response actions
Migration Guide:
- Update WebSocket message handlers to check for
rfq_post_responseandrfq_cancel_responseinstead ofrfq_response - Remove any logic that checks the fills array to determine if it's a cancellation
- Handle each event type with its specific business logic
Note: RFQ cancellations are now properly emitted only on the rfq channel and no longer appear on orderbook channels.
[1.6.1] - 2025-08-27
📝 Fixed - WebSocket Documentation Corrections
Corrected WebSocket Message kind Field Values
kind Field Values- Fixed documentation to accurately reflect the WebSocket message
kindfield values used in the actual implementation - Previous documentation incorrectly showed uppercase values (
"RESPONSE","EVENT") - Corrected values now show lowercase as per the codebase (
"response","event")
Before (Incorrect):
{
"kind": "RESPONSE", // ❌ Incorrect - uppercase
"type": "auth",
"id": "request-123",
"timestamp_ms": 1677721600000,
"success": true
}After (Correct):
{
"kind": "response", // ✅ Correct - lowercase
"type": "auth",
"id": "request-123",
"timestamp_ms": 1677721600000,
"success": true
}Impact:
- No functional changes to the WebSocket API behavior
- Documentation only update to match actual implementation
[1.6.0] - 2025-08-20
✨ Added - Account History Endpoint
New Endpoint: GET /account_history for Complete Trading History
GET /account_history for Complete Trading History- New public REST endpoint for retrieving comprehensive account trading history and events
- Consolidated view: Access all trades and account events (deposits, withdrawals, settlements, funding) in a single request
- Flexible filtering: Query by time range and limit results for efficient data retrieval
- Complete audit trail: Track all account activity for reconciliation and analysis
Usage Example:
// Retrieve account history with optional filters
const response = await fetch('/account_history?' + new URLSearchParams({
address: '0x9a2f0C371820e8BE3D64efb3E814808F231880ff',
start_timestamp: '1704067200', // Optional: Unix timestamp
end_timestamp: '1704153600', // Optional: Unix timestamp
count: '100' // Optional: Max records to return
}));
const data = await response.json();
// Response structure
{
address: '0x9a2f0C371820e8BE3D64efb3E814808F231880ff',
history: {
trades: [
{
trade_id: 'a1b2c3d4e5f678901234567890abcdef',
instrument_name: 'BTC_USDC-29AUG25-106000-C',
direction: 'buy',
size: 1.5,
average_price: 125.50,
realised_pnl: -5.75,
// ... full trade details including fees and greeks
}
],
account_events: [
{
action: 'deposit', // Types: deposit, withdrawal, settlement, funding
amount: 1000.0,
symbol: 'USDC',
timestamp: 1704067500,
// ... complete event details
}
]
}
}[1.5.0] - 2025-08-02
✨ Added - Enhanced Order Tracking
Optional User ID Field for Order Tracking
- Added
user_idfield to all order types for enhanced tracking and analytics:- REST Endpoints: All limit orders (
POST /limit), market orders (POST /market), combo orders (POST /combo), and RFQ orders - WebSocket Events: Trade events now include
user_idfield in data payload - Field Type: Optional string with maximum 36 characters
- Use Cases: Custom order labeling, client-side tracking, analytics categorization, portfolio grouping
- REST Endpoints: All limit orders (
Migration Example:
// Before (existing functionality continues to work)
const limitOrder = {
instrument_name: 'BTC_USDC-29AUG25-106000-C',
type: 'good_til_cancelled',
contracts: 1.5,
direction: 'buy',
price: 1000.5,
// ... other required fields
};
// After (optional user_id field available)
const limitOrder = {
instrument_name: 'BTC_USDC-29AUG25-106000-C',
type: 'good_til_cancelled',
contracts: 1.5,
direction: 'buy',
price: 1000.5,
user_id: 'portfolio_a_trade_001', // New optional field
// ... other required fields
};Benefits:
- Custom tracking: Label orders with your own identifiers for easier management
- Portfolio organization: Group orders by strategy, client, or trading session
- Analytics enhancement: Track performance metrics across custom categories
- Backwards compatible: Existing code continues to work without changes
🔧 Changed - RFQ Validation and Rate Limiting
Breaking Change: RFQ Opposite Direction Requirement
- RFQ responses now require opposite directions between taker requests and maker limit orders
- Traditional market making: Takers request one direction, makers provide liquidity in the opposite direction
- Enhanced validation: System validates direction compatibility before accepting RFQ responses
Before:
// Previously allowed (incorrect market making)
const rfqResponse = {
fills: [
[
{
instrument_name: 'BTC_USDC-29AUG25-106000-C',
contracts: 1.5,
direction: 'buy',
}, // Taker request
{
instrument_name: 'BTC_USDC-29AUG25-106000-C',
contracts: 1.5,
direction: 'buy', // Same direction - previously allowed but incorrect
price: 2500.0,
// ... other limit order fields
},
],
],
};After:
// Now required (correct market making)
const rfqResponse = {
fills: [
[
{
instrument_name: 'BTC_USDC-29AUG25-106000-C',
contracts: 1.5,
direction: 'buy',
}, // Taker request
{
instrument_name: 'BTC_USDC-29AUG25-106000-C',
contracts: 1.5,
direction: 'sell', // Opposite direction - now required
price: 2500.0,
// ... other limit order fields
},
],
],
};Benefits:
- Correct market making: Ensures proper liquidity provision patterns
- Reduced errors: Prevents mismatched trading pairs that could lead to unintended positions
- Market integrity: Aligns with traditional finance market making principles
WebSocket Rate Limiting Scope Change
- Rate limiting changed from per-API-key to per-session for WebSocket connections
- Independent limits: Each WebSocket connection now has its own 15 requests/minute limit
- Same endpoints affected:
get_ob_state_by_instrumentsandget_ob_state_by_market
Before:
// All connections using the same API key shared a single rate limit
// If you had 3 WebSocket connections with the same API key,
// they collectively shared 15 requests/minuteAfter:
// Each WebSocket connection gets its own independent rate limit
// 3 WebSocket connections = 3 × 15 = 45 total requests/minuteBenefits:
- Better scalability: Multiple connections per API key don't interfere with each other
- Fairness: Each connection gets full rate limit allocation
- Simplified management: Rate limits tied to connection lifecycle rather than API key usage
[1.4.0] - 2025-07-26
✨ Added - New Endpoint and Enhanced Features
New REST Endpoint: Index Price Retrieval
- Added
GET /index_priceendpoint for retrieving current index prices- Supported markets: BTC, ETH, ARB
- Data source: Real-time Chainlink oracle feeds via WebSocket streaming
- Response format: Direct numerical value (e.g.,
106500.25) - Authentication: API key required
- Use cases: Portfolio valuation, risk management, strategy analysis, settlement reference
WebSocket Rate Limiting Implementation
- Added per-API-key rate limiting for market data WebSocket messages:
get_ob_state_by_instruments: 15 requests per minute per API keyget_ob_state_by_market: 15 requests per minute per API key
- Enhanced error responses with reset time and remaining request information
- Sliding window algorithm with 60-second windows for fair usage distribution
WebSocket Documentation Enhancements
- Added comprehensive timestamp format clarification:
- Event wrapper timestamps (
timestamp_ms): 13-digit milliseconds for event ordering - Data payload timestamps (
timestamp): Usually 13-digit milliseconds for data-specific times - Creation timestamps (
creation_timestamp): 10-digit seconds for order/request creation
- Event wrapper timestamps (
🔧 Changed - Rate Limiting and Performance
WebSocket Rate Limiting Behavior
- Rate limits now apply per API key instead of global limits
- Enhanced rate limit responses include specific reset timing and remaining request counts
- Alternative guidance provided encouraging subscription-based real-time updates over polling
[1.3.0] - 2025-07-17
✨ Added - API Documentation Enhancements
Enhanced API Documentation Structure
- Added Key Identifier Types section to main API documentation explaining
order_idvstrade_idrelationship - Created comprehensive developer guide (
order_id_vs_trade_id.md) with detailed trading scenarios and examples
Enhanced Batch Order Constraints
- Added detailed constraint documentation for limit order batching:
- All orders must be from the same maker
- All orders must be for the same market (BTC, ETH, or ARB)
- Added comprehensive examples showing valid and invalid batch configurations
- Enhanced error response documentation with specific rejection reasons and examples
Order Cancellation Requirements
- Made
marketfield required inCancelAllOrdersRequestschema (breaking change for order cancellation) - Updated endpoint description to clarify market-specific cancellation behavior
[1.2.0] - 2025-01-10
⚠️ Removed - WebSocket Method
Deprecated get_last_trades_by_instrument WebSocket Method
get_last_trades_by_instrument WebSocket MethodThe get_last_trades_by_instrument WebSocket method has been removed. This method was previously used to retrieve historical trade data through the WebSocket connection.
Migration Guide
Use the REST API endpoint instead:
// Before (WebSocket)
ws.send(
JSON.stringify({
type: 'get_last_trades_by_instrument',
instrument_name: 'BTC_USDC-29AUG25-106000-C',
start_timestamp: 1677721600000,
end_timestamp: 1677808000000,
}),
);
// After (REST API)
const response = await fetch(
`/last_trades_by_instrument?instrument_name=${instrumentName}&start_timestamp=${startTimestamp}&end_timestamp=${endTimestamp}`,
{
headers: {
'x-apikey': API_KEY,
'Content-Type': 'application/json',
},
},
);
const trades = await response.json();Benefits
- Better Performance: REST API is optimized for historical data queries
- Caching: REST responses can be cached by CDNs and browsers
- Simpler Integration: No need to maintain WebSocket connection for historical data
- Standard HTTP: Use familiar HTTP methods and status codes for error handling
📚 Enhanced - Order Submission Documentation
Improved Code Examples and Field Clarifications
Enhanced the order submission documentation with clearer examples and important field requirements:
- Signature Requirements: Clearly documented that both
signatureandsignature_deadlineare required when not using one-click sessions - Separate Examples: Added distinct examples for options and perpetual orders showing the correct field usage
- Field Clarifications:
- Options orders use
contractsfield - Perpetual orders use
amountfield - The
takerfield is optional and defaults to zero address (any taker)
- Options orders use
New Code Examples
// Options Order Example
const optionsOrder = {
instrument_name: 'BTC_USDC-29AUG25-106000-C',
type: 'good_til_cancelled',
contracts: 1.5, // For options
direction: 'buy',
price: 2500,
// ... other fields
};
// Perpetuals Order Example
const perpsOrder = {
instrument_name: 'BTC_USDC-PERPETUAL',
type: 'good_til_cancelled',
amount: 10000, // For perpetuals
direction: 'buy',
price: 45000,
// ... other fields
};🔧 Enhanced - Error Response Documentation
Detailed Validation Error Structure
Order rejection responses now include detailed validation error information when the rejection reason is "invalid request":
{
"rejected_orders": [
{
"order_id": "abc123",
"reason": "invalid request",
"error": [
{
"instancePath": "/orders/0/contracts",
"schemaPath": "#/properties/contracts/minimum",
"keyword": "minimum",
"params": { "limit": 0 },
"message": "must be >= 0"
}
]
}
]
}Benefits
- Precise Error Location:
instancePathshows exactly which field failed validation - Clear Error Messages: Human-readable messages explain what went wrong
- Faster Debugging: Developers can quickly identify and fix validation issues
[1.1.1] - 2025-01-09
🔧 Fixed - API Header Standardization
API Key Header Casing
Standardized the API key header name to use consistent lowercase formatting:
Before:
X-APIKey: your-api-key-hereAfter:
x-apikey: your-api-key-hereMigration Guide
Update your API requests to use the lowercase header:
// Before
const response = await fetch('/instruments?market=ETH', {
headers: {
'X-APIKey': API_KEY,
'Content-Type': 'application/json',
},
});
// After
const response = await fetch('/instruments?market=ETH', {
headers: {
'x-apikey': API_KEY,
'Content-Type': 'application/json',
},
});Benefits
- Consistent Header Casing: All headers now follow lowercase convention
- HTTP/2 Compatibility: Lowercase headers are required for HTTP/2
- Framework Alignment: Matches standard practices across modern APIs
🔧 Fixed - WebSocket Event Types
Corrected Event Type Naming
Fixed inconsistent event type naming in WebSocket documentation:
Before:
{
"type": "withdraw",
"action": "withdraw"
}After:
{
"type": "withdrawal",
"action": "withdrawal"
}Migration Guide
Update your WebSocket event handlers:
// Before
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.type === 'withdraw') {
// Handle withdrawal event
}
};
// After
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.type === 'withdrawal') {
// Handle withdrawal event
}
};Benefits
- Consistency: Event types now match the implementation and enum definitions
- Clarity: "withdrawal" is more descriptive than "withdraw"
- Type Safety: Consistent naming improves TypeScript integration
[1.1.0] - 2025-01-04
🚀 Enhanced - Account State Endpoint
Improved Risk & Market Data
The /account_state/{account} endpoint now provides significantly more detailed information to support advanced trading strategies and risk management.
Breaking Changes
-
Response Structure Flattened: The
summarywrapper object has been removed. Account state fields are now directly accessible at the root level of each margin account.Before:
{ "margin_accounts": [ { "pair": "ETH_USDC", "summary": { "equity": 10500.0, "im": 2000.0, "mm": 1500.0, "pnl": 500.0 }, "positions": [...] } ] }After:
{ "margin_accounts": [ { "pair": "ETH_USDC", "timestamp": 1677721600000, "margin_account": 12345, "equity": 10500.0, "im": 2000.0, "mm": 1500.0, "unrealised_pnl": 500.0, // ... additional fields "positions": [...] } ] }
New Response Fields
timestamp: Unix timestamp when the account state was calculatedmargin_account: Unique margin account identifiermatrix_risk: Portfolio risk matrix component for comprehensive risk assessmentdelta_risk: Delta risk component measuring directional exposureroll_risk: Roll risk component for near-expiry option positionsportfolio_greeks: Portfolio-level Greeks aggregationdelta: Portfolio delta exposuregamma: Portfolio gamma exposurevega: Portfolio vega exposuretheta: Portfolio theta (time decay)rho: Portfolio rho (interest rate sensitivity)
Enhanced Position Data
Positions now include real-time market data and risk metrics:
For Options:
instrument_type: Always "option" for option positionsmark_price: Current mark price of the optionmark_iv: Mark implied volatilitymark_interest: Mark interest rate used in pricingposition_greeks: Position-level Greeksdelta,gamma,theta,vega,rho
For Perpetuals:
instrument_type: Always "perp" for perpetual positionsmark_price: Current mark price of the perpetualcurrent_funding_rate: Current funding rateposition_greeks: Position-level Greeksdelta
Migration Guide
Update your code to access account state fields directly:
// Before
const equity = accountState.margin_accounts[0].summary.equity;
const im = accountState.margin_accounts[0].summary.im;
// After
const equity = accountState.margin_accounts[0].equity;
const im = accountState.margin_accounts[0].im;
// New capabilities
const portfolioGreeks = accountState.margin_accounts[0].portfolio_greeks;
const riskBreakdown = {
matrix: accountState.margin_accounts[0].matrix_risk,
delta: accountState.margin_accounts[0].delta_risk,
roll: accountState.margin_accounts[0].roll_risk,
};Benefits
- Better Risk Management: Detailed risk component breakdown enables more sophisticated risk monitoring
- Real-time Market Data: Position-level mark prices and Greeks for accurate P&L calculation
- Reduced API Calls: Mark prices and Greeks available directly without additional requests
- Enhanced Analytics: Portfolio-level Greeks aggregation for portfolio analysis
- Streamlined Integration: Simplified response structure reduces parsing complexity
For questions or support, please contact our development team or visit our documentation.
