Skip to main content

DhanClient

Struct DhanClient 

Source
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

Source

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);
Source

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.

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.

Source

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-..."

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}

Step 1 (Partner): Generate a partner consent session.

Endpoint: POST https://auth.dhan.co/partner/generate-consent

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.

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

Source

pub async fn place_conditional_trigger( &self, req: &ConditionalTriggerRequest, ) -> Result<ConditionalTriggerResponse>

Place a new conditional trigger.

Endpoint: POST /v2/alerts/orders

Source

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}

Source

pub async fn delete_conditional_trigger( &self, alert_id: &str, ) -> Result<ConditionalTriggerResponse>

Delete a conditional trigger.

Endpoint: DELETE /v2/alerts/orders/{alertId}

Source

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}

Source

pub async fn get_all_conditional_triggers( &self, ) -> Result<Vec<ConditionalTriggerDetail>>

Get all conditional triggers.

Endpoint: GET /v2/alerts/orders

Source§

impl DhanClient

Source

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

Source

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

Source

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

Source

pub async fn create_forever_order( &self, req: &CreateForeverOrderRequest, ) -> Result<OrderResponse>

Create a new forever order.

Endpoint: POST /v2/forever/orders

Source

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}

Source

pub async fn delete_forever_order( &self, order_id: &str, ) -> Result<OrderResponse>

Delete a pending forever order.

Endpoint: DELETE /v2/forever/orders/{order-id}

Source

pub async fn get_all_forever_orders(&self) -> Result<Vec<ForeverOrderDetail>>

Retrieve all existing forever orders.

Endpoint: GET /v2/forever/all

Source§

impl DhanClient

Source

pub async fn calculate_margin( &self, req: &MarginCalculatorRequest, ) -> Result<MarginCalculatorResponse>

Calculate margin requirement for a single order.

Endpoint: POST /v2/margincalculator

Source

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

Source

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

Source

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

Source

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

Source

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);
Source

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

Source

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

Source

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

Source

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

Source

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

Source

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

Source

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

Source

pub async fn place_order( &self, req: &PlaceOrderRequest, ) -> Result<OrderResponse>

Place a new order.

Endpoint: POST /v2/orders

Source

pub async fn modify_order( &self, order_id: &str, req: &ModifyOrderRequest, ) -> Result<OrderResponse>

Modify a pending order.

Endpoint: PUT /v2/orders/{order-id}

Source

pub async fn cancel_order(&self, order_id: &str) -> Result<OrderResponse>

Cancel a pending order.

Endpoint: DELETE /v2/orders/{order-id}

Source

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

Source

pub async fn get_orders(&self) -> Result<Vec<OrderDetail>>

Retrieve all orders for the day.

Endpoint: GET /v2/orders

Source

pub async fn get_order(&self, order_id: &str) -> Result<OrderDetail>

Retrieve a specific order by its ID.

Endpoint: GET /v2/orders/{order-id}

Source

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}

Source

pub async fn get_trades(&self) -> Result<Vec<TradeDetail>>

Retrieve all trades for the day.

Endpoint: GET /v2/trades

Source

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

Source

pub async fn get_holdings(&self) -> Result<Vec<Holding>>

Retrieve all holdings in the demat account.

Endpoint: GET /v2/holdings

Source

pub async fn get_positions(&self) -> Result<Vec<Position>>

Retrieve all open positions for the day.

Endpoint: GET /v2/positions

Source

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

Source

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

Source

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

Source

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}

Source

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

Source

pub async fn place_super_order( &self, req: &PlaceSuperOrderRequest, ) -> Result<OrderResponse>

Place a new super order.

Endpoint: POST /v2/super/orders

Source

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}

Source

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}

Source

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

Source

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}

Source

pub async fn get_kill_switch_status(&self) -> Result<KillSwitchResponse>

Retrieve current kill switch status.

Endpoint: GET /v2/killswitch

Source

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

Source

pub async fn stop_pnl_exit(&self) -> Result<PnlExitResponse>

Disable the active P&L-based exit configuration.

Endpoint: DELETE /v2/pnlExit

Source

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

Source

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).

Source

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.

Source

pub fn http(&self) -> &Client

Returns a reference to the underlying reqwest::Client.

Source

pub fn client_id(&self) -> &str

Returns the Dhan client ID.

Source

pub fn access_token(&self) -> &str

Returns the current access token.

Source

pub fn set_access_token(&mut self, token: impl Into<String>)

Replace the access token (e.g. after renewal).

Source

pub fn base_url(&self) -> &str

Returns the base URL.

Source

pub async fn get<R: DeserializeOwned>(&self, path: &str) -> Result<R>

Perform a GET request and deserialize the JSON response.

Source

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.

Source

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.

Source

pub async fn delete<R: DeserializeOwned>(&self, path: &str) -> Result<R>

Perform a DELETE request and deserialize the JSON response.

Source

pub async fn delete_no_content(&self, path: &str) -> Result<()>

Perform a DELETE request that returns no body (expects 202 Accepted).

Source

pub async fn get_no_content(&self, path: &str) -> Result<()>

Perform a GET request that returns no body (expects 202 Accepted).

Source

pub async fn post_no_content<B: Serialize>( &self, path: &str, body: &B, ) -> Result<()>

Perform a POST request that returns no body (expects 202 Accepted).

Trait Implementations§

Source§

impl Clone for DhanClient

Source§

fn clone(&self) -> DhanClient

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for DhanClient

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more