Unofficial Kotlin/Java SDK for the Fyers trading platform. Supports REST APIs and real-time WebSocket streaming.
Gradle (Kotlin DSL)
implementation("io.github.sonicalgo:fyers-java-sdk:1.2.0")Gradle (Groovy)
implementation 'io.github.sonicalgo:fyers-java-sdk:1.2.0'Maven
<dependency>
<groupId>io.github.sonicalgo</groupId>
<artifactId>fyers-java-sdk</artifactId>
<version>1.2.0</version>
</dependency>Kotlin
import io.github.sonicalgo.fyers.Fyers
import io.github.sonicalgo.fyers.usecase.*
import io.github.sonicalgo.fyers.common.*
import io.github.sonicalgo.fyers.common.Exchange.*
import io.github.sonicalgo.fyers.util.*
fun main() {
val fyers = Fyers.builder()
.appId("your-app-id")
.accessToken("your-access-token")
.build()
// Get user profile
val profile = fyers.getProfile()
println("Hello, ${profile.name}!")
// Place an order using Kotlin DSL
val orderId = fyers.placeOrder(PlaceOrderParams {
symbol = NSE.equity("SBIN")
qty = 1
type = OrderType.MARKET
side = OrderSide.BUY
productType = ProductType.INTRADAY
validity = OrderValidity.DAY
})
println("Order placed: $orderId")
// Get market quotes
val quotes = fyers.getQuotes(listOf(NSE.equity("SBIN"), NSE.equity("HDFCBANK")))
quotes.forEach { quote ->
// values is nullable - null if symbol is invalid or market data unavailable
println("${quote.name}: LTP = ${quote.values?.lastPrice}")
}
fyers.close()
}Java
import io.github.sonicalgo.fyers.Fyers;
import io.github.sonicalgo.fyers.usecase.*;
import io.github.sonicalgo.fyers.common.*;
import io.github.sonicalgo.fyers.util.Symbol;
public class Main {
public static void main(String[] args) {
Fyers fyers = Fyers.builder()
.appId("your-app-id")
.accessToken("your-access-token")
.build();
try {
// Get user profile
var profile = fyers.getProfile();
System.out.println("Hello, " + profile.getName() + "!");
// Place an order using Builder pattern
var orderId = fyers.placeOrder(new PlaceOrderParamsBuilder()
.symbol(Symbol.equity(Exchange.NSE, "SBIN"))
.qty(1)
.type(OrderType.MARKET)
.side(OrderSide.BUY)
.productType(ProductType.INTRADAY)
.validity(OrderValidity.DAY)
.build());
System.out.println("Order placed: " + orderId);
} finally {
fyers.close();
}
}
}Note: All subsequent examples assume the SDK is initialized as shown above.
- Why This SDK?
- Features
- Type-Safe Enums
- API Reference
- Configuration
- Authentication
- REST API Reference
- WebSocket Streaming
- Error Handling
- Symbol Format
- Symbol Builder
| Benefit | Description |
|---|---|
| Type-Safe API | Strongly typed enums prevent invalid parameters at compile time |
| Complete Trading Stack | 50+ REST methods: orders, positions, holdings, market data, GTT, eDIS |
| Built-in TOTP | Automatic login with no external authenticator dependencies |
| 2 WebSocket Protocols | HSM (quotes, 5-depth), Order stream - pick what you need |
| Batch Operations | Place/modify/cancel up to 10 orders in a single API call |
| Bandwidth Optimization | LITE mode for market data (4 fields vs 20+) |
| Thread-Safe | HTTP client and WebSocket clients safe for concurrent use |
| Auto-Reconnect | Exponential backoff with automatic resubscription |
| Per-Instance Design | Multiple SDK instances for different trading accounts |
| Unwrapped Responses | Methods return data directly, not wrapper objects |
- User: Profile, funds/margin info
- Orders: Single, multi (batch 10), multi-leg spreads
- GTT: Place, modify, cancel, query triggered orders
- Portfolio: Positions, holdings, exit by ID/filter, position conversion
- Market Data: Quotes, 5-level depth, historical candles, option chains
- Utilities: Symbol master, market status, SPAN margin calculator
| Client | Protocol | Best For |
|---|---|---|
MarketFeedClient |
Binary HSM | Quotes, LTP, OHLC, 5-depth (RECOMMENDED) |
OrderStreamClient |
JSON | Order/trade/position updates |
- OAuth flow with authorization URL generation
- Automatic TOTP login - built-in RFC 6238 generator
- Refresh token support with PIN verification
- Session logout
- Builder pattern for SDK configuration
- Flat API (
fyers.placeOrder()notfyers.orders().place()) - Symbol builder helpers (
NSE.equity("SBIN")) - Comprehensive input validation
- Full KDoc with examples
The SDK provides type-safe enums for all API parameters:
// Order types
OrderType.LIMIT // 1 - Limit order, executed at specified price or better
OrderType.MARKET // 2 - Market order, executed at current market price
OrderType.STOP // 3 - Stop-Loss Market (SL-M), becomes market order when stop price is hit
OrderType.STOP_LIMIT // 4 - Stop-Loss Limit (SL-L), becomes limit order when stop price is hit
// Order side
OrderSide.BUY // 1 - Buy order
OrderSide.SELL // -1 - Sell order
// Product types
ProductType.CNC // Cash and Carry - For equity delivery, positions carried forward
ProductType.INTRADAY // Intraday - Positions squared off same day
ProductType.MARGIN // Margin - For derivatives, positions carried forward
ProductType.CO // Cover Order - With mandatory stop loss
ProductType.BO // Bracket Order - With stop loss and take profit
ProductType.MTF // Margin Trading Facility - For approved symbols only
// Order validity
OrderValidity.DAY // Valid till end of trading day
OrderValidity.IOC // Immediate or Cancel - Execute immediately or cancel
// Position side
PositionSide.LONG // 1 - Long position (bought)
PositionSide.SHORT // -1 - Short position (sold)
PositionSide.CLOSED // 0 - Closed position
// Segments
Segment.EQUITY // 10 - Capital Market / Equity
Segment.FNO // 11 - Equity Derivatives / F&O
Segment.CURRENCY // 12 - Currency Derivatives
Segment.COMMODITY // 20 - Commodity Derivatives
// Exchanges
Exchange.NSE // 10 - National Stock Exchange
Exchange.BSE // 12 - Bombay Stock Exchange
Exchange.MCX // 11 - Multi Commodity ExchangeAll methods are called directly on the Fyers instance:
| Method | Description |
|---|---|
getAuthorizationUrl() |
Get OAuth URL |
validateAuthCode() |
Exchange code for token |
validateRefreshToken() |
Refresh access token |
logout() |
Invalidate session |
login() |
Auto login with TOTP |
getProfile() |
Get user profile |
getFunds() |
Get fund/margin info |
placeOrder() |
Place single order |
placeMultiOrder() |
Place multiple orders |
placeMultiLegOrder() |
Place multi-leg order |
modifyOrder() |
Modify order |
modifyMultiOrder() |
Modify multiple orders |
cancelOrder() |
Cancel order |
cancelMultiOrder() |
Cancel multiple orders |
getOrders() |
Get order book |
getOrderById() |
Get specific order |
getOrdersByTag() |
Get orders by tag |
getTrades() |
Get trade book |
getTradesByTag() |
Get trades by tag |
getPositions() |
Get positions |
exitPositionById() |
Exit position by ID |
exitPositionsByIds() |
Exit multiple positions |
exitAllPositions() |
Exit all positions |
exitPositionsByFilter() |
Exit by filter |
convertPosition() |
Convert position |
cancelPendingOrders() |
Cancel pending orders |
getHoldings() |
Get holdings |
getHistory() |
Get historical data |
getQuotes() |
Get quotes |
getMarketDepth() |
Get market depth |
getOptionChain() |
Get option chain |
getMarketStatus() |
Get market status |
getSymbolMaster() |
Get symbol master |
getSpanMargin() |
Calculate SPAN margin |
getMultiOrderMargin() |
Calculate multi-order margin |
placeGttOrder() |
Place GTT order |
modifyGttOrder() |
Modify GTT order |
cancelGttOrder() |
Cancel GTT order |
getGttOrders() |
Get GTT orders |
generateTpin() |
Generate TPIN |
getEdisDetails() |
Get eDIS details |
initiateEdis() |
Initiate eDIS |
inquireEdis() |
Inquire eDIS status |
| Option | Default | Description |
|---|---|---|
appId |
- | Your Fyers app ID (required) |
accessToken |
- | Access token from authentication (can set later) |
loggingEnabled |
false |
Enable HTTP request/response logging (logs URL, method, headers, body) |
rateLimitRetries |
0 |
Number of retries on rate limit (HTTP 429). Range: 0-5. Uses exponential backoff. |
val fyers = Fyers.builder()
.appId("your-app-id")
.accessToken("your-access-token")
.loggingEnabled(true)
.rateLimitRetries(3)
.build()
// Update credentials at runtime
fyers.setAccessToken("new-token")
fyers.setAppId("new-app-id")| Option | Default | Description |
|---|---|---|
maxReconnectAttempts |
5 |
Maximum reconnection attempts (1-20) |
autoReconnectEnabled |
true |
Enable automatic reconnection |
autoResubscribeEnabled |
true |
Auto-resubscribe after reconnect |
- Register at Fyers API Portal
- Create an app to get your
app_idandapp_secret - Set up a redirect URL for OAuth callback
val fyers = Fyers.builder()
.appId("your-app-id")
.build()
// Step 1: Generate authorization URL
val authUrl = fyers.getAuthorizationUrl(
redirectUri = "https://your-app.com/callback",
state = "random-state"
)
// Redirect user to authUrl
// Step 2: Exchange auth code for access token
val tokenData = fyers.validateAuthCode(
appSecret = "your-app-secret",
code = "auth-code-from-callback"
)
// Step 3: Configure SDK with access token
fyers.setAccessToken(tokenData.accessToken!!)Kotlin:
val fyers = Fyers.builder()
.appId("your-app-id")
.build()
val tokenData = fyers.login(
clientId = "FY12345",
totpSecret = "your-totp-secret",
pin = "1234",
appSecret = "your-app-secret",
redirectUri = "https://your-app.com/callback"
)
// Access token is automatically configured - ready to use!
val profile = fyers.getProfile()Java:
TokenData tokenData = fyers.login(
"FY12345",
"your-totp-secret",
"1234",
"your-app-secret",
"https://your-app.com/callback"
);val newAccessToken = fyers.validateRefreshToken(
appSecret = "your-app-secret",
refreshToken = "your-refresh-token",
pin = "1234"
)
fyers.setAccessToken(newAccessToken)// Invalidate the current session
fyers.logout()// Get profile
val profile = fyers.getProfile()
println("Name: ${profile.name}")
println("Email: ${profile.emailId}")
// Get funds
val funds = fyers.getFunds()
funds.forEach { fund ->
println("${fund.title}: ${fund.equityAmount}")
}Kotlin:
val params = PlaceOrderParams {
symbol = NSE.equity("SBIN")
qty = 10
type = OrderType.LIMIT
side = OrderSide.BUY
productType = ProductType.INTRADAY
validity = OrderValidity.DAY
limitPrice = 650.0
}
val orderId = fyers.placeOrder(params)Java:
PlaceOrderParams params = new PlaceOrderParamsBuilder()
.symbol(Symbol.equity(Exchange.NSE, "SBIN"))
.qty(10)
.type(OrderType.LIMIT)
.side(OrderSide.BUY)
.productType(ProductType.INTRADAY)
.validity(OrderValidity.DAY)
.limitPrice(650.0)
.build();
String orderId = fyers.placeOrder(params);Kotlin:
val params = ModifyOrderParams {
id = orderId
qty = 15
type = OrderType.LIMIT
limitPrice = 655.0
}
fyers.modifyOrder(params)Java:
ModifyOrderParams params = new ModifyOrderParamsBuilder()
.id(orderId)
.qty(15)
.type(OrderType.LIMIT)
.limitPrice(655.0)
.build();
fyers.modifyOrder(params);fyers.cancelOrder(orderId)// Place multiple orders (max 10) using DSL
val results = fyers.placeMultiOrder(listOf(
PlaceOrderParams {
symbol = NSE.equity("SBIN")
qty = 10
type = OrderType.MARKET
side = OrderSide.BUY
productType = ProductType.INTRADAY
validity = OrderValidity.DAY
},
PlaceOrderParams {
symbol = NSE.equity("HDFCBANK")
qty = 5
type = OrderType.MARKET
side = OrderSide.BUY
productType = ProductType.INTRADAY
validity = OrderValidity.DAY
}
))
results.forEach { result ->
if (result.isSuccess) println("Order placed: ${result.body?.id}")
else println("Failed: ${result.statusDescription}")
}
// Modify multiple orders
val modifyResults = fyers.modifyMultiOrder(listOf(
ModifyOrderParams {
id = "order1"
type = OrderType.LIMIT
limitPrice = 100.0
},
ModifyOrderParams {
id = "order2"
type = OrderType.LIMIT
limitPrice = 200.0
}
))
// Cancel multiple orders
val cancelResults = fyers.cancelMultiOrder(listOf("order1", "order2"))Kotlin:
val params = PlaceMultiLegOrderParams {
productType = ProductType.INTRADAY
orderType = MultiLegOrderType.TWO_LEG
validity = OrderValidity.IOC
legs = MultiLegOrderLegs {
leg1 = MultiLegOrderLeg {
symbol = NSE.option("NIFTY25JAN2322500CE")
qty = 50
side = OrderSide.BUY
type = OrderType.LIMIT
limitPrice = 100.0
}
leg2 = MultiLegOrderLeg {
symbol = NSE.option("NIFTY25JAN2322600CE")
qty = 50
side = OrderSide.SELL
type = OrderType.LIMIT
limitPrice = 80.0
}
}
}
val orderId = fyers.placeMultiLegOrder(params)Java:
PlaceMultiLegOrderParams params = new PlaceMultiLegOrderParamsBuilder()
.productType(ProductType.INTRADAY)
.orderType(MultiLegOrderType.TWO_LEG)
.validity(OrderValidity.IOC)
.legs(new MultiLegOrderLegsBuilder()
.leg1(new MultiLegOrderLegBuilder()
.symbol(Symbol.option(Exchange.NSE, "NIFTY25JAN2322500CE"))
.qty(50)
.side(OrderSide.BUY)
.type(OrderType.LIMIT)
.limitPrice(100.0)
.build())
.leg2(new MultiLegOrderLegBuilder()
.symbol(Symbol.option(Exchange.NSE, "NIFTY25JAN2322600CE"))
.qty(50)
.side(OrderSide.SELL)
.type(OrderType.LIMIT)
.limitPrice(80.0)
.build())
.build())
.build();
String orderId = fyers.placeMultiLegOrder(params);// Get all orders
val orders = fyers.getOrders()
orders.forEach { order ->
println("${order.id}: ${order.symbol} - ${order.status}")
}
// Get specific order by ID
val order = fyers.getOrderById("2420611000001")
// Get orders by tag
val taggedOrders = fyers.getOrdersByTag("my-strategy")
// Get trades
val trades = fyers.getTrades()
trades.forEach { trade ->
println("${trade.symbol}: ${trade.tradedQuantity} @ ${trade.tradePrice}")
}
// Get trades by tag
val taggedTrades = fyers.getTradesByTag("my-strategy")Kotlin:
// Place GTT order
val placeParams = PlaceGttOrderParams {
symbol = NSE.equity("SBIN")
side = OrderSide.BUY
productType = ProductType.CNC
orderInfo = GttOrderInfo {
leg1 = GttOrderLeg {
price = 605.0
triggerPrice = 600.0
qty = 10
}
}
}
val gttId = fyers.placeGttOrder(placeParams)
// Get GTT orders
val gttOrders = fyers.getGttOrders()
// Modify GTT order
val modifyParams = ModifyGttOrderParams {
id = gttId
orderInfo = GttOrderInfo {
leg1 = GttOrderLeg {
price = 610.0
triggerPrice = 605.0
qty = 15
}
}
}
fyers.modifyGttOrder(modifyParams)
// Cancel GTT order
fyers.cancelGttOrder(gttId)Java:
// Place GTT order
PlaceGttOrderParams placeParams = new PlaceGttOrderParamsBuilder()
.symbol(Symbol.equity(Exchange.NSE, "SBIN"))
.side(OrderSide.BUY)
.productType(ProductType.CNC)
.orderInfo(new GttOrderInfoBuilder()
.leg1(new GttOrderLegBuilder()
.price(605.0)
.triggerPrice(600.0)
.qty(10)
.build())
.build())
.build();
String gttId = fyers.placeGttOrder(placeParams);
// Modify GTT order
ModifyGttOrderParams modifyParams = new ModifyGttOrderParamsBuilder()
.id(gttId)
.orderInfo(new GttOrderInfoBuilder()
.leg1(new GttOrderLegBuilder()
.price(610.0)
.triggerPrice(605.0)
.qty(15)
.build())
.build())
.build();
fyers.modifyGttOrder(modifyParams);// Get positions
val positionsData = fyers.getPositions()
positionsData.netPositions.forEach { position ->
println("${position.symbol}: Qty=${position.netQuantity}, P&L=${position.realizedPl}")
}
// Exit position by ID
fyers.exitPositionById("NSE:SBIN-EQ-INTRADAY")
// Exit multiple positions by IDs
fyers.exitPositionsByIds(listOf("NSE:SBIN-EQ-INTRADAY", "NSE:HDFCBANK-EQ-INTRADAY"))
// Exit all positions
fyers.exitAllPositions()
// Cancel all pending orders (optional: pass position ID to cancel for specific position)
fyers.cancelPendingOrders()
// Exit positions by filter using DSL
fyers.exitPositionsByFilter(ExitPositionByFilterParams {
segment = listOf(Segment.EQUITY)
side = listOf(PositionSide.LONG)
productType = listOf(ProductType.INTRADAY)
})
// Convert position using DSL
fyers.convertPosition(ConvertPositionParams {
symbol = NSE.equity("SBIN")
positionSide = PositionSide.LONG
convertQty = 10
convertFrom = ProductType.INTRADAY
convertTo = ProductType.CNC
overnight = 0
})val holdingsData = fyers.getHoldings()
holdingsData.holdings.forEach { holding ->
println("${holding.symbol}: Qty=${holding.quantity}, P&L=${holding.profitLoss}")
}val quotes = fyers.getQuotes(listOf(NSE.equity("SBIN"), NSE.equity("HDFCBANK")))
quotes.forEach { quote ->
// values is nullable - null if symbol is invalid or market data unavailable
println("${quote.name}: LTP=${quote.values?.lastPrice}")
}val depthMap = fyers.getMarketDepth(
symbol = NSE.equity("SBIN"),
includeOhlcv = true
)Kotlin:
val params = HistoryParams {
symbol = NSE.equity("SBIN")
resolution = Resolution.DAY
rangeFrom = "2025-01-01"
rangeTo = "2025-12-31"
dateFormat = DateFormat.FORMATTED
}
val candles = fyers.getHistory(params)
// Returns List<Candle> with timestamp, open, high, low, close, volume, openInterest
candles.forEach { candle ->
println("${candle.timestamp}: O=${candle.open} H=${candle.high} L=${candle.low} C=${candle.close} V=${candle.volume}")
}Java:
HistoryParams params = new HistoryParamsBuilder()
.symbol(Symbol.equity(Exchange.NSE, "SBIN"))
.resolution(Resolution.DAY)
.rangeFrom("2025-01-01")
.rangeTo("2025-12-31")
.dateFormat(DateFormat.FORMATTED)
.build();
List<Candle> candles = fyers.getHistory(params);val optionChainData = fyers.getOptionChain(
symbol = NSE.index("NIFTY50"),
strikeCount = 10
)
// Returns flat list of options - filter by optionType: "" (underlying), "CE" (call), "PE" (put)
optionChainData.optionsChain?.forEach { item ->
when (item.optionType) {
"" -> println("Underlying: ${item.symbol} LTP=${item.lastPrice}")
"CE" -> println("Call: Strike=${item.strikePrice} LTP=${item.lastPrice} OI=${item.openInterest}")
"PE" -> println("Put: Strike=${item.strikePrice} LTP=${item.lastPrice} OI=${item.openInterest}")
}
}// Get symbol master for a segment (NSE_CM, NSE_FO, BSE_CM, MCX_COM, etc.)
val symbols = fyers.getSymbolMaster(SymbolMasterSegment.NSE_FO)
symbols.forEach { (symbol, info) ->
println("$symbol: Lot=${info.minLotSize}, Tick=${info.tickSize}")
}Kotlin:
// SPAN margin calculation
val spanItem = SpanMarginItem {
symbol = NSE.option("NIFTY25JAN2322500CE")
qty = 50
side = OrderSide.BUY
type = OrderType.MARKET
productType = ProductType.INTRADAY
}
val marginData = fyers.getSpanMargin(listOf(spanItem))
println("Total margin required: ${marginData.totalMargin}")
// Multi-order margin calculation
val marginItem = MultiOrderMarginItem {
symbol = NSE.equity("SBIN")
qty = 100
side = OrderSide.BUY
type = OrderType.MARKET
productType = ProductType.CNC
}
val multiMargin = fyers.getMultiOrderMargin(listOf(marginItem))
println("New order margin: ${multiMargin.newOrderMargin}")Java:
// SPAN margin calculation
SpanMarginItem spanItem = new SpanMarginItemBuilder()
.symbol(Symbol.option(Exchange.NSE, "NIFTY25JAN2322500CE"))
.qty(50)
.side(OrderSide.BUY)
.type(OrderType.MARKET)
.productType(ProductType.INTRADAY)
.build();
SpanMarginData marginData = fyers.getSpanMargin(List.of(spanItem));
// Multi-order margin calculation
MultiOrderMarginItem marginItem = new MultiOrderMarginItemBuilder()
.symbol(Symbol.equity(Exchange.NSE, "SBIN"))
.qty(100)
.side(OrderSide.BUY)
.type(OrderType.MARKET)
.productType(ProductType.CNC)
.build();
MultiOrderMarginData multiMargin = fyers.getMultiOrderMargin(List.of(marginItem));Kotlin:
// Generate TPIN
fyers.generateTpin()
// Get EDIS details
val details = fyers.getEdisDetails()
// Initiate EDIS transaction
val record = EdisRecord { isinCode = "INE062A01020"; qty = "10"; symbol = NSE.equity("SAIL") }
val cdslForm = fyers.initiateEdis(listOf(record))
// Inquire EDIS status
val inquiry = fyers.inquireEdis("txn-12345")Java:
// Initiate EDIS transaction
EdisRecord record = new EdisRecordBuilder()
.isinCode("INE062A01020").qty("10").symbol("NSE:SAIL-EQ")
.build();
String cdslForm = fyers.initiateEdis(List.of(record));The SDK provides two WebSocket clients for real-time data:
| Client | Protocol | Use Case |
|---|---|---|
| MarketFeedClient | Binary HSM | LTP, quotes, 5-level depth (RECOMMENDED) |
| OrderStreamClient | JSON | Orders, trades, positions |
- For real-time quotes, LTP, OHLC → Use
MarketFeedClient(most efficient) - For 5-level market depth → Use
MarketFeedClientwithDataType.DEPTH - For order/trade/position updates → Use
OrderStreamClient(auto-subscribes on connect)
Tip:
MarketFeedClientsupports two modes:
FULLmode (default): 20+ fields including OHLC, volume, bid/askLITEmode: Only 4 fields (symbol, ltp, change, changePercent) - saves bandwidth
The Market Feed client uses Fyers' binary HSM protocol for efficient real-time market data.
FULL Mode (default) - Complete market data with 20+ fields:
val marketFeedClient = fyers.createMarketFeedClient(
maxReconnectAttempts = 5,
autoReconnectEnabled = true,
autoResubscribeEnabled = true
)
marketFeedClient.addListener(object : MarketFeedListener {
override fun onConnected() {
println("Connected!")
// Subscribe to quote updates (LTP, OHLC, volume, bid/ask) - QUOTE is default
marketFeedClient.subscribe(listOf(NSE.equity("SBIN"), NSE.equity("HDFCBANK")))
// Subscribe to 5-level depth
marketFeedClient.subscribe(listOf(NSE.equity("SBIN")), DataType.DEPTH)
// Subscribe to index (use quotes for index symbols)
marketFeedClient.subscribe(listOf(NSE.index("NIFTY50")))
}
override fun onDisconnected(code: Int, reason: String) {
println("Disconnected: $reason")
}
override fun onFullQuoteUpdate(update: MarketQuoteUpdate) {
// Full data: symbol, ltp, open, high, low, volume, bid/ask, etc. (20+ fields)
println("${update.symbol}: LTP=${update.ltp} Vol=${update.volume}")
}
override fun onFullIndexUpdate(update: MarketIndexUpdate) {
println("${update.symbol}: LTP=${update.ltp}")
}
override fun onDepthUpdate(update: MarketDepthUpdate) {
println("${update.symbol}: Bids=${update.bids.size} Asks=${update.asks.size}")
}
override fun onError(error: Throwable) {
error.printStackTrace()
}
})
marketFeedClient.connect()LITE Mode - Minimal bandwidth with only 4 fields (symbol, ltp, change, changePercent):
val liteClient = fyers.createMarketFeedClient()
liteClient.addListener(object : MarketFeedListener {
override fun onConnected() {
liteClient.setMode(DataMode.LITE) // Switch to LITE mode
liteClient.subscribe(listOf(NSE.equity("SBIN")))
}
override fun onLiteQuoteUpdate(update: LiteQuoteUpdate) {
// Only 4 fields: symbol, ltp, change, changePercent
println("${update.symbol}: LTP=${update.ltp} Change=${update.changePercent}%")
}
override fun onLiteIndexUpdate(update: LiteIndexUpdate) {
println("${update.symbol}: LTP=${update.ltp} Change=${update.changePercent}%")
}
})
liteClient.connect()Market Feed API:
| Method | Description |
|---|---|
subscribe(symbols) |
Subscribe to quotes (default) |
subscribe(symbols, DataType.DEPTH) |
Subscribe to 5-level depth |
unsubscribe(symbols) |
Auto-detects type and unsubscribes |
setMode(DataMode.LITE) |
LITE mode - only onLiteQuoteUpdate/onLiteIndexUpdate callbacks |
setMode(DataMode.FULL) |
FULL mode - only onFullQuoteUpdate/onFullIndexUpdate callbacks (default) |
Listener Callbacks:
| Callback | Mode | Fields |
|---|---|---|
onFullQuoteUpdate(MarketQuoteUpdate) |
FULL | 20+ fields (LTP, OHLC, volume, bid/ask, etc.) |
onLiteQuoteUpdate(LiteQuoteUpdate) |
LITE | 4 fields (symbol, ltp, change, changePercent) |
onFullIndexUpdate(MarketIndexUpdate) |
FULL | 8 fields (LTP, OHLC, etc.) |
onLiteIndexUpdate(LiteIndexUpdate) |
LITE | 4 fields (symbol, ltp, change, changePercent) |
onDepthUpdate(MarketDepthUpdate) |
Both | 5-level bid/ask depth |
The Order Stream client auto-subscribes to all update types on connect:
val orderClient = fyers.createOrderStreamClient(
maxReconnectAttempts = 5,
autoReconnectEnabled = true
)
// Auto-subscribes to all updates (orders, trades, positions, eDIS)
// Required callbacks: onConnected, onDisconnected, onError
orderClient.addListener(object : OrderStreamListener {
override fun onConnected() {
println("Connected!")
}
override fun onOrderUpdate(order: WsOrderUpdate) {
println("Order: ${order.id} - Status: ${order.status}")
}
override fun onDisconnected(code: Int, reason: String) {
println("Disconnected: $reason")
}
override fun onError(error: Throwable) {
error.printStackTrace()
}
// Other optional callbacks: onTradeUpdate(), onPositionUpdate(), onEdisUpdate(), etc.
})
orderClient.connect()
// Cleanup
orderClient.close()All API methods throw FyersApiException on failure:
try {
val orderId = fyers.placeOrder(params)
} catch (e: FyersApiException) {
println("Error: ${e.message}") // Raw response body from API
println("HTTP Status: ${e.httpStatusCode}") // HTTP status code (e.g., 401, 429, 500)
// Helper methods for common error categories
when {
e.isRateLimitError -> println("Rate limited, retry later")
e.isAuthenticationError -> println("Invalid credentials")
e.isValidationError -> println("Bad request parameters")
e.isServerError -> println("Server error, try again")
}
}Exception Properties:
| Property | Type | Description |
|---|---|---|
message |
String? |
Raw response body from the API |
httpStatusCode |
Int? |
HTTP status code |
isRateLimitError |
Boolean |
True if HTTP 429 (rate limited) |
isAuthenticationError |
Boolean |
True if HTTP 401/403 |
isValidationError |
Boolean |
True if HTTP 400 |
isServerError |
Boolean |
True if HTTP 5xx |
| Type | Format | Examples |
|---|---|---|
| Equity | EXCHANGE:SYMBOL-EQ |
NSE:SBIN-EQ, BSE:RELIANCE-EQ |
| Index | EXCHANGE:SYMBOL-INDEX |
NSE:NIFTY50-INDEX, NSE:BANKNIFTY-INDEX |
| Futures | EXCHANGE:SYMBOLYYMONTHFUT |
NSE:SBIN25JANFUT, NSE:NIFTY25JANFUT |
| Options | EXCHANGE:SYMBOLYYMONTHDDSTRIKETYPE |
NSE:SBIN25JAN19650CE, NSE:NIFTY25JAN2322500PE |
| Commodity | MCX:SYMBOLYYMONTHFUT |
MCX:GOLD25FEBFUT |
| Currency | NSE:PAIRYYMONTHFUT |
NSE:USDINR25JANFUT |
Format Notes:
YY= 2-digit year (e.g.,25for 2025)MONTH= 3-letter month in uppercase (e.g.,JAN,FEB,MAR)DD= 2-digit day (for weekly options)STRIKE= Strike price without decimalTYPE= Option type (CEfor Call,PEfor Put)
Recommended: Use symbol builder instead of raw strings.
Kotlin:
import io.github.sonicalgo.fyers.common.Exchange.*
import io.github.sonicalgo.fyers.util.*
NSE.equity("SBIN") // "NSE:SBIN-EQ"
NSE.index("NIFTY50") // "NSE:NIFTY50-INDEX"
NSE.future("NIFTY25JANFUT") // "NSE:NIFTY25JANFUT"
NSE.option("NIFTY25JAN2322500PE") // "NSE:NIFTY25JAN2322500PE"Java:
import io.github.sonicalgo.fyers.util.Symbol;
import io.github.sonicalgo.fyers.common.Exchange;
Symbol.equity(Exchange.NSE, "SBIN"); // "NSE:SBIN-EQ"
Symbol.index(Exchange.NSE, "NIFTY50"); // "NSE:NIFTY50-INDEX"
Symbol.future(Exchange.NSE, "NIFTY25JANFUT"); // "NSE:NIFTY25JANFUT"
Symbol.option(Exchange.NSE, "NIFTY25JAN2322500PE"); // "NSE:NIFTY25JAN2322500PE"| Method | Suffix | Example Output |
|---|---|---|
equity() |
-EQ |
NSE:SBIN-EQ |
index() |
-INDEX |
NSE:NIFTY50-INDEX |
future() |
none | NSE:NIFTY25JANFUT |
option() |
none | NSE:NIFTY25JAN2322500PE |
- JDK 11 or higher
- Kotlin 1.9+ (for Kotlin projects)
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
This is an unofficial SDK and is not affiliated with, endorsed by, or supported by Fyers. Use at your own risk. Always test thoroughly in a sandbox/paper trading environment before using in production.