pub struct DhanClient { /* private fields */ }Expand description
Core HTTP client for the DhanHQ REST API v2.
Wraps reqwest::Client and injects the required authentication headers
into every request. Auth header values are cached at construction time to
avoid per-request allocation.
§Example
use dhan_rs::client::DhanClient;
let client = DhanClient::new("1000000001", "your-access-token");
// client.get::<MyResponse>("/v2/orders").await?;Implementations§
Source§impl DhanClient
impl DhanClient
Sourcepub async fn generate_access_token(
client_id: &str,
pin: &str,
totp: &str,
) -> Result<TokenResponse>
pub async fn generate_access_token( client_id: &str, pin: &str, totp: &str, ) -> Result<TokenResponse>
Generate an access token using client credentials and TOTP.
Requires TOTP to be enabled on the Dhan account.
Endpoint: POST https://auth.dhan.co/app/generateAccessToken
§Arguments
client_id— The Dhan Client ID.pin— 6-digit Dhan PIN.totp— 6-digit TOTP code from an authenticator app.
§Example
let client = DhanClient::new("1000000001", "");
let token = DhanClient::generate_access_token("1000000001", "123456", "654321").await?;
println!("Access token: {}", token.access_token);Sourcepub async fn renew_token(&mut self) -> Result<TokenResponse>
pub async fn renew_token(&mut self) -> Result<TokenResponse>
Renew the current access token for another 24 hours.
Only works for tokens generated from Dhan Web that are still active. This expires the current token and returns a new one.
Endpoint: GET /v2/RenewToken
§Note
The RenewToken endpoint uses dhanClientId as its client
identification header, unlike most other endpoints that use client-id.
This method handles the difference automatically.
Sourcepub async fn generate_consent(
client_id: &str,
app_id: &str,
app_secret: &str,
) -> Result<AppConsentResponse>
pub async fn generate_consent( client_id: &str, app_id: &str, app_secret: &str, ) -> Result<AppConsentResponse>
Step 1: Generate a consent session for API key-based login.
Validates the app_id and app_secret and creates a new session.
Endpoint: POST https://auth.dhan.co/app/generate-consent?client_id={dhanClientId}
Returns an AppConsentResponse containing a consent_app_id to be
used in the browser redirect step.
Sourcepub fn consent_login_url(consent_app_id: &str) -> String
pub fn consent_login_url(consent_app_id: &str) -> String
Step 2: Build the browser login URL for user consent.
Open this URL in a browser. After the user authenticates, they will be
redirected to the redirect URL configured for the API key, with a
tokenId query parameter appended.
use dhan_rs::DhanClient;
let url = DhanClient::consent_login_url("940b0ca1-3ff4-4476-b46e-03a3ce7dc55d");
// → "https://auth.dhan.co/login/consentApp-login?consentAppId=940b0ca1-..."Sourcepub async fn consume_consent(
token_id: &str,
app_id: &str,
app_secret: &str,
) -> Result<TokenResponse>
pub async fn consume_consent( token_id: &str, app_id: &str, app_secret: &str, ) -> Result<TokenResponse>
Step 3: Consume the consent to obtain an access token.
Uses the token_id obtained from the browser redirect after the user
logged in.
Endpoint: POST https://auth.dhan.co/app/consumeApp-consent?tokenId={tokenId}
Sourcepub async fn partner_generate_consent(
partner_id: &str,
partner_secret: &str,
) -> Result<PartnerConsentResponse>
pub async fn partner_generate_consent( partner_id: &str, partner_secret: &str, ) -> Result<PartnerConsentResponse>
Step 1 (Partner): Generate a partner consent session.
Endpoint: POST https://auth.dhan.co/partner/generate-consent
Sourcepub fn partner_consent_login_url(consent_id: &str) -> String
pub fn partner_consent_login_url(consent_id: &str) -> String
Step 2 (Partner): Build the browser login URL for partner consent.
Open this URL in a browser. After the user authenticates, they will be
redirected with a tokenId query parameter.
Sourcepub async fn partner_consume_consent(
token_id: &str,
partner_id: &str,
partner_secret: &str,
) -> Result<TokenResponse>
pub async fn partner_consume_consent( token_id: &str, partner_id: &str, partner_secret: &str, ) -> Result<TokenResponse>
Step 3 (Partner): Consume the partner consent to obtain an access token.
Endpoint: POST https://auth.dhan.co/partner/consume-consent?tokenId={tokenId}
Source§impl DhanClient
impl DhanClient
Sourcepub async fn place_conditional_trigger(
&self,
req: &ConditionalTriggerRequest,
) -> Result<ConditionalTriggerResponse>
pub async fn place_conditional_trigger( &self, req: &ConditionalTriggerRequest, ) -> Result<ConditionalTriggerResponse>
Place a new conditional trigger.
Endpoint: POST /v2/alerts/orders
Sourcepub async fn modify_conditional_trigger(
&self,
alert_id: &str,
req: &ConditionalTriggerRequest,
) -> Result<ConditionalTriggerResponse>
pub async fn modify_conditional_trigger( &self, alert_id: &str, req: &ConditionalTriggerRequest, ) -> Result<ConditionalTriggerResponse>
Modify an existing conditional trigger.
Endpoint: PUT /v2/alerts/orders/{alertId}
Sourcepub async fn delete_conditional_trigger(
&self,
alert_id: &str,
) -> Result<ConditionalTriggerResponse>
pub async fn delete_conditional_trigger( &self, alert_id: &str, ) -> Result<ConditionalTriggerResponse>
Delete a conditional trigger.
Endpoint: DELETE /v2/alerts/orders/{alertId}
Sourcepub async fn get_conditional_trigger(
&self,
alert_id: &str,
) -> Result<ConditionalTriggerDetail>
pub async fn get_conditional_trigger( &self, alert_id: &str, ) -> Result<ConditionalTriggerDetail>
Get a specific conditional trigger by its ID.
Endpoint: GET /v2/alerts/orders/{alertId}
Sourcepub async fn get_all_conditional_triggers(
&self,
) -> Result<Vec<ConditionalTriggerDetail>>
pub async fn get_all_conditional_triggers( &self, ) -> Result<Vec<ConditionalTriggerDetail>>
Get all conditional triggers.
Endpoint: GET /v2/alerts/orders
Source§impl DhanClient
impl DhanClient
Sourcepub async fn generate_tpin(&self) -> Result<()>
pub async fn generate_tpin(&self) -> Result<()>
Generate a T-PIN on the user’s registered mobile number.
Returns 202 Accepted on success.
Endpoint: GET /v2/edis/tpin
Sourcepub async fn generate_edis_form(
&self,
req: &EdisFormRequest,
) -> Result<EdisFormResponse>
pub async fn generate_edis_form( &self, req: &EdisFormRequest, ) -> Result<EdisFormResponse>
Generate an eDIS form for CDSL T-PIN entry.
Endpoint: POST /v2/edis/form
Sourcepub async fn inquire_edis(&self, isin: &str) -> Result<EdisInquiry>
pub async fn inquire_edis(&self, isin: &str) -> Result<EdisInquiry>
Inquire the eDIS status for a stock by ISIN.
Pass "ALL" as the ISIN to get status of all holdings.
Endpoint: GET /v2/edis/inquire/{isin}
Source§impl DhanClient
impl DhanClient
Sourcepub async fn create_forever_order(
&self,
req: &CreateForeverOrderRequest,
) -> Result<OrderResponse>
pub async fn create_forever_order( &self, req: &CreateForeverOrderRequest, ) -> Result<OrderResponse>
Create a new forever order.
Endpoint: POST /v2/forever/orders
Sourcepub async fn modify_forever_order(
&self,
order_id: &str,
req: &ModifyForeverOrderRequest,
) -> Result<OrderResponse>
pub async fn modify_forever_order( &self, order_id: &str, req: &ModifyForeverOrderRequest, ) -> Result<OrderResponse>
Modify an existing forever order.
Endpoint: PUT /v2/forever/orders/{order-id}
Sourcepub async fn delete_forever_order(
&self,
order_id: &str,
) -> Result<OrderResponse>
pub async fn delete_forever_order( &self, order_id: &str, ) -> Result<OrderResponse>
Delete a pending forever order.
Endpoint: DELETE /v2/forever/orders/{order-id}
Sourcepub async fn get_all_forever_orders(&self) -> Result<Vec<ForeverOrderDetail>>
pub async fn get_all_forever_orders(&self) -> Result<Vec<ForeverOrderDetail>>
Retrieve all existing forever orders.
Endpoint: GET /v2/forever/all
Source§impl DhanClient
impl DhanClient
Sourcepub async fn calculate_margin(
&self,
req: &MarginCalculatorRequest,
) -> Result<MarginCalculatorResponse>
pub async fn calculate_margin( &self, req: &MarginCalculatorRequest, ) -> Result<MarginCalculatorResponse>
Calculate margin requirement for a single order.
Endpoint: POST /v2/margincalculator
Sourcepub async fn calculate_multi_margin(
&self,
req: &MultiMarginRequest,
) -> Result<MultiMarginResponse>
pub async fn calculate_multi_margin( &self, req: &MultiMarginRequest, ) -> Result<MultiMarginResponse>
Calculate margin requirements for multiple scripts in a single request.
Endpoint: POST /v2/margincalculator/multi
Sourcepub async fn get_fund_limit(&self) -> Result<FundLimit>
pub async fn get_fund_limit(&self) -> Result<FundLimit>
Retrieve fund limits for the trading account.
Returns balance, margin utilised, collateral, and other fund details.
Endpoint: GET /v2/fundlimit
Source§impl DhanClient
impl DhanClient
Sourcepub async fn get_daily_historical(
&self,
req: &HistoricalDataRequest,
) -> Result<CandleData>
pub async fn get_daily_historical( &self, req: &HistoricalDataRequest, ) -> Result<CandleData>
Retrieve daily OHLCV candle data for an instrument.
Data is available back to the instrument’s inception date.
Endpoint: POST /v2/charts/historical
Sourcepub async fn get_intraday_historical(
&self,
req: &IntradayDataRequest,
) -> Result<CandleData>
pub async fn get_intraday_historical( &self, req: &IntradayDataRequest, ) -> Result<CandleData>
Retrieve intraday OHLCV candle data for an instrument.
Supports 1, 5, 15, 25, and 60-minute intervals. Only 90 days of data can be polled per request.
Endpoint: POST /v2/charts/intraday
Source§impl DhanClient
impl DhanClient
Sourcepub async fn set_ip(&self, req: &SetIpRequest) -> Result<IpSetResponse>
pub async fn set_ip(&self, req: &SetIpRequest) -> Result<IpSetResponse>
Set a primary or secondary static IP for the account.
Once set, the IP cannot be modified for the next 7 days.
Endpoint: POST /v2/ip/setIP
§Example
let client = DhanClient::new("1000000001", "your-access-token");
let req = SetIpRequest {
dhan_client_id: "1000000001".into(),
ip: "10.200.10.10".into(),
ip_flag: IpFlag::PRIMARY,
};
let resp = client.set_ip(&req).await?;
println!("{}: {}", resp.status, resp.message);Sourcepub async fn modify_ip(&self, req: &SetIpRequest) -> Result<IpSetResponse>
pub async fn modify_ip(&self, req: &SetIpRequest) -> Result<IpSetResponse>
Modify a previously set primary or secondary static IP.
Can only be used when IP modification is allowed (once every 7 days).
Endpoint: PUT /v2/ip/modifyIP
Sourcepub async fn get_ip(&self) -> Result<IpInfo>
pub async fn get_ip(&self) -> Result<IpInfo>
Get the currently configured static IPs and their modification dates.
Endpoint: GET /v2/ip/getIP
§Example
let client = DhanClient::new("1000000001", "your-access-token");
let info = client.get_ip().await?;
if let Some(ip) = &info.primary_ip {
println!("Primary IP: {ip}");
}Source§impl DhanClient
impl DhanClient
Sourcepub async fn get_ltp(
&self,
instruments: &MarketQuoteRequest,
) -> Result<MarketQuoteResponse<TickerData>>
pub async fn get_ltp( &self, instruments: &MarketQuoteRequest, ) -> Result<MarketQuoteResponse<TickerData>>
Retrieve LTP (Last Traded Price) for a list of instruments.
Up to 1000 instruments per request (rate limit: 1 req/sec).
Endpoint: POST /v2/marketfeed/ltp
Sourcepub async fn get_ohlc(
&self,
instruments: &MarketQuoteRequest,
) -> Result<MarketQuoteResponse<OhlcData>>
pub async fn get_ohlc( &self, instruments: &MarketQuoteRequest, ) -> Result<MarketQuoteResponse<OhlcData>>
Retrieve OHLC + LTP for a list of instruments.
Up to 1000 instruments per request (rate limit: 1 req/sec).
Endpoint: POST /v2/marketfeed/ohlc
Sourcepub async fn get_quote(
&self,
instruments: &MarketQuoteRequest,
) -> Result<MarketQuoteResponse<QuoteData>>
pub async fn get_quote( &self, instruments: &MarketQuoteRequest, ) -> Result<MarketQuoteResponse<QuoteData>>
Retrieve full market depth (quote) data for a list of instruments.
Includes depth, OHLC, OI, volume and circuit limits. Up to 1000 instruments per request (rate limit: 1 req/sec).
Endpoint: POST /v2/marketfeed/quote
Source§impl DhanClient
impl DhanClient
Sourcepub async fn get_option_chain(
&self,
req: &OptionChainRequest,
) -> Result<OptionChainResponse>
pub async fn get_option_chain( &self, req: &OptionChainRequest, ) -> Result<OptionChainResponse>
Retrieve real-time Option Chain for a given underlying and expiry.
Returns OI, Greeks, Volume, LTP, Best Bid/Ask and IV across all strikes.
Rate limit: 1 unique request every 3 seconds.
Endpoint: POST /v2/optionchain
Sourcepub async fn get_expiry_list(
&self,
req: &ExpiryListRequest,
) -> Result<ExpiryListResponse>
pub async fn get_expiry_list( &self, req: &ExpiryListRequest, ) -> Result<ExpiryListResponse>
Retrieve all active expiry dates for an underlying instrument.
Rate limit: 1 unique request every 3 seconds.
Endpoint: POST /v2/optionchain/expirylist
Source§impl DhanClient
impl DhanClient
Sourcepub async fn place_order(
&self,
req: &PlaceOrderRequest,
) -> Result<OrderResponse>
pub async fn place_order( &self, req: &PlaceOrderRequest, ) -> Result<OrderResponse>
Place a new order.
Endpoint: POST /v2/orders
Sourcepub async fn modify_order(
&self,
order_id: &str,
req: &ModifyOrderRequest,
) -> Result<OrderResponse>
pub async fn modify_order( &self, order_id: &str, req: &ModifyOrderRequest, ) -> Result<OrderResponse>
Modify a pending order.
Endpoint: PUT /v2/orders/{order-id}
Sourcepub async fn cancel_order(&self, order_id: &str) -> Result<OrderResponse>
pub async fn cancel_order(&self, order_id: &str) -> Result<OrderResponse>
Cancel a pending order.
Endpoint: DELETE /v2/orders/{order-id}
Sourcepub async fn slice_order(
&self,
req: &PlaceOrderRequest,
) -> Result<Vec<OrderResponse>>
pub async fn slice_order( &self, req: &PlaceOrderRequest, ) -> Result<Vec<OrderResponse>>
Slice an order into multiple legs (for quantities over freeze limit).
Endpoint: POST /v2/orders/slicing
Sourcepub async fn get_orders(&self) -> Result<Vec<OrderDetail>>
pub async fn get_orders(&self) -> Result<Vec<OrderDetail>>
Retrieve all orders for the day.
Endpoint: GET /v2/orders
Sourcepub async fn get_order(&self, order_id: &str) -> Result<OrderDetail>
pub async fn get_order(&self, order_id: &str) -> Result<OrderDetail>
Retrieve a specific order by its ID.
Endpoint: GET /v2/orders/{order-id}
Sourcepub async fn get_order_by_correlation_id(
&self,
correlation_id: &str,
) -> Result<OrderDetail>
pub async fn get_order_by_correlation_id( &self, correlation_id: &str, ) -> Result<OrderDetail>
Retrieve an order by its correlation ID.
Endpoint: GET /v2/orders/external/{correlation-id}
Sourcepub async fn get_trades(&self) -> Result<Vec<TradeDetail>>
pub async fn get_trades(&self) -> Result<Vec<TradeDetail>>
Retrieve all trades for the day.
Endpoint: GET /v2/trades
Sourcepub async fn get_trades_for_order(
&self,
order_id: &str,
) -> Result<Vec<TradeDetail>>
pub async fn get_trades_for_order( &self, order_id: &str, ) -> Result<Vec<TradeDetail>>
Retrieve trades for a specific order.
Endpoint: GET /v2/trades/{order-id}
Source§impl DhanClient
impl DhanClient
Sourcepub async fn get_holdings(&self) -> Result<Vec<Holding>>
pub async fn get_holdings(&self) -> Result<Vec<Holding>>
Retrieve all holdings in the demat account.
Endpoint: GET /v2/holdings
Sourcepub async fn get_positions(&self) -> Result<Vec<Position>>
pub async fn get_positions(&self) -> Result<Vec<Position>>
Retrieve all open positions for the day.
Endpoint: GET /v2/positions
Sourcepub async fn convert_position(&self, req: &ConvertPositionRequest) -> Result<()>
pub async fn convert_position(&self, req: &ConvertPositionRequest) -> Result<()>
Convert a position’s product type (e.g. intraday → delivery).
Returns 202 Accepted on success.
Endpoint: POST /v2/positions/convert
Sourcepub async fn exit_all_positions(&self) -> Result<ExitAllResponse>
pub async fn exit_all_positions(&self) -> Result<ExitAllResponse>
Exit all active positions and cancel all open orders.
Endpoint: DELETE /v2/positions
Source§impl DhanClient
impl DhanClient
Sourcepub async fn get_profile(&self) -> Result<UserProfile>
pub async fn get_profile(&self) -> Result<UserProfile>
Retrieve the user profile.
Can also be used to validate that an access token is still active.
Endpoint: GET /v2/profile
§Example
let client = DhanClient::new("1000000001", "your-access-token");
let profile = client.get_profile().await?;
println!("Token valid until: {}", profile.token_validity);Source§impl DhanClient
impl DhanClient
Sourcepub async fn get_ledger(
&self,
from_date: &str,
to_date: &str,
) -> Result<Vec<LedgerEntry>>
pub async fn get_ledger( &self, from_date: &str, to_date: &str, ) -> Result<Vec<LedgerEntry>>
Retrieve Trading Account Ledger Report for a date range.
Dates should be in YYYY-MM-DD format.
Endpoint: GET /v2/ledger?from-date={from}&to-date={to}
Sourcepub async fn get_trade_history(
&self,
from_date: &str,
to_date: &str,
page: u32,
) -> Result<Vec<TradeHistoryEntry>>
pub async fn get_trade_history( &self, from_date: &str, to_date: &str, page: u32, ) -> Result<Vec<TradeHistoryEntry>>
Retrieve historical trade data for a date range.
Dates should be in YYYY-MM-DD format. Use page = 0 as default.
The response is paginated.
Endpoint: GET /v2/trades/{from-date}/{to-date}/{page}
Source§impl DhanClient
impl DhanClient
Sourcepub async fn place_super_order(
&self,
req: &PlaceSuperOrderRequest,
) -> Result<OrderResponse>
pub async fn place_super_order( &self, req: &PlaceSuperOrderRequest, ) -> Result<OrderResponse>
Place a new super order.
Endpoint: POST /v2/super/orders
Sourcepub async fn modify_super_order(
&self,
order_id: &str,
req: &ModifySuperOrderRequest,
) -> Result<OrderResponse>
pub async fn modify_super_order( &self, order_id: &str, req: &ModifySuperOrderRequest, ) -> Result<OrderResponse>
Modify a pending super order.
Endpoint: PUT /v2/super/orders/{order-id}
Sourcepub async fn cancel_super_order(
&self,
order_id: &str,
leg: &str,
) -> Result<OrderResponse>
pub async fn cancel_super_order( &self, order_id: &str, leg: &str, ) -> Result<OrderResponse>
Cancel a super order leg.
Cancelling the ENTRY_LEG cancels all legs.
Endpoint: DELETE /v2/super/orders/{order-id}/{order-leg}
Sourcepub async fn get_super_orders(&self) -> Result<Vec<SuperOrderDetail>>
pub async fn get_super_orders(&self) -> Result<Vec<SuperOrderDetail>>
Retrieve all super orders for the day.
Endpoint: GET /v2/super/orders
Source§impl DhanClient
impl DhanClient
Sourcepub async fn manage_kill_switch(
&self,
status: &str,
) -> Result<KillSwitchResponse>
pub async fn manage_kill_switch( &self, status: &str, ) -> Result<KillSwitchResponse>
Activate or deactivate the kill switch for the current trading day.
Pass "ACTIVATE" or "DEACTIVATE" as the status parameter.
Endpoint: POST /v2/killswitch?killSwitchStatus={status}
Sourcepub async fn get_kill_switch_status(&self) -> Result<KillSwitchResponse>
pub async fn get_kill_switch_status(&self) -> Result<KillSwitchResponse>
Retrieve current kill switch status.
Endpoint: GET /v2/killswitch
Sourcepub async fn set_pnl_exit(
&self,
req: &PnlExitRequest,
) -> Result<PnlExitResponse>
pub async fn set_pnl_exit( &self, req: &PnlExitRequest, ) -> Result<PnlExitResponse>
Configure P&L-based auto-exit for the current trading day.
Endpoint: PUT /v2/pnlExit
Sourcepub async fn stop_pnl_exit(&self) -> Result<PnlExitResponse>
pub async fn stop_pnl_exit(&self) -> Result<PnlExitResponse>
Disable the active P&L-based exit configuration.
Endpoint: DELETE /v2/pnlExit
Sourcepub async fn get_pnl_exit(&self) -> Result<PnlExitConfig>
pub async fn get_pnl_exit(&self) -> Result<PnlExitConfig>
Fetch the currently active P&L-based exit configuration.
Endpoint: GET /v2/pnlExit
Source§impl DhanClient
impl DhanClient
Sourcepub fn new(
client_id: impl Into<String>,
access_token: impl Into<String>,
) -> Self
pub fn new( client_id: impl Into<String>, access_token: impl Into<String>, ) -> Self
Create a new DhanClient with the given client ID and access token.
Uses the default API base URL (https://api.dhan.co).
Sourcepub fn with_base_url(
client_id: impl Into<String>,
access_token: impl Into<String>,
base_url: impl Into<String>,
) -> Self
pub fn with_base_url( client_id: impl Into<String>, access_token: impl Into<String>, base_url: impl Into<String>, ) -> Self
Create a new DhanClient pointing at a custom base URL.
Useful for testing against a sandbox or mock server.
Sourcepub fn access_token(&self) -> &str
pub fn access_token(&self) -> &str
Returns the current access token.
Sourcepub fn set_access_token(&mut self, token: impl Into<String>)
pub fn set_access_token(&mut self, token: impl Into<String>)
Replace the access token (e.g. after renewal).
Sourcepub async fn get<R: DeserializeOwned>(&self, path: &str) -> Result<R>
pub async fn get<R: DeserializeOwned>(&self, path: &str) -> Result<R>
Perform a GET request and deserialize the JSON response.
Sourcepub async fn post<B: Serialize, R: DeserializeOwned>(
&self,
path: &str,
body: &B,
) -> Result<R>
pub async fn post<B: Serialize, R: DeserializeOwned>( &self, path: &str, body: &B, ) -> Result<R>
Perform a POST request with a JSON body and deserialize the response.
Sourcepub async fn put<B: Serialize, R: DeserializeOwned>(
&self,
path: &str,
body: &B,
) -> Result<R>
pub async fn put<B: Serialize, R: DeserializeOwned>( &self, path: &str, body: &B, ) -> Result<R>
Perform a PUT request with a JSON body and deserialize the response.
Sourcepub async fn delete<R: DeserializeOwned>(&self, path: &str) -> Result<R>
pub async fn delete<R: DeserializeOwned>(&self, path: &str) -> Result<R>
Perform a DELETE request and deserialize the JSON response.
Sourcepub async fn delete_no_content(&self, path: &str) -> Result<()>
pub async fn delete_no_content(&self, path: &str) -> Result<()>
Perform a DELETE request that returns no body (expects 202 Accepted).
Sourcepub async fn get_no_content(&self, path: &str) -> Result<()>
pub async fn get_no_content(&self, path: &str) -> Result<()>
Perform a GET request that returns no body (expects 202 Accepted).
Trait Implementations§
Source§impl Clone for DhanClient
impl Clone for DhanClient
Source§fn clone(&self) -> DhanClient
fn clone(&self) -> DhanClient
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more