//!
//! AUTO-GENERATED CODE - DO NOT EDIT!
//!
//! IB REST API
//! Source: crates/bezant-spec/ibkr-openapi-3.1.json
//! Version: 2.29.0
//! Generated by `oas3-gen v0.25.3`
//!
//! The IB REST API reference documentation
use super::types::*;
use anyhow::Context;
use reqwest::{Client, Url};
use validator::Validate;
pub const BASE_URL: &str = "https://api.ibkr.com";
#[derive(Debug, Clone)]
pub struct IbRestApiClient {
pub client: Client,
pub base_url: Url,
}
impl Default for IbRestApiClient {
fn default() -> Self {
Self::new()
}
}
impl IbRestApiClient {
/// Create a client using the OpenAPI `servers[0]` URL.
#[must_use]
#[track_caller]
pub fn new() -> Self {
Self {
client: Client::builder().build().expect("client"),
base_url: Url::parse(BASE_URL).expect("valid base url"),
}
}
/// Create a client with a custom base URL.
pub fn with_base_url(base_url: impl AsRef<str>) -> anyhow::Result<Self> {
Ok(Self {
client: Client::builder()
.build()
.context("building reqwest client")?,
base_url: Url::parse(base_url.as_ref()).context("parsing base url")?,
})
}
/// Create a client from an existing `reqwest::Client`.
pub fn with_client(base_url: impl AsRef<str>, client: Client) -> anyhow::Result<Self> {
let url = Url::parse(base_url.as_ref()).context("parsing base url")?;
Ok(Self {
client,
base_url: url,
})
}
/// List Account Signatures And Owners
///
/// Receive a list of all applicant names on the account and for which account and entity is represented.
///
/// * Path: `GET /acesws/{accountId}/signatures-and-owners`
pub async fn get_account_owners(
&self,
request: GetAccountOwnersRequest,
) -> anyhow::Result<GetAccountOwnersResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("acesws")
.push(&request.path.account_id.to_string())
.push("signatures-and-owners");
let response = self.client.get(url).send().await?;
Ok(GetAccountOwnersRequest::parse_response(response).await?)
}
/// Trading Schedule (NEW)
///
/// Returns the trading schedule for the 6 total days surrounding the current trading day. Non-Trading days, such as holidays, will not be returned.
///
/// * Path: `GET /contract/trading-schedule`
pub async fn get_trading_schedule(
&self,
request: GetTradingScheduleRequest,
) -> anyhow::Result<GetTradingScheduleResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("contract")
.push("trading-schedule");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetTradingScheduleRequest::parse_response(response).await?)
}
/// Get Model Preset
///
/// Get the preset behavior for model rebalancing.
///
/// * Path: `POST /fa/fa-preset/get`
pub async fn get_model_presets(
&self,
request: GetModelPresetsRequest,
) -> anyhow::Result<GetModelPresetsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fa")
.push("fa-preset")
.push("get");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(GetModelPresetsRequest::parse_response(response).await?)
}
/// Set Model Preset
///
/// Set the preset behavior for models.
///
/// * Path: `POST /fa/fa-preset/save`
pub async fn set_model_presets(
&self,
request: SetModelPresetsRequest,
) -> anyhow::Result<SetModelPresetsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fa")
.push("fa-preset")
.push("save");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(SetModelPresetsRequest::parse_response(response).await?)
}
/// Get Models Accounts
///
/// Request all accounts held within a model.
///
/// * Path: `POST /fa/model/accounts-details`
pub async fn get_accounts_in_model(
&self,
request: GetAccountsInModelRequest,
) -> anyhow::Result<GetAccountsInModelResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fa")
.push("model")
.push("accounts-details");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(GetAccountsInModelRequest::parse_response(response).await?)
}
/// Invest Account Into Model
///
/// Assign an account and the amount of cash to allocate into a model.
///
/// * Path: `POST /fa/model/invest-divest`
pub async fn set_accountinvestment_in_model(
&self,
request: SetAccountinvestmentInModelRequest,
) -> anyhow::Result<SetAccountinvestmentInModelResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fa")
.push("model")
.push("invest-divest");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(SetAccountinvestmentInModelRequest::parse_response(response).await?)
}
/// Summary Of Accounts Invested In The Model
///
/// Request the list of all accounts already invested in the provided model and a summary of their investment.
///
/// * Path: `POST /fa/model/invest-divest-positions`
pub async fn get_invested_accounts_in_model(
&self,
request: GetInvestedAccountsInModelRequest,
) -> anyhow::Result<GetInvestedAccountsInModelResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fa")
.push("model")
.push("invest-divest-positions");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(GetInvestedAccountsInModelRequest::parse_response(response).await?)
}
/// Request All Models
///
/// Retrieve summaries for all models under the advisor account.
///
/// * Path: `POST /fa/model/list`
pub async fn get_allmodels(
&self,
request: GetAllmodelsRequest,
) -> anyhow::Result<GetAllmodelsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fa")
.push("model")
.push("list");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(GetAllmodelsRequest::parse_response(response).await?)
}
/// Request Model Positions
///
/// Request all positions held within the model.
///
/// * Path: `POST /fa/model/positions`
pub async fn get_all_model_positions(
&self,
request: GetAllModelPositionsRequest,
) -> anyhow::Result<GetAllModelPositionsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fa")
.push("model")
.push("positions");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(GetAllModelPositionsRequest::parse_response(response).await?)
}
/// Set Model Allocations
///
/// Create or Modify a model's target positions.
///
/// * Path: `POST /fa/model/save`
pub async fn set_model_target_positions(
&self,
request: SetModelTargetPositionsRequest,
) -> anyhow::Result<SetModelTargetPositionsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fa")
.push("model")
.push("save");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(SetModelTargetPositionsRequest::parse_response(response).await?)
}
/// Submit Transfers
///
/// Submit all pending orders to the models. This is similar to the Model page's Submit All Orders selection.
///
/// * Path: `POST /fa/model/submit-transfers`
pub async fn submit_model_orders(
&self,
request: SubmitModelOrdersRequest,
) -> anyhow::Result<SubmitModelOrdersResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fa")
.push("model")
.push("submit-transfers");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(SubmitModelOrdersRequest::parse_response(response).await?)
}
/// Request Model Summary
///
/// Request a summary for a single model.
///
/// * Path: `POST /fa/model/summary`
pub async fn get_model_summary_single(
&self,
request: GetModelSummarySingleRequest,
) -> anyhow::Result<GetModelSummarySingleResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fa")
.push("model")
.push("summary");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(GetModelSummarySingleRequest::parse_response(response).await?)
}
/// Event Contract Categories
///
/// Returns the category names, parent ids, and markets for Event Contracts.
///
/// * Path: `GET /forecast/category/tree`
pub async fn get_forecast_categories(
&self,
request: GetForecastCategoriesRequest,
) -> anyhow::Result<GetForecastCategoriesResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("forecast")
.push("category")
.push("tree");
let response = self.client.get(url).send().await?;
Ok(GetForecastCategoriesRequest::parse_response(response).await?)
}
/// Event Contract Details
///
/// Provides instrument details for the specific forecast contract.
///
/// * Path: `GET /forecast/contract/details`
pub async fn get_forecast_contract(
&self,
request: GetForecastContractRequest,
) -> anyhow::Result<GetForecastContractResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("forecast")
.push("contract")
.push("details");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetForecastContractRequest::parse_response(response).await?)
}
/// Provides All Contracts For Given Underlying Market.
///
/// Returns all high level contract details affiliated with the underlying market conid provided.
///
/// * Path: `GET /forecast/contract/market`
pub async fn get_forecast_markets(
&self,
request: GetForecastMarketsRequest,
) -> anyhow::Result<GetForecastMarketsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("forecast")
.push("contract")
.push("market");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetForecastMarketsRequest::parse_response(response).await?)
}
/// Event Contract Rules
///
/// Provides trading rules for specific event contracts.
///
/// * Path: `GET /forecast/contract/rules`
pub async fn get_forecast_rules(
&self,
request: GetForecastRulesRequest,
) -> anyhow::Result<GetForecastRulesResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("forecast")
.push("contract")
.push("rules");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetForecastRulesRequest::parse_response(response).await?)
}
/// Event Contract Schedules
///
/// Provides forecast trading schedules.
///
/// * Path: `GET /forecast/contract/schedules`
pub async fn get_forecast_schedule(
&self,
request: GetForecastScheduleRequest,
) -> anyhow::Result<GetForecastScheduleResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("forecast")
.push("contract")
.push("schedules");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetForecastScheduleRequest::parse_response(response).await?)
}
/// Get Delivery Options
///
/// Options for sending fyis to email and other devices.
///
/// * Path: `GET /fyi/deliveryoptions`
pub async fn get_fyi_delivery(
&self,
request: GetFyiDeliveryRequest,
) -> anyhow::Result<GetFyiDeliveryResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fyi")
.push("deliveryoptions");
let response = self.client.get(url).send().await?;
Ok(GetFyiDeliveryRequest::parse_response(response).await?)
}
/// Toggle Delivery To A Device
///
/// Choose whether a particular device is enabled or disabled.
///
/// * Path: `POST /fyi/deliveryoptions/device`
pub async fn modify_fyi_delivery(
&self,
request: ModifyFyiDeliveryRequest,
) -> anyhow::Result<ModifyFyiDeliveryResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fyi")
.push("deliveryoptions")
.push("device");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(ModifyFyiDeliveryRequest::parse_response(response).await?)
}
/// Toggle Email Delivery
///
/// Enable or disable your account's primary email to receive notifications.
///
/// * Path: `PUT /fyi/deliveryoptions/email`
pub async fn modify_fyi_emails(
&self,
request: ModifyFyiEmailsRequest,
) -> anyhow::Result<ModifyFyiEmailsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fyi")
.push("deliveryoptions")
.push("email");
let response = self.client.put(url).query(&request.query).send().await?;
Ok(ModifyFyiEmailsRequest::parse_response(response).await?)
}
/// Delete A Device
///
/// Delete a specific device from our saved list of notification devices.
///
/// * Path: `DELETE /fyi/deliveryoptions/{deviceId}`
pub async fn delete_fyi_device(
&self,
request: DeleteFyiDeviceRequest,
) -> anyhow::Result<DeleteFyiDeviceResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fyi")
.push("deliveryoptions")
.push(&request.path.device_id.to_string());
let response = self.client.delete(url).send().await?;
Ok(DeleteFyiDeviceRequest::parse_response(response).await?)
}
/// Get Disclaimers By FYI Type
///
/// Receive additional disclaimers based on the specified typecode.
///
/// * Path: `GET /fyi/disclaimer/{typecode}`
pub async fn get_fyi_disclaimerss(
&self,
request: GetFyiDisclaimerssRequest,
) -> anyhow::Result<GetFyiDisclaimerssResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fyi")
.push("disclaimer")
.push(&request.path.typecode.to_string());
let response = self.client.get(url).send().await?;
Ok(GetFyiDisclaimerssRequest::parse_response(response).await?)
}
/// Mark FYI Disclaimer Read
///
/// Mark a specific disclaimer message as read.
///
/// * Path: `PUT /fyi/disclaimer/{typecode}`
pub async fn read_fyi_disclaimer(
&self,
request: ReadFyiDisclaimerRequest,
) -> anyhow::Result<ModifyFyiDeliveryResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fyi")
.push("disclaimer")
.push(&request.path.typecode.to_string());
let response = self.client.put(url).send().await?;
Ok(ReadFyiDisclaimerRequest::parse_response(response).await?)
}
/// List All Notifications
///
/// Get a list of available notifications.
///
/// * Path: `GET /fyi/notifications`
pub async fn get_all_fyis(
&self,
request: GetAllFyisRequest,
) -> anyhow::Result<GetAllFyisResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fyi")
.push("notifications");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetAllFyisRequest::parse_response(response).await?)
}
/// Mark Notification Read
///
/// Mark a particular notification message as read or unread.
///
/// * Path: `PUT /fyi/notifications/{notificationID}`
pub async fn read_fyi_notification(
&self,
request: ReadFyiNotificationRequest,
) -> anyhow::Result<ReadFyiNotificationResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fyi")
.push("notifications")
.push(&request.path.notification_id.to_string());
let response = self.client.put(url).send().await?;
Ok(ReadFyiNotificationRequest::parse_response(response).await?)
}
/// Get Notification Settings
///
/// Return the current choices of subscriptions for notifications.
///
/// * Path: `GET /fyi/settings`
pub async fn get_fyi_settings(
&self,
request: GetFyiSettingsRequest,
) -> anyhow::Result<GetFyiSettingsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fyi")
.push("settings");
let response = self.client.get(url).send().await?;
Ok(GetFyiSettingsRequest::parse_response(response).await?)
}
/// Modify FYI Notifications
///
/// Enable or disable group of notifications by the specific typecode.
///
/// * Path: `POST /fyi/settings/{typecode}`
pub async fn modify_fyi_notification(
&self,
request: ModifyFyiNotificationRequest,
) -> anyhow::Result<ModifyFyiEmailsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fyi")
.push("settings")
.push(&request.path.typecode.to_string());
let response = self.client.post(url).json(&request.body).send().await?;
Ok(ModifyFyiNotificationRequest::parse_response(response).await?)
}
/// Get Number Of Unread Notifications
///
/// Returns the total number of unread notifications
///
/// * Path: `GET /fyi/unreadnumber`
pub async fn get_unread_fyis(
&self,
request: GetUnreadFyisRequest,
) -> anyhow::Result<GetUnreadFyisResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("fyi")
.push("unreadnumber");
let response = self.client.get(url).send().await?;
Ok(GetUnreadFyisRequest::parse_response(response).await?)
}
/// Retrieve Processed Application
///
/// Retrieve the application request and IBKR response data based on IBKR accountId or externalId. Only available for accounts that originate via API<br><br>**Scope**: `accounts.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/accounts`
pub async fn get_gw_api_v1_accounts(
&self,
request: GetGwApiV1AccountsRequest,
) -> anyhow::Result<GetGwApiV1AccountsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("accounts");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetGwApiV1AccountsRequest::parse_response(response).await?)
}
/// Create Account
///
/// Submit account application. This will create brokerage account for the end user.<br><br>**Scope**: `accounts.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/accounts`
pub async fn post_gw_api_v1_accounts(
&self,
request: PostGwApiV1AccountsRequest,
) -> anyhow::Result<PostGwApiV1AccountsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("accounts");
let response = self
.client
.post(url)
.body((&request.body).to_string())
.send()
.await?;
Ok(PostGwApiV1AccountsRequest::parse_response(response).await?)
}
/// Update Account
///
/// Update information for an existing accountId<br><br>**Scope**: `accounts.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `PATCH /gw/api/v1/accounts`
pub async fn patch_gw_api_v1_accounts(
&self,
request: PatchGwApiV1AccountsRequest,
) -> anyhow::Result<PostGwApiV1AccountsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("accounts");
let response = self
.client
.patch(url)
.body((&request.body).to_string())
.send()
.await?;
Ok(PatchGwApiV1AccountsRequest::parse_response(response).await?)
}
/// Submit General Agreements And Disclosures
///
/// Provides mechanism to submit Agreements and Disclosures to IBKR once a day instead of with each application. We store these documents on the servers and will use them for new application requests submitted that day.<ul><li>Documents will need to be submitted once a day (before the Applications are submitted). PDFs will be displayed and submitted as is- no changes/edits will be made to the actual PDF files.</li><li>This end-point will not process any Tax Form Documents. Tax Form document should be submitted with every application</li><li>If submitted in the morning, you only need to include the Tax Form attachment for each applicant. Otherwise, you will need to include PDFs with each application (Create Account).</li></ul><br><br>**Scope**: `accounts.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/accounts/documents`
pub async fn post_gw_api_v1_accounts_documents(
&self,
request: PostGwApiV1AccountsDocumentsRequest,
) -> anyhow::Result<PostGwApiV1AccountsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("accounts")
.push("documents");
let response = self
.client
.post(url)
.body((&request.body).to_string())
.send()
.await?;
Ok(PostGwApiV1AccountsDocumentsRequest::parse_response(response).await?)
}
/// Get Login Messages
///
/// Query all accounts associated with ‘Client ID’ that have incomplete login message<br><br>**Scope**: `accounts.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/accounts/login-messages`
pub async fn get_gw_api_v1_accounts_login_messages(
&self,
request: GetGwApiV1AccountsLoginMessagesRequest,
) -> anyhow::Result<GetGwApiV1AccountsLoginMessagesResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("accounts")
.push("login-messages");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetGwApiV1AccountsLoginMessagesRequest::parse_response(response).await?)
}
/// Get Status Of Accounts
///
/// Query status of all accounts associated with ‘Client ID'<br><br>**Scope**: `accounts.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/accounts/status`
pub async fn get_gw_api_v1_accounts_status(
&self,
request: GetGwApiV1AccountsStatusRequest,
) -> anyhow::Result<GetGwApiV1AccountsStatusResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("accounts")
.push("status");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetGwApiV1AccountsStatusRequest::parse_response(response).await?)
}
/// Get Account Information
///
/// <br>**Scope**: `accounts.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/accounts/{accountId}/details`
pub async fn get_gw_api_v1_accounts_accountid_details(
&self,
request: GetGwApiV1AccountsAccountidDetailsRequest,
) -> anyhow::Result<GetGwApiV1AccountsAccountidDetailsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("accounts")
.push(&request.path.account_id.to_string())
.push("details");
let response = self.client.get(url).send().await?;
Ok(GetGwApiV1AccountsAccountidDetailsRequest::parse_response(response).await?)
}
/// Retrieve Au10Tix URL
///
/// Generate URL address to complete real-time KYC verification using Au10Tix<br><br>**Scope**: `accounts.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/accounts/{accountId}/kyc`
pub async fn get_gw_api_v1_accounts_accountid_kyc(
&self,
request: GetGwApiV1AccountsAccountidKycRequest,
) -> anyhow::Result<GetGwApiV1AccountsAccountidKycResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("accounts")
.push(&request.path.account_id.to_string())
.push("kyc");
let response = self.client.get(url).send().await?;
Ok(GetGwApiV1AccountsAccountidKycRequest::parse_response(response).await?)
}
/// Get Login Message By Account
///
/// Query login messages assigned by accountId<br><br>**Scope**: `accounts.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/accounts/{accountId}/login-messages`
pub async fn get_gw_api_v1_accounts_accountid_login_messages(
&self,
request: GetGwApiV1AccountsAccountidLoginMessagesRequest,
) -> anyhow::Result<GetGwApiV1AccountsLoginMessagesResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("accounts")
.push(&request.path.account_id.to_string())
.push("login-messages");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetGwApiV1AccountsAccountidLoginMessagesRequest::parse_response(response).await?)
}
/// Get Status By Account
///
/// Query status of account by accountId<br><br>**Scope**: `accounts.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/accounts/{accountId}/status`
pub async fn get_gw_api_v1_accounts_accountid_status(
&self,
request: GetGwApiV1AccountsAccountidStatusRequest,
) -> anyhow::Result<GetGwApiV1AccountsAccountidStatusResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("accounts")
.push(&request.path.account_id.to_string())
.push("status");
let response = self.client.get(url).send().await?;
Ok(GetGwApiV1AccountsAccountidStatusRequest::parse_response(response).await?)
}
/// Update Status By Account
///
/// Query status of account by accountId<br><br>**Scope**: `accounts.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `PATCH /gw/api/v1/accounts/{accountId}/status`
pub async fn patch_gw_api_v1_accounts_accountid_status(
&self,
request: PatchGwApiV1AccountsAccountidStatusRequest,
) -> anyhow::Result<GetGwApiV1AccountsAccountidStatusResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("accounts")
.push(&request.path.account_id.to_string())
.push("status");
let response = self
.client
.patch(url)
.body((&request.body).to_string())
.send()
.await?;
Ok(PatchGwApiV1AccountsAccountidStatusRequest::parse_response(response).await?)
}
/// Get Registration Tasks
///
/// Query registration tasks assigned to account and pending tasks that are required for account approval<br><br>**Scope**: `accounts.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/accounts/{accountId}/tasks`
pub async fn get_gw_api_v1_accounts_accountid_tasks(
&self,
request: GetGwApiV1AccountsAccountidTasksRequest,
) -> anyhow::Result<GetGwApiV1AccountsAccountidTasksResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("accounts")
.push(&request.path.account_id.to_string())
.push("tasks");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetGwApiV1AccountsAccountidTasksRequest::parse_response(response).await?)
}
/// Assign Tasks
///
/// Task can be assigned from this api<br><br>**Scope**: `accounts.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/accounts/{accountId}/tasks`
pub async fn post_gw_api_v1_accounts_accountid_tasks(
&self,
request: PostGwApiV1AccountsAccountidTasksRequest,
) -> anyhow::Result<PostGwApiV1AccountsAccountidTasksResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("accounts")
.push(&request.path.account_id.to_string())
.push("tasks");
let response = self
.client
.post(url)
.body((&request.body).to_string())
.send()
.await?;
Ok(PostGwApiV1AccountsAccountidTasksRequest::parse_response(response).await?)
}
/// Update Tasks Status
///
/// Task status can be updated from this api<br><br>**Scope**: `accounts.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `PATCH /gw/api/v1/accounts/{accountId}/tasks`
pub async fn patch_gw_api_v1_accounts_accountid_tasks(
&self,
request: PatchGwApiV1AccountsAccountidTasksRequest,
) -> anyhow::Result<PostGwApiV1AccountsAccountidTasksResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("accounts")
.push(&request.path.account_id.to_string())
.push("tasks");
let response = self
.client
.patch(url)
.body((&request.body).to_string())
.send()
.await?;
Ok(PatchGwApiV1AccountsAccountidTasksRequest::parse_response(response).await?)
}
/// View Cash Balances
///
/// View available cash for withdrawal and account equity value by accountId<br><br>**Scope**: `balances.read`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/balances/query`
pub async fn post_gw_api_v1_balances_query(
&self,
request: PostGwApiV1BalancesQueryRequest,
) -> anyhow::Result<PostGwApiV1BalancesQueryResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("balances")
.push("query");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1BalancesQueryRequest::parse_response(response).await?)
}
/// Manage Bank Instructions
///
/// Create or delete bank instructions by accountId. Only ACH and EDDA are supported for 'Create'.<br><br>**Scope**: `bank-instructions.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/bank-instructions`
pub async fn post_gw_api_v1_bank_instructions(
&self,
request: PostGwApiV1BankInstructionsRequest,
) -> anyhow::Result<PostGwApiV1BankInstructionsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("bank-instructions");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1BankInstructionsRequest::parse_response(response).await?)
}
/// View Bank Instructions
///
/// View active bank instructions for an accountId.<br><br>**Scope**: `bank-instructions.read`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/bank-instructions/query`
pub async fn post_gw_api_v1_bank_instructions_query(
&self,
request: PostGwApiV1BankInstructionsQueryRequest,
) -> anyhow::Result<PostGwApiV1BankInstructionsQueryResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("bank-instructions")
.push("query");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1BankInstructionsQueryRequest::parse_response(response).await?)
}
/// Creates Multiple Banking Instructions(ach, Delete, Micro-amount, Predefined-destination-instruction)
///
/// <br>**Scope**: `bank-instructions.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/bank-instructions:bulk`
pub async fn post_gw_api_v1_bank_instructions_bulk(
&self,
request: PostGwApiV1BankInstructionsBulkRequest,
) -> anyhow::Result<PostGwApiV1BankInstructionsBulkResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("bank-instructions:bulk");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1BankInstructionsBulkRequest::parse_response(response).await?)
}
/// Get Status For ClientInstructionId
///
/// Retrieve status of request by clientInstructionId.<br><br>**Scope**: `instructions.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/client-instructions/{clientInstructionId}`
pub async fn get_gw_api_v1_client_instructions_clientinstructionid(
&self,
request: GetGwApiV1ClientInstructionsClientinstructionidRequest,
) -> anyhow::Result<GetGwApiV1InstructionsInstructionidResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("client-instructions")
.push(&request.path.client_instruction_id.to_string());
let response = self.client.get(url).query(&request.query).send().await?;
Ok(
GetGwApiV1ClientInstructionsClientinstructionidRequest::parse_response(response)
.await?,
)
}
/// Echo A Request With HTTPS Security Policy Back After Validation.
///
/// <br>**Scope**: `echo.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/echo/https`
pub async fn get_gw_api_v1_echo_https(
&self,
request: GetGwApiV1EchoHttpsRequest,
) -> anyhow::Result<GetGwApiV1EchoHttpsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("echo")
.push("https");
let response = self.client.get(url).send().await?;
Ok(GetGwApiV1EchoHttpsRequest::parse_response(response).await?)
}
/// Echo A Request With Signed JWT Security Policy Back After Validation.
///
/// <br>**Scope**: `echo.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/echo/signed-jwt`
pub async fn post_gw_api_v1_echo_signed_jwt(
&self,
request: PostGwApiV1EchoSignedJwtRequest,
) -> anyhow::Result<GetGwApiV1EchoHttpsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("echo")
.push("signed-jwt");
let response = self
.client
.post(url)
.body((&request.body).to_string())
.send()
.await?;
Ok(PostGwApiV1EchoSignedJwtRequest::parse_response(response).await?)
}
/// Get A List Of Participating Brokers For The Given Asset Type
///
/// Get list of brokers supported for given asset transfer type<br><br>**Scope**: `enumerations.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/enumerations/complex-asset-transfer`
pub async fn get_gw_api_v1_enumerations_complex_asset_transfer(
&self,
request: GetGwApiV1EnumerationsComplexAssetTransferRequest,
) -> anyhow::Result<GetGwApiV1EnumerationsComplexAssetTransferResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("enumerations")
.push("complex-asset-transfer");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetGwApiV1EnumerationsComplexAssetTransferRequest::parse_response(response).await?)
}
/// Get Enumerations
///
/// Used to query list of enumerations for attributes included within extPositionsTransfers, occupation, employerBusiness, financialInformation, affiliationDetails, tradingPermissions, etc.<br><br>**Scope**: `accounts.read` OR `enumerations.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/enumerations/{enumerationType}`
pub async fn get_gw_api_v1_enumerations_enumerationtype(
&self,
request: GetGwApiV1EnumerationsEnumerationtypeRequest,
) -> anyhow::Result<GetGwApiV1EnumerationsEnumerationtypeResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("enumerations")
.push(&request.path.enumeration_type.to_string());
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetGwApiV1EnumerationsEnumerationtypeRequest::parse_response(response).await?)
}
/// Transfer Positions Externally (ACATS, ATON, FOP, DWAC, Complex Asset Transfer)
///
/// Initiate request to submit external position transfer. Methods- ACATS, ATON, Basic FOP, FOP, DWAC. More information on transfer methods can be found here - https://www.interactivebrokers.com/campus/trading-lessons/cash-and-position-transfers/<br><br>**Scope**: `transfers.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/external-asset-transfers`
pub async fn post_gw_api_v1_external_asset_transfers(
&self,
request: PostGwApiV1ExternalAssetTransfersRequest,
) -> anyhow::Result<PostGwApiV1BankInstructionsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("external-asset-transfers");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1ExternalAssetTransfersRequest::parse_response(response).await?)
}
/// Creates Multiple External Asset Transfers (Fop, DWAC And Complex Asset Transfer)
///
/// <br>**Scope**: `transfers.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/external-asset-transfers:bulk`
pub async fn post_gw_api_v1_external_asset_transfers_bulk(
&self,
request: PostGwApiV1ExternalAssetTransfersBulkRequest,
) -> anyhow::Result<PostGwApiV1BankInstructionsBulkResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("external-asset-transfers:bulk");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1ExternalAssetTransfersBulkRequest::parse_response(response).await?)
}
/// Transfer Cash Externally
///
/// Initiate request to deposit or withdrawal between IBKR account and bank account. More information on transfer methods can be found here - https://www.interactivebrokers.com/campus/trading-lessons/cash-and-position-transfers<br><br>**Scope**: `transfers.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/external-cash-transfers`
pub async fn post_gw_api_v1_external_cash_transfers(
&self,
request: PostGwApiV1ExternalCashTransfersRequest,
) -> anyhow::Result<PostGwApiV1BankInstructionsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("external-cash-transfers");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1ExternalCashTransfersRequest::parse_response(response).await?)
}
/// View Cash Balances
///
/// View available cash for withdrawal with and without margin loan by accountId<br><br>**Scope**: `transfers.read`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/external-cash-transfers/query`
pub async fn post_gw_api_v1_external_cash_transfers_query(
&self,
request: PostGwApiV1ExternalCashTransfersQueryRequest,
) -> anyhow::Result<PostGwApiV1ExternalCashTransfersQueryResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("external-cash-transfers")
.push("query");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1ExternalCashTransfersQueryRequest::parse_response(response).await?)
}
/// Creates Multiple External Cash Transfers (Deposit And Withdraw Fund)
///
/// <br>**Scope**: `transfers.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/external-cash-transfers:bulk`
pub async fn post_gw_api_v1_external_cash_transfers_bulk(
&self,
request: PostGwApiV1ExternalCashTransfersBulkRequest,
) -> anyhow::Result<PostGwApiV1BankInstructionsBulkResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("external-cash-transfers:bulk");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1ExternalCashTransfersBulkRequest::parse_response(response).await?)
}
/// Get Forms
///
/// Get forms<br><br>**Scope**: `accounts.read` OR `forms.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/forms`
pub async fn get_gw_api_v1_forms(
&self,
request: GetGwApiV1FormsRequest,
) -> anyhow::Result<GetGwApiV1FormsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("forms");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetGwApiV1FormsRequest::parse_response(response).await?)
}
/// Get Required Forms
///
/// Get required forms<br><br>**Scope**: `accounts.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/forms/required-forms`
pub async fn get_gw_api_v1_forms_required_forms(
&self,
request: GetGwApiV1FormsRequiredFormsRequest,
) -> anyhow::Result<GetGwApiV1FormsRequiredFormsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("forms")
.push("required-forms");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetGwApiV1FormsRequiredFormsRequest::parse_response(response).await?)
}
/// Get Status For InstructionSetId
///
/// Retrieve status of all requests associated with instructionSetId.<br><br>**Scope**: `instructions.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/instruction-sets/{instructionSetId}`
pub async fn get_gw_api_v1_instruction_sets_instructionsetid(
&self,
request: GetGwApiV1InstructionSetsInstructionsetidRequest,
) -> anyhow::Result<GetGwApiV1InstructionSetsInstructionsetidResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("instruction-sets")
.push(&request.path.instruction_set_id.to_string());
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetGwApiV1InstructionSetsInstructionsetidRequest::parse_response(response).await?)
}
/// Cancel Request
///
/// Cancel request by instructionId.<br><br>**Scope**: `instructions.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/instructions/cancel`
pub async fn post_gw_api_v1_instructions_cancel(
&self,
request: PostGwApiV1InstructionsCancelRequest,
) -> anyhow::Result<PostGwApiV1InstructionsCancelResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("instructions")
.push("cancel");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1InstructionsCancelRequest::parse_response(response).await?)
}
/// Creates Multiple Cancel Instructions
///
/// <br>**Scope**: `instructions.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/instructions/cancel:bulk`
pub async fn post_gw_api_v1_instructions_cancel_bulk(
&self,
request: PostGwApiV1InstructionsCancelBulkRequest,
) -> anyhow::Result<PostGwApiV1BankInstructionsBulkResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("instructions")
.push("cancel:bulk");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1InstructionsCancelBulkRequest::parse_response(response).await?)
}
/// Get Transaction History
///
/// Query list of recent transactions (up to 30 days) based on accountId.<br><br>**Scope**: `instructions.read`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/instructions/query`
pub async fn post_gw_api_v1_instructions_query(
&self,
request: PostGwApiV1InstructionsQueryRequest,
) -> anyhow::Result<PostGwApiV1BankInstructionsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("instructions")
.push("query");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1InstructionsQueryRequest::parse_response(response).await?)
}
/// Get Status For InstructionId
///
/// Retrieve status of request by instructionId<br><br>**Scope**: `instructions.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/instructions/{instructionId}`
pub async fn get_gw_api_v1_instructions_instructionid(
&self,
request: GetGwApiV1InstructionsInstructionidRequest,
) -> anyhow::Result<GetGwApiV1InstructionsInstructionidResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("instructions")
.push(&request.path.instruction_id.to_string());
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetGwApiV1InstructionsInstructionidRequest::parse_response(response).await?)
}
/// Transfer Positions Internally
///
/// Transfer positions internally between two accounts with Interactive Brokers<br><br>**Scope**: `transfers.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/internal-asset-transfers`
pub async fn post_gw_api_v1_internal_asset_transfers(
&self,
request: PostGwApiV1InternalAssetTransfersRequest,
) -> anyhow::Result<PostGwApiV1BankInstructionsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("internal-asset-transfers");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1InternalAssetTransfersRequest::parse_response(response).await?)
}
/// Creates Multiple Internal Asset Transfers Between The Provided Account Id Pairs
///
/// <br>**Scope**: `transfers.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/internal-asset-transfers:bulk`
pub async fn post_gw_api_v1_internal_asset_transfers_bulk(
&self,
request: PostGwApiV1InternalAssetTransfersBulkRequest,
) -> anyhow::Result<PostGwApiV1BankInstructionsBulkResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("internal-asset-transfers:bulk");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1InternalAssetTransfersBulkRequest::parse_response(response).await?)
}
/// Transfer Cash Internally
///
/// Transfer cash internally between two accounts with Interactive Brokers.<br><br>**Scope**: `transfers.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/internal-cash-transfers`
pub async fn post_gw_api_v1_internal_cash_transfers(
&self,
request: PostGwApiV1InternalCashTransfersRequest,
) -> anyhow::Result<PostGwApiV1InstructionsCancelResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("internal-cash-transfers");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1InternalCashTransfersRequest::parse_response(response).await?)
}
/// Creates Multiple Internal Cash Transfers Between The Provided Account Id Pairs
///
/// <br>**Scope**: `transfers.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/internal-cash-transfers:bulk`
pub async fn post_gw_api_v1_internal_cash_transfers_bulk(
&self,
request: PostGwApiV1InternalCashTransfersBulkRequest,
) -> anyhow::Result<PostGwApiV1BankInstructionsBulkResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("internal-cash-transfers:bulk");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1InternalCashTransfersBulkRequest::parse_response(response).await?)
}
/// Get Participating Banks
///
/// Get list of banks which support banking connection with Interactive Brokers.<br><br>**Scope**: `enumerations.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/participating-banks`
pub async fn get_gw_api_v1_participating_banks(
&self,
request: GetGwApiV1ParticipatingBanksRequest,
) -> anyhow::Result<GetGwApiV1ParticipatingBanksResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("participating-banks");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetGwApiV1ParticipatingBanksRequest::parse_response(response).await?)
}
/// Get Requests' Details By Timeframe
///
/// Fetch Requests' Details By Timeframe<br><br>**Scope**: `accounts.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/requests`
pub async fn get_gw_api_v1_requests(
&self,
request: GetGwApiV1RequestsRequest,
) -> anyhow::Result<GetGwApiV1RequestsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("requests");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetGwApiV1RequestsRequest::parse_response(response).await?)
}
/// Update Status Of An Am Request
///
/// This api will be used to update the status of am request<br><br>**Scope**: `accounts.read`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `PATCH /gw/api/v1/requests/{requestId}/status`
pub async fn patch_gw_api_v1_requests_requestid_status(
&self,
request: PatchGwApiV1RequestsRequestidStatusRequest,
) -> anyhow::Result<PatchGwApiV1RequestsRequestidStatusResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("requests")
.push(&request.path.request_id.to_string())
.push("status");
let response = self
.client
.patch(url)
.body((&request.body).to_string())
.send()
.await?;
Ok(PatchGwApiV1RequestsRequestidStatusRequest::parse_response(response).await?)
}
/// Apply PTC CSV
///
/// Applies verified CSV changes. Requires both Bearer token (header) and signed JWT (body). CSV must be verified via /csv/v2/verify first. JWT validity: 1 minute.<br><br>**Scope**: `restrictions.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/restrictions`
pub async fn apply_csv(&self, request: ApplyCsvRequest) -> anyhow::Result<ApplyCsvResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("restrictions");
let response = self
.client
.post(url)
.headers(
http::HeaderMap::try_from(&request.header).context("building request headers")?,
)
.body((&request.body).to_string())
.send()
.await?;
Ok(ApplyCsvRequest::parse_response(response).await?)
}
/// Verify PTC CSV
///
/// Validates CSV structure, restriction names, and rule parameters without applying changes. Must be called before /csv/v2/apply with the same requestId.<br><br>**Scope**: `restrictions.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/restrictions/verify`
pub async fn verify_csv(&self, request: VerifyCsvRequest) -> anyhow::Result<ApplyCsvResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("restrictions")
.push("verify");
let response = self
.client
.post(url)
.headers(
http::HeaderMap::try_from(&request.header).context("building request headers")?,
)
.json(&request.body)
.send()
.await?;
Ok(VerifyCsvRequest::parse_response(response).await?)
}
/// Create SSO Browser Session.
///
/// <br>**Scope**: `sso-browser-sessions.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/sso-browser-sessions`
pub async fn post_gw_api_v1_sso_browser_sessions(
&self,
request: PostGwApiV1SsoBrowserSessionsRequest,
) -> anyhow::Result<PostGwApiV1SsoBrowserSessionsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("sso-browser-sessions");
let response = self
.client
.post(url)
.headers(
http::HeaderMap::try_from(&request.header).context("building request headers")?,
)
.body((&request.body).to_string())
.send()
.await?;
Ok(PostGwApiV1SsoBrowserSessionsRequest::parse_response(response).await?)
}
/// Create A New SSO Session On Behalf Of An End-user.
///
/// <br>**Scope**: `sso-sessions.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/sso-sessions`
pub async fn post_gw_api_v1_sso_sessions(
&self,
request: PostGwApiV1SsoSessionsRequest,
) -> anyhow::Result<PostGwApiV1SsoSessionsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("sso-sessions");
let response = self
.client
.post(url)
.headers(
http::HeaderMap::try_from(&request.header).context("building request headers")?,
)
.body((&request.body).to_string())
.send()
.await?;
Ok(PostGwApiV1SsoSessionsRequest::parse_response(response).await?)
}
/// Generates Statements In Supported Formats Based On Request Parameters.
///
/// <br>**Scope**: `statements.read` OR `statements.write` OR `reports.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/statements`
pub async fn post_gw_api_v1_statements(
&self,
request: PostGwApiV1StatementsRequest,
) -> anyhow::Result<PostGwApiV1StatementsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("statements");
let response = self
.client
.post(url)
.headers(
http::HeaderMap::try_from(&request.header).context("building request headers")?,
)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1StatementsRequest::parse_response(response).await?)
}
/// Fetch Available Daily, Monthly, And Annual Report Dates For An Account Id
///
/// <br>**Scope**: `statements.read` OR `reports.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/statements/available`
pub async fn get_gw_api_v1_statements_available(
&self,
request: GetGwApiV1StatementsAvailableRequest,
) -> anyhow::Result<GetGwApiV1StatementsAvailableResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("statements")
.push("available");
let response = self
.client
.get(url)
.query(&request.query)
.headers(
http::HeaderMap::try_from(&request.header).context("building request headers")?,
)
.send()
.await?;
Ok(GetGwApiV1StatementsAvailableRequest::parse_response(response).await?)
}
/// Fetch Tax Forms In Supported Formats Based On Request Parameters.
///
/// <br>**Scope**: `statements.write` OR `reports.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/tax-documents`
pub async fn post_gw_api_v1_tax_documents(
&self,
request: PostGwApiV1TaxDocumentsRequest,
) -> anyhow::Result<PostGwApiV1TaxDocumentsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("tax-documents");
let response = self
.client
.post(url)
.headers(
http::HeaderMap::try_from(&request.header).context("building request headers")?,
)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1TaxDocumentsRequest::parse_response(response).await?)
}
/// Fetch List Of Available Tax Reports/forms/documents For A Specified Account And Tax Year
///
/// <br>**Scope**: `statements.read` OR `reports.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/tax-documents/available`
pub async fn get_gw_api_v1_tax_documents_available(
&self,
request: GetGwApiV1TaxDocumentsAvailableRequest,
) -> anyhow::Result<GetGwApiV1TaxDocumentsAvailableResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("tax-documents")
.push("available");
let response = self
.client
.get(url)
.query(&request.query)
.headers(
http::HeaderMap::try_from(&request.header).context("building request headers")?,
)
.send()
.await?;
Ok(GetGwApiV1TaxDocumentsAvailableRequest::parse_response(response).await?)
}
/// Fetch Trade Confirmations In Supported Formats Based On Request Parameters.
///
/// <br>**Scope**: `statements.write` OR `reports.write`<br>**Security Policy**: `Signed JWT`
///
/// * Path: `POST /gw/api/v1/trade-confirmations`
pub async fn post_gw_api_v1_trade_confirmations(
&self,
request: PostGwApiV1TradeConfirmationsRequest,
) -> anyhow::Result<PostGwApiV1TradeConfirmationsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("trade-confirmations");
let response = self
.client
.post(url)
.headers(
http::HeaderMap::try_from(&request.header).context("building request headers")?,
)
.json(&request.body)
.send()
.await?;
Ok(PostGwApiV1TradeConfirmationsRequest::parse_response(response).await?)
}
/// Fetch List Of Available Trade Confirmation Dates, For A Specific Account Id
///
/// <br>**Scope**: `statements.read` OR `reports.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/trade-confirmations/available`
pub async fn get_gw_api_v1_trade_confirmations_available(
&self,
request: GetGwApiV1TradeConfirmationsAvailableRequest,
) -> anyhow::Result<GetGwApiV1TradeConfirmationsAvailableResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("trade-confirmations")
.push("available");
let response = self
.client
.get(url)
.query(&request.query)
.headers(
http::HeaderMap::try_from(&request.header).context("building request headers")?,
)
.send()
.await?;
Ok(GetGwApiV1TradeConfirmationsAvailableRequest::parse_response(response).await?)
}
/// Verify User Availability
///
/// Verify whether user is valid and available<br><br>**Scope**: `accounts.read` OR `validations.read`<br>**Security Policy**: `HTTPS`
///
/// * Path: `GET /gw/api/v1/validations/usernames/{username}`
pub async fn get_gw_api_v1_validations_usernames_username(
&self,
request: GetGwApiV1ValidationsUsernamesUsernameRequest,
) -> anyhow::Result<GetGwApiV1ValidationsUsernamesUsernameResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("gw")
.push("api")
.push("v1")
.push("validations")
.push("usernames")
.push(&request.path.username.to_string());
let response = self.client.get(url).send().await?;
Ok(GetGwApiV1ValidationsUsernamesUsernameRequest::parse_response(response).await?)
}
/// Switch Selected Account
///
/// Switch the active account for how you request data. Only available for financial advisors and multi-account structures.
///
/// * Path: `POST /iserver/account`
pub async fn set_active_account(
&self,
request: SetActiveAccountRequest,
) -> anyhow::Result<SetActiveAccountResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(SetActiveAccountRequest::parse_response(response).await?)
}
/// Details Of A Specific Alert
///
/// Request details of a specific alert by providing the assigned alertId Id.
///
/// * Path: `GET /iserver/account/alert/{alertId}`
pub async fn get_alert_details(
&self,
request: GetAlertDetailsRequest,
) -> anyhow::Result<GetAlertDetailsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("alert")
.push(&request.path.alert_id.to_string());
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetAlertDetailsRequest::parse_response(response).await?)
}
/// List Allocatable Subaccounts
///
/// Retrieves a list of all sub-accounts and returns their net liquidity and available equity for advisors to make decisions on what accounts should be allocated and how. This endpoint is only supported for Financial Advisors and IBroker Accounts.
///
/// * Path: `GET /iserver/account/allocation/accounts`
pub async fn get_allocatable_subaccounts(
&self,
request: GetAllocatableSubaccountsRequest,
) -> anyhow::Result<GetAllocatableSubaccountsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("allocation")
.push("accounts");
let response = self.client.get(url).send().await?;
Ok(GetAllocatableSubaccountsRequest::parse_response(response).await?)
}
/// List All Allocation Groups
///
/// Retrieves a list of all of the advisor's allocation groups. This describes the name of the allocation group, number of subaccounts within the group, and the method in use for the group. This endpoint is only supported for Financial Advisors and IBroker Accounts.
///
/// * Path: `GET /iserver/account/allocation/group`
pub async fn get_allocation_groups(
&self,
request: GetAllocationGroupsRequest,
) -> anyhow::Result<GetAllocationGroupsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("allocation")
.push("group");
let response = self.client.get(url).send().await?;
Ok(GetAllocationGroupsRequest::parse_response(response).await?)
}
/// Modify Allocation Group
///
/// Modify an existing allocation group.
///
/// * Path: `PUT /iserver/account/allocation/group`
pub async fn modify_allocation_group(
&self,
request: ModifyAllocationGroupRequest,
) -> anyhow::Result<CreateAllocationGroupResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("allocation")
.push("group");
let response = self.client.put(url).json(&request.body).send().await?;
Ok(ModifyAllocationGroupRequest::parse_response(response).await?)
}
/// Add Allocation Group
///
/// Add a new allocation group. This group can be used to trade in place of the {accountId} for the /iserver/account/{accountId}/orders endpoint.
///
/// * Path: `POST /iserver/account/allocation/group`
pub async fn create_allocation_group(
&self,
request: CreateAllocationGroupRequest,
) -> anyhow::Result<CreateAllocationGroupResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("allocation")
.push("group");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(CreateAllocationGroupRequest::parse_response(response).await?)
}
/// Delete An Allocation Group
///
/// Deletes a previously created allocation group. This endpoint is only supported for Financial Advisors and IBroker Accounts.
///
/// * Path: `POST /iserver/account/allocation/group/delete`
pub async fn delete_allocation_group(
&self,
request: DeleteAllocationGroupRequest,
) -> anyhow::Result<CreateAllocationGroupResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("allocation")
.push("group")
.push("delete");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(DeleteAllocationGroupRequest::parse_response(response).await?)
}
/// Retrieve Single Allocation Group
///
/// Retrieves the configuration of a single account group. This describes the name of the allocation group, the specific accounts contained in the group, and the allocation method in use along with any relevant quantities. This endpoint is only supported for Financial Advisors and IBroker Accounts.
///
/// * Path: `POST /iserver/account/allocation/group/single`
pub async fn get_single_allocation_group(
&self,
request: GetSingleAllocationGroupRequest,
) -> anyhow::Result<GetSingleAllocationGroupResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("allocation")
.push("group")
.push("single");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(GetSingleAllocationGroupRequest::parse_response(response).await?)
}
/// Retrieve Allocation Presets
///
/// Retrieve the preset behavior for allocation groups for specific events. This endpoint is only supported for Financial Advisors and IBroker Accounts.
///
/// * Path: `GET /iserver/account/allocation/presets`
pub async fn get_allocation_presets(
&self,
request: GetAllocationPresetsRequest,
) -> anyhow::Result<GetAllocationPresetsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("allocation")
.push("presets");
let response = self.client.get(url).send().await?;
Ok(GetAllocationPresetsRequest::parse_response(response).await?)
}
/// Set Allocation Preset
///
/// Set the preset behavior for new allocation groups for specific events.
///
/// * Path: `POST /iserver/account/allocation/presets`
pub async fn set_allocation_preset(
&self,
request: SetAllocationPresetRequest,
) -> anyhow::Result<SetAllocationPresetResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("allocation")
.push("presets");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(SetAllocationPresetRequest::parse_response(response).await?)
}
/// Details Of A Mobile Trading Alert
///
/// Retrieve information about your MTA alert. Each login user only has one mobile trading assistant (MTA) alert with it's own unique tool id that cannot be changed. MTA alerts can not be created or deleted, only modified. When modified a new order Id is generated.
///
/// * Path: `GET /iserver/account/mta`
pub async fn get_mta_details(
&self,
request: GetMtaDetailsRequest,
) -> anyhow::Result<GetMtaDetailsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("mta");
let response = self.client.get(url).send().await?;
Ok(GetMtaDetailsRequest::parse_response(response).await?)
}
/// Status Of A Single Order
///
/// Retrieve the status of a single order. Only displays orders from the current brokerage session. If orders executed on a previous day or session, queries will 503 error.
///
/// * Path: `GET /iserver/account/order/status/{orderId}`
pub async fn get_order_status(
&self,
request: GetOrderStatusRequest,
) -> anyhow::Result<GetOrderStatusResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("order")
.push("status")
.push(&request.path.order_id.to_string());
let response = self.client.get(url).send().await?;
Ok(GetOrderStatusRequest::parse_response(response).await?)
}
/// List Open Orders
///
/// Returns open orders and filled or cancelled orders submitted during the current brokerage session.
///
/// * Path: `GET /iserver/account/orders`
pub async fn get_open_orders(
&self,
request: GetOpenOrdersRequest,
) -> anyhow::Result<GetOpenOrdersResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("orders");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetOpenOrdersRequest::parse_response(response).await?)
}
/// Account Profit And Loss
///
/// Returns updated profit and loss values for the selected account. Initial request will return an empty array in the upnl object.
///
/// * Path: `GET /iserver/account/pnl/partitioned`
pub async fn get_pnl(&self, request: GetPnlRequest) -> anyhow::Result<GetPnlResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("pnl")
.push("partitioned");
let response = self.client.get(url).send().await?;
Ok(GetPnlRequest::parse_response(response).await?)
}
/// Search Dynamic Accounts
///
/// Returns a list of accounts matching a query pattern set in the request. Broker accounts configured with the DYNACCT property will not receive account information at login. Instead, they must dynamically query then set their account number. Customers without the DYNACCT property will receive a 503 error.
///
/// * Path: `GET /iserver/account/search/{searchPattern}`
pub async fn get_dynamic_accounts(
&self,
request: GetDynamicAccountsRequest,
) -> anyhow::Result<GetDynamicAccountsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("search")
.push(&request.path.search_pattern.to_string());
let response = self.client.get(url).send().await?;
Ok(GetDynamicAccountsRequest::parse_response(response).await?)
}
/// Trade History
///
/// Retrieve a list of trades, up to a maximum of 7 days prior.
///
/// * Path: `GET /iserver/account/trades`
pub async fn get_trade_history(
&self,
request: GetTradeHistoryRequest,
) -> anyhow::Result<GetTradeHistoryResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push("trades");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetTradeHistoryRequest::parse_response(response).await?)
}
/// Create Or Modify Alert
///
/// Endpoint used to create a new alert, or modify an existing alert.
///
/// * Path: `POST /iserver/account/{accountId}/alert`
pub async fn create_alert(
&self,
request: CreateAlertRequest,
) -> anyhow::Result<CreateAlertResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push(&request.path.account_id.to_string())
.push("alert");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(CreateAlertRequest::parse_response(response).await?)
}
/// Activate Or Deactivate An Alert
///
/// Activate or Deactivate existing alerts created for this account. This does not delete alerts, but disables notifications until reactivated.
///
/// * Path: `POST /iserver/account/{accountId}/alert/activate`
pub async fn activate_alert(
&self,
request: ActivateAlertRequest,
) -> anyhow::Result<ActivateAlertResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push(&request.path.account_id.to_string())
.push("alert")
.push("activate");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(ActivateAlertRequest::parse_response(response).await?)
}
/// Delete An Alert
///
/// Permanently delete an existing alert. Deleting an MTA alert will reset it to the default state.
///
/// * Path: `DELETE /iserver/account/{accountId}/alert/{alertId}`
pub async fn delete_alert(
&self,
request: DeleteAlertRequest,
) -> anyhow::Result<DeleteAlertResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push(&request.path.account_id.to_string())
.push("alert")
.push(&request.path.alert_id.to_string());
let response = self.client.delete(url).json(&request.body).send().await?;
Ok(DeleteAlertRequest::parse_response(response).await?)
}
/// List All Alerts
///
/// Retrieve a list of all alerts attached to the provided account.
///
/// * Path: `GET /iserver/account/{accountId}/alerts`
pub async fn get_all_alerts(
&self,
request: GetAllAlertsRequest,
) -> anyhow::Result<GetAllAlertsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push(&request.path.account_id.to_string())
.push("alerts");
let response = self.client.get(url).send().await?;
Ok(GetAllAlertsRequest::parse_response(response).await?)
}
/// Modify Open Order
///
/// Modify an existing, unfilled order.
///
/// * Path: `POST /iserver/account/{accountId}/order/{orderId}`
pub async fn modify_open_order(
&self,
request: ModifyOpenOrderRequest,
) -> anyhow::Result<ModifyOpenOrderResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push(&request.path.account_id.to_string())
.push("order")
.push(&request.path.order_id.to_string());
let response = self.client.post(url).json(&request.body).send().await?;
Ok(ModifyOpenOrderRequest::parse_response(response).await?)
}
/// Cancel An Open Order
///
/// Cancel an existing, unfilled order.
///
/// * Path: `DELETE /iserver/account/{accountId}/order/{orderId}`
pub async fn cancel_open_order(
&self,
request: CancelOpenOrderRequest,
) -> anyhow::Result<CancelOpenOrderResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push(&request.path.account_id.to_string())
.push("order")
.push(&request.path.order_id.to_string());
let response = self.client.delete(url).query(&request.query).send().await?;
Ok(CancelOpenOrderRequest::parse_response(response).await?)
}
/// Submit New Order
///
/// Submit a new order(s) ticket, bracket, or OCA group.
///
/// * Path: `POST /iserver/account/{accountId}/orders`
pub async fn submit_new_order(
&self,
request: SubmitNewOrderRequest,
) -> anyhow::Result<SubmitNewOrderResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push(&request.path.account_id.to_string())
.push("orders");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(SubmitNewOrderRequest::parse_response(response).await?)
}
/// New Order Preview
///
/// Preview the projected effects of an order ticket or bracket of orders, including cost and changes to margin and account equity.
///
/// * Path: `POST /iserver/account/{accountId}/orders/whatif`
pub async fn preview_margin_impact(
&self,
request: PreviewMarginImpactRequest,
) -> anyhow::Result<PreviewMarginImpactResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push(&request.path.account_id.to_string())
.push("orders")
.push("whatif");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(PreviewMarginImpactRequest::parse_response(response).await?)
}
/// Summary Of Account Values
///
/// Provides a general overview of the account details such as balance values.
///
/// * Path: `GET /iserver/account/{accountId}/summary`
pub async fn get_account_summary(
&self,
request: GetAccountSummaryRequest,
) -> anyhow::Result<GetAccountSummaryResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push(&request.path.account_id.to_string())
.push("summary");
let response = self.client.get(url).send().await?;
Ok(GetAccountSummaryRequest::parse_response(response).await?)
}
/// Summary Of Available Funds
///
/// Provides a summary specific for avilable funds giving more depth than the standard /summary endpoint.
///
/// * Path: `GET /iserver/account/{accountId}/summary/available_funds`
pub async fn get_fund_summary(
&self,
request: GetFundSummaryRequest,
) -> anyhow::Result<GetFundSummaryResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push(&request.path.account_id.to_string())
.push("summary")
.push("available_funds");
let response = self.client.get(url).send().await?;
Ok(GetFundSummaryRequest::parse_response(response).await?)
}
/// Summary Of Account Balances
///
/// Returns a summary of an account's equity and cash balances, in total and by account segment.
///
/// * Path: `GET /iserver/account/{accountId}/summary/balances`
pub async fn get_balance_summary(
&self,
request: GetBalanceSummaryRequest,
) -> anyhow::Result<GetBalanceSummaryResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push(&request.path.account_id.to_string())
.push("summary")
.push("balances");
let response = self.client.get(url).send().await?;
Ok(GetBalanceSummaryRequest::parse_response(response).await?)
}
/// Summary Of Account Margin Usage
///
/// Returns a summary of an account's margin, in total and by account segment.
///
/// * Path: `GET /iserver/account/{accountId}/summary/margins`
pub async fn get_margin_summary(
&self,
request: GetMarginSummaryRequest,
) -> anyhow::Result<GetMarginSummaryResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push(&request.path.account_id.to_string())
.push("summary")
.push("margins");
let response = self.client.get(url).send().await?;
Ok(GetMarginSummaryRequest::parse_response(response).await?)
}
/// Summary Of Account Market Value
///
/// Returns a summary of an account's market value, by currency and asset class.
///
/// * Path: `GET /iserver/account/{accountId}/summary/market_value`
pub async fn get_account_market_summary(
&self,
request: GetAccountMarketSummaryRequest,
) -> anyhow::Result<GetAccountMarketSummaryResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("account")
.push(&request.path.account_id.to_string())
.push("summary")
.push("market_value");
let response = self.client.get(url).send().await?;
Ok(GetAccountMarketSummaryRequest::parse_response(response).await?)
}
/// List All Tradable Accounts
///
/// Returns a list of accounts the user has trading access to, their respective aliases and the currently selected account. Note this endpoint must be called before modifying an order or querying open orders.
///
/// * Path: `GET /iserver/accounts`
pub async fn get_brokerage_accounts(
&self,
request: GetBrokerageAccountsRequest,
) -> anyhow::Result<GetBrokerageAccountsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("accounts");
let response = self.client.get(url).send().await?;
Ok(GetBrokerageAccountsRequest::parse_response(response).await?)
}
/// Initialize Brokerage Session
///
/// After retrieving the access token and subsequent Live Session Token, customers can initialize their brokerage session with the ssodh/init endpoint.
///
/// * Path: `POST /iserver/auth/ssodh/init`
pub async fn initialize_session(
&self,
request: InitializeSessionRequest,
) -> anyhow::Result<InitializeSessionResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("auth")
.push("ssodh")
.push("init");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(InitializeSessionRequest::parse_response(response).await?)
}
/// Brokerage Session Status
///
/// Current Authentication status to the Brokerage system. Market Data and Trading is not possible if not authenticated.
///
/// * Path: `POST /iserver/auth/status`
pub async fn get_brokerage_status(
&self,
request: GetBrokerageStatusRequest,
) -> anyhow::Result<GetBrokerageStatusResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("auth")
.push("status");
let response = self.client.post(url).body(Vec::<u8>::new()).send().await?;
Ok(GetBrokerageStatusRequest::parse_response(response).await?)
}
/// Search Contract Rules
///
/// Returns trading related rules for a specific contract and side.
///
/// * Path: `POST /iserver/contract/rules`
pub async fn get_contract_rules(
&self,
request: GetContractRulesRequest,
) -> anyhow::Result<GetContractRulesResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("contract")
.push("rules");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(GetContractRulesRequest::parse_response(response).await?)
}
/// Search Algos For An Instrument
///
/// Returns supported IB Algos for an instrument. A pre-flight request must be submitted before retrieving information.
///
/// * Path: `GET /iserver/contract/{conid}/algos`
pub async fn get_algos_by_instrument(
&self,
request: GetAlgosByInstrumentRequest,
) -> anyhow::Result<GetAlgosByInstrumentResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("contract")
.push(&request.path.conid.to_string())
.push("algos");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetAlgosByInstrumentRequest::parse_response(response).await?)
}
/// General Instrument Information
///
/// Requests full contract details for the given conid.
///
/// * Path: `GET /iserver/contract/{conid}/info`
pub async fn get_instrument_info(
&self,
request: GetInstrumentInfoRequest,
) -> anyhow::Result<GetInstrumentInfoResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("contract")
.push(&request.path.conid.to_string())
.push("info");
let response = self.client.get(url).send().await?;
Ok(GetInstrumentInfoRequest::parse_response(response).await?)
}
/// Instrument Info And Market Rules
///
/// Requests full contract details and trading rules for the given conid. A follow-up request will provide additional trading rules.
///
/// * Path: `GET /iserver/contract/{conid}/info-and-rules`
pub async fn get_info_and_rules(
&self,
request: GetInfoAndRulesRequest,
) -> anyhow::Result<GetInfoAndRulesResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("contract")
.push(&request.path.conid.to_string())
.push("info-and-rules");
let response = self.client.get(url).send().await?;
Ok(GetInfoAndRulesRequest::parse_response(response).await?)
}
/// Available Currency Pairs
///
/// Obtains available currency pairs corresponding to the given target currency.
///
/// * Path: `GET /iserver/currency/pairs`
pub async fn get_currency_pairs(
&self,
request: GetCurrencyPairsRequest,
) -> anyhow::Result<GetCurrencyPairsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("currency")
.push("pairs");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetCurrencyPairsRequest::parse_response(response).await?)
}
/// Set Active Dynamic Account
///
/// Set the active dynamic account.
///
/// * Path: `POST /iserver/dynaccount`
pub async fn set_dynamic_account(
&self,
request: SetDynamicAccountRequest,
) -> anyhow::Result<SetActiveAccountResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("dynaccount");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(SetDynamicAccountRequest::parse_response(response).await?)
}
/// Currency Exchange Rate
///
/// Obtains the exchange rates of the currency pair.
///
/// * Path: `GET /iserver/exchangerate`
pub async fn get_exchange_rates(
&self,
request: GetExchangeRatesRequest,
) -> anyhow::Result<GetExchangeRatesResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("exchangerate");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetExchangeRatesRequest::parse_response(response).await?)
}
/// Historical OHLC Bar Data
///
/// Request historical data for an instrument in the form of OHLC bars.
///
/// * Path: `GET /iserver/marketdata/history`
pub async fn get_md_history(
&self,
request: GetMdHistoryRequest,
) -> anyhow::Result<GetMdHistoryResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("marketdata")
.push("history");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetMdHistoryRequest::parse_response(response).await?)
}
/// Live Market Data Snapshot
///
/// Get Market Data for the given conid(s). A pre-flight request must be made prior to ever receiving data. For some fields, it may take more than a few moments to receive information. See response fields for a list of available fields that can be request via fields argument. The endpoint /iserver/accounts must be called prior to /iserver/marketdata/snapshot. For derivative contracts the endpoint /iserver/secdef/search must be called first.
///
/// * Path: `GET /iserver/marketdata/snapshot`
pub async fn get_md_snapshot(
&self,
request: GetMdSnapshotRequest,
) -> anyhow::Result<GetMdSnapshotResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("marketdata")
.push("snapshot");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetMdSnapshotRequest::parse_response(response).await?)
}
/// Close A Backend Data Stream
///
/// Instruct IServer to close its backend stream for the instrument when real-time snapshots are no longer needed.
///
/// * Path: `POST /iserver/marketdata/unsubscribe`
pub async fn close_md_stream(
&self,
request: CloseMdStreamRequest,
) -> anyhow::Result<CloseMdStreamResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("marketdata")
.push("unsubscribe");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(CloseMdStreamRequest::parse_response(response).await?)
}
/// Close All Backend Data Streams
///
/// Instruct IServer to close all of its open backend data streams for all instruments.
///
/// * Path: `GET /iserver/marketdata/unsubscribeall`
pub async fn close_all_md_streams(
&self,
request: CloseAllMdStreamsRequest,
) -> anyhow::Result<CloseAllMdStreamsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("marketdata")
.push("unsubscribeall");
let response = self.client.get(url).send().await?;
Ok(CloseAllMdStreamsRequest::parse_response(response).await?)
}
/// Dismiss Server Prompt
///
/// Respond to a server prompt received via ntf websocket message.
///
/// * Path: `POST /iserver/notification`
pub async fn ack_server_prompt(
&self,
request: AckServerPromptRequest,
) -> anyhow::Result<AckServerPromptResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("notification");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(AckServerPromptRequest::parse_response(response).await?)
}
/// Suppress Order Reply Messages
///
/// Suppress the specified order reply messages for the duration of the brokerage session.
///
/// * Path: `POST /iserver/questions/suppress`
pub async fn suppress_order_replies(
&self,
request: SuppressOrderRepliesRequest,
) -> anyhow::Result<SuppressOrderRepliesResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("questions")
.push("suppress");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(SuppressOrderRepliesRequest::parse_response(response).await?)
}
/// Reset Order Reply Message Suppression
///
/// Removes suppression of all order reply messages that were previously suppressed in the current brokerage session.
///
/// * Path: `POST /iserver/questions/suppress/reset`
pub async fn reset_order_suppression(
&self,
request: ResetOrderSuppressionRequest,
) -> anyhow::Result<ResetOrderSuppressionResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("questions")
.push("suppress")
.push("reset");
let response = self.client.post(url).body(Vec::<u8>::new()).send().await?;
Ok(ResetOrderSuppressionRequest::parse_response(response).await?)
}
/// Confirm Order Reply Message
///
/// Confirm an order reply message and continue with submission of order ticket.
///
/// * Path: `POST /iserver/reply/{replyId}`
pub async fn confirm_order_reply(
&self,
request: ConfirmOrderReplyRequest,
) -> anyhow::Result<ConfirmOrderReplyResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("reply")
.push(&request.path.reply_id.to_string());
let response = self.client.post(url).json(&request.body).send().await?;
Ok(ConfirmOrderReplyRequest::parse_response(response).await?)
}
/// Get Valid IServer Scanner Parameters
///
/// Returns an xml file containing all available parameters to be sent for the Iserver scanner request.
///
/// * Path: `GET /iserver/scanner/params`
pub async fn get_scanner_parameters(
&self,
request: GetScannerParametersRequest,
) -> anyhow::Result<GetScannerParametersResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("scanner")
.push("params");
let response = self.client.get(url).send().await?;
Ok(GetScannerParametersRequest::parse_response(response).await?)
}
/// Run An IServer Market Scanner
///
/// Searches for contracts according to the filters specified in /iserver/scanner/params endpoint.
///
/// * Path: `POST /iserver/scanner/run`
pub async fn get_scanner_results(
&self,
request: GetScannerResultsRequest,
) -> anyhow::Result<GetScannerResultsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("scanner")
.push("run");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(GetScannerResultsRequest::parse_response(response).await?)
}
/// Search Bond Filter Information
///
/// Request a list of filters relating to a given Bond issuerID. The issuerId is retrieved from /iserver/secdef/search and can be used in /iserver/secdef/info?issuerId={issuerId} for retrieving conIds.
///
/// * Path: `GET /iserver/secdef/bond-filters`
pub async fn get_bond_filters(
&self,
request: GetBondFiltersRequest,
) -> anyhow::Result<GetBondFiltersResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("secdef")
.push("bond-filters");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetBondFiltersRequest::parse_response(response).await?)
}
/// Instrument Attributes Detail
///
/// Returns the attributes of the instrument.
///
/// * Path: `GET /iserver/secdef/info`
pub async fn get_contract_info(
&self,
request: GetContractInfoRequest,
) -> anyhow::Result<GetContractInfoResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("secdef")
.push("info");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetContractInfoRequest::parse_response(response).await?)
}
/// Search Instruments By Symbol
///
/// Returns a list of contracts based on the search symbol provided as a query param.
///
/// * Path: `GET /iserver/secdef/search`
pub async fn get_contract_symbols(
&self,
request: GetContractSymbolsRequest,
) -> anyhow::Result<GetContractSymbolsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("secdef")
.push("search");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetContractSymbolsRequest::parse_response(response).await?)
}
/// Search Instruments By Symbol
///
/// Returns a list of contracts based on the search symbol provided as a query param.
///
/// * Path: `POST /iserver/secdef/search`
pub async fn get_contract_symbols_from_body(
&self,
request: GetContractSymbolsFromBodyRequest,
) -> anyhow::Result<GetContractSymbolsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("secdef")
.push("search");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(GetContractSymbolsFromBodyRequest::parse_response(response).await?)
}
/// Search Strikes For An Underlier
///
/// Returns lists of valid strikes for options contracts on a given underlier, for all currently trading expirations. The /iserver/secdef/search endpoint must be called prior for the underlying. Otherwise empty arrays will return for "puts" and "calls".
///
/// * Path: `GET /iserver/secdef/strikes`
pub async fn get_contract_strikes(
&self,
request: GetContractStrikesRequest,
) -> anyhow::Result<GetContractStrikesResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("secdef")
.push("strikes");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetContractStrikesRequest::parse_response(response).await?)
}
/// Return A Single Saved Watchlist
///
/// Retrieve details of a single watchlist stored in the username's settings.
///
/// * Path: `GET /iserver/watchlist`
pub async fn get_specific_watchlist(
&self,
request: GetSpecificWatchlistRequest,
) -> anyhow::Result<GetSpecificWatchlistResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("watchlist");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetSpecificWatchlistRequest::parse_response(response).await?)
}
/// Create A Watchlist
///
/// Create a named watchlist by submitting a set of conids.
///
/// * Path: `POST /iserver/watchlist`
pub async fn post_new_watchlist(
&self,
request: PostNewWatchlistRequest,
) -> anyhow::Result<PostNewWatchlistResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("watchlist");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(PostNewWatchlistRequest::parse_response(response).await?)
}
/// Delete A Saved Watchlist
///
/// Delete a specified watchlist from the username's settings.
///
/// * Path: `DELETE /iserver/watchlist`
pub async fn delete_watchlist(
&self,
request: DeleteWatchlistRequest,
) -> anyhow::Result<DeleteWatchlistResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("watchlist");
let response = self.client.delete(url).query(&request.query).send().await?;
Ok(DeleteWatchlistRequest::parse_response(response).await?)
}
/// Return All Saved Watchlists
///
/// Returns all saved watchlists stored on IB backend for the username in use in the current Web API session.
///
/// * Path: `GET /iserver/watchlists`
pub async fn get_all_watchlists(
&self,
request: GetAllWatchlistsRequest,
) -> anyhow::Result<GetAllWatchlistsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("iserver")
.push("watchlists");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetAllWatchlistsRequest::parse_response(response).await?)
}
/// Terminate Web API Session
///
/// Logs the user out of the gateway session. Any further activity requires re-authentication. Discard client-side cookies upon logout.
///
/// * Path: `POST /logout`
pub async fn logout(&self, request: LogoutRequest) -> anyhow::Result<LogoutResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("logout");
let response = self.client.post(url).body(Vec::<u8>::new()).send().await?;
Ok(LogoutRequest::parse_response(response).await?)
}
/// Generate An Access Token
///
/// Request an access token for the IB username that has granted authorization to the consumer.
///
/// * Path: `POST /oauth/access_token`
pub async fn req_access_token(
&self,
request: ReqAccessTokenRequest,
) -> anyhow::Result<ReqAccessTokenResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("oauth")
.push("access_token");
let response = self
.client
.post(url)
.headers(
http::HeaderMap::try_from(&request.header).context("building request headers")?,
)
.send()
.await?;
Ok(ReqAccessTokenRequest::parse_response(response).await?)
}
/// Generate A Live Session Token
///
/// Generate a Live Session Token shared secret and gain access to Web API.
///
/// * Path: `POST /oauth/live_session_token`
pub async fn req_live_session_token(
&self,
request: ReqLiveSessionTokenRequest,
) -> anyhow::Result<ReqLiveSessionTokenResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("oauth")
.push("live_session_token");
let response = self
.client
.post(url)
.headers(
http::HeaderMap::try_from(&request.header).context("building request headers")?,
)
.send()
.await?;
Ok(ReqLiveSessionTokenRequest::parse_response(response).await?)
}
/// Obtain A Request Token
///
/// Request a temporary token as a third party to begin the OAuth 1.0a authorization workflow.
///
/// * Path: `POST /oauth/request_token`
pub async fn req_temp_token(
&self,
request: ReqTempTokenRequest,
) -> anyhow::Result<ReqTempTokenResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("oauth")
.push("request_token");
let response = self
.client
.post(url)
.headers(
http::HeaderMap::try_from(&request.header).context("building request headers")?,
)
.send()
.await?;
Ok(ReqTempTokenRequest::parse_response(response).await?)
}
/// Create Access Token
///
/// Generate OAuth 2.0 access tokens based on request parameters.
///
/// * Path: `POST /oauth2/api/v1/token`
pub async fn generate_token(
&self,
request: GenerateTokenRequest,
) -> anyhow::Result<GenerateTokenResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("oauth2")
.push("api")
.push("v1")
.push("token");
let response = self.client.post(url).form(&request.body).send().await?;
Ok(GenerateTokenRequest::parse_response(response).await?)
}
/// Account Performance (All Time Periods)
///
/// Returns the performance (MTM) for the given accounts, if more than one account is passed, the result is consolidated.
///
/// * Path: `POST /pa/allperiods`
pub async fn get_performance_all_periods(
&self,
request: GetPerformanceAllPeriodsRequest,
) -> anyhow::Result<GetPerformanceAllPeriodsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("pa")
.push("allperiods");
let response = self
.client
.post(url)
.query(&request.query)
.json(&request.body)
.send()
.await?;
Ok(GetPerformanceAllPeriodsRequest::parse_response(response).await?)
}
/// Account Performance
///
/// Returns the performance (MTM) for the given accounts, if more than one account is passed, the result is consolidated.
///
/// * Path: `POST /pa/performance`
pub async fn get_single_performance_period(
&self,
request: GetSinglePerformancePeriodRequest,
) -> anyhow::Result<GetSinglePerformancePeriodResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("pa")
.push("performance");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(GetSinglePerformancePeriodRequest::parse_response(response).await?)
}
/// Transaction History
///
/// Transaction history for a given number of conids and accounts. Types of transactions include dividend payments, buy and sell transactions, transfers.
///
/// * Path: `POST /pa/transactions`
pub async fn get_transactions(
&self,
request: GetTransactionsRequest,
) -> anyhow::Result<GetTransactionsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("pa")
.push("transactions");
let response = self.client.post(url).json(&request.body).send().await?;
Ok(GetTransactionsRequest::parse_response(response).await?)
}
/// List All Accounts
///
/// return accounts
///
/// * Path: `GET /portfolio/accounts`
pub async fn get_all_accounts(
&self,
request: GetAllAccountsRequest,
) -> anyhow::Result<GetAllAccountsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("portfolio")
.push("accounts");
let response = self.client.get(url).send().await?;
Ok(GetAllAccountsRequest::parse_response(response).await?)
}
/// All Account Positions In An Instrument
///
/// Get positions in accounts for a given instrument (no secDef await control)
///
/// * Path: `GET /portfolio/positions/{conid}`
pub async fn get_all_accounts_for_conid(
&self,
request: GetAllAccountsForConidRequest,
) -> anyhow::Result<GetAllAccountsForConidResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("portfolio")
.push("positions")
.push(&request.path.conid.to_string());
let response = self.client.get(url).send().await?;
Ok(GetAllAccountsForConidRequest::parse_response(response).await?)
}
/// List All Subaccounts
///
/// Retrieve attributes of the subaccounts in the account structure.
///
/// * Path: `GET /portfolio/subaccounts`
pub async fn get_all_subaccounts(
&self,
request: GetAllSubaccountsRequest,
) -> anyhow::Result<GetAllSubaccountsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("portfolio")
.push("subaccounts");
let response = self.client.get(url).send().await?;
Ok(GetAllSubaccountsRequest::parse_response(response).await?)
}
/// Portfolio Subaccounts (Large Account Structures)
///
/// Used in tiered account structures (such as Financial Advisor and IBroker Accounts) to return a list of sub-accounts, paginated up to 20 accounts per page, for which the user can view position and account-related information. This endpoint must be called prior to calling other /portfolio endpoints for those sub-accounts. If you have less than 100 sub-accounts use /portfolio/subaccounts. To query a list of accounts the user can trade, see /iserver/accounts.
///
/// * Path: `GET /portfolio/subaccounts2`
pub async fn get_many_subaccounts(
&self,
request: GetManySubaccountsRequest,
) -> anyhow::Result<GetManySubaccountsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("portfolio")
.push("subaccounts2");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetManySubaccountsRequest::parse_response(response).await?)
}
/// Account Allocations
///
/// Get an account's allocations by asset class, sector group, and sector.
///
/// * Path: `GET /portfolio/{accountId}/allocation`
pub async fn get_asset_allocation(
&self,
request: GetAssetAllocationRequest,
) -> anyhow::Result<GetAssetAllocationResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("portfolio")
.push(&request.path.account_id.to_string())
.push("allocation");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetAssetAllocationRequest::parse_response(response).await?)
}
/// Combination Positions
///
/// Provides all positions held in the account acquired as a combination, including values such as ratios, size, and market value.
///
/// * Path: `GET /portfolio/{accountId}/combo/positions`
pub async fn get_combo_positions(
&self,
request: GetComboPositionsRequest,
) -> anyhow::Result<GetComboPositionsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("portfolio")
.push(&request.path.account_id.to_string())
.push("combo")
.push("positions");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetComboPositionsRequest::parse_response(response).await?)
}
/// Account Ledger
///
/// Get the given account's ledger data detailing its balances by currency.
///
/// * Path: `GET /portfolio/{accountId}/ledger`
pub async fn get_portfolio_ledger(
&self,
request: GetPortfolioLedgerRequest,
) -> anyhow::Result<GetPortfolioLedgerResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("portfolio")
.push(&request.path.account_id.to_string())
.push("ledger");
let response = self.client.get(url).send().await?;
Ok(GetPortfolioLedgerRequest::parse_response(response).await?)
}
/// Account Attributes
///
/// Get a single account's attributes and capabilities.
///
/// * Path: `GET /portfolio/{accountId}/meta`
pub async fn get_portfolio_metadata(
&self,
request: GetPortfolioMetadataRequest,
) -> anyhow::Result<GetPortfolioMetadataResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("portfolio")
.push(&request.path.account_id.to_string())
.push("meta");
let response = self.client.get(url).send().await?;
Ok(GetPortfolioMetadataRequest::parse_response(response).await?)
}
/// Refresh Position Cache
///
/// Instructs IB to discard cached portfolio positions for a given account, so that the next request for positions delivers freshly obtained data.
///
/// * Path: `POST /portfolio/{accountId}/positions/invalidate`
pub async fn invalidate_position_cache(
&self,
request: InvalidatePositionCacheRequest,
) -> anyhow::Result<InvalidatePositionCacheResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("portfolio")
.push(&request.path.account_id.to_string())
.push("positions")
.push("invalidate");
let response = self.client.post(url).body(Vec::<u8>::new()).send().await?;
Ok(InvalidatePositionCacheRequest::parse_response(response).await?)
}
/// Account Positions
///
/// Get all positions in an account.
///
/// * Path: `GET /portfolio/{accountId}/positions/{pageId}`
pub async fn get_paginated_positions(
&self,
request: GetPaginatedPositionsRequest,
) -> anyhow::Result<GetPaginatedPositionsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("portfolio")
.push(&request.path.account_id.to_string())
.push("positions")
.push(&request.path.page_id.to_string());
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetPaginatedPositionsRequest::parse_response(response).await?)
}
/// Account Portfolio Summary
///
/// Returns detailed summary of account values, by segment where appropriate.
///
/// * Path: `GET /portfolio/{accountId}/summary`
pub async fn get_portfolio_summary(
&self,
request: GetPortfolioSummaryRequest,
) -> anyhow::Result<GetPortfolioSummaryResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("portfolio")
.push(&request.path.account_id.to_string())
.push("summary");
let response = self.client.get(url).send().await?;
Ok(GetPortfolioSummaryRequest::parse_response(response).await?)
}
/// Account Position In An Instrument
///
/// Get position for a given instrument in a single account.
///
/// * Path: `GET /portfolio/{accountid}/position/{conid}`
pub async fn get_position_by_conid(
&self,
request: GetPositionByConidRequest,
) -> anyhow::Result<GetPositionByConidResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("portfolio")
.push(&request.path.accountid.to_string())
.push("position")
.push(&request.path.conid.to_string());
let response = self.client.get(url).send().await?;
Ok(GetPositionByConidRequest::parse_response(response).await?)
}
/// Account Positions (NEW)
///
/// Returns a list of positions for the given account. /portfolio/accounts or /portfolio/subaccounts must be called prior to this endpoint. This endpoint provides near-real time updates and removes caching otherwise found in the /portfolio/{accountId}/positions/{pageId} endpoint.
///
/// * Path: `GET /portfolio2/{accountId}/positions`
pub async fn get_uncached_positions(
&self,
request: GetUncachedPositionsRequest,
) -> anyhow::Result<GetUncachedPositionsResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("portfolio2")
.push(&request.path.account_id.to_string())
.push("positions");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetUncachedPositionsRequest::parse_response(response).await?)
}
/// Validate SSO Web API Session
///
/// Validates the current session for the SSO user.
///
/// * Path: `GET /sso/validate`
pub async fn get_session_validation(
&self,
request: GetSessionValidationRequest,
) -> anyhow::Result<GetSessionValidationResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("sso")
.push("validate");
let response = self.client.get(url).send().await?;
Ok(GetSessionValidationRequest::parse_response(response).await?)
}
/// Brokerage Keep-Alive Ping
///
/// If the gateway has not received any requests for several minutes an open session will automatically timeout. The tickle endpoint pings the server to prevent the session from ending. It is expected to call this endpoint approximately every 60 seconds to maintain the connection to the brokerage session.
///
/// * Path: `POST /tickle`
pub async fn get_session_token(
&self,
request: GetSessionTokenRequest,
) -> anyhow::Result<GetSessionTokenResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("tickle");
let response = self.client.post(url).body(Vec::<u8>::new()).send().await?;
Ok(GetSessionTokenRequest::parse_response(response).await?)
}
/// List All Stock Conids By Exchange
///
/// Send out a request to retrieve all contracts made available on a requested exchange. This returns all contracts that are tradable on the exchange, even those that are not using the exchange as their primary listing.
///
/// * Path: `GET /trsrv/all-conids`
pub async fn get_conids_by_exchange(
&self,
request: GetConidsByExchangeRequest,
) -> anyhow::Result<GetConidsByExchangeResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("trsrv")
.push("all-conids");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetConidsByExchangeRequest::parse_response(response).await?)
}
/// Search Futures By Symbol
///
/// Returns a list of non-expired future contracts for given symbol(s)
///
/// * Path: `GET /trsrv/futures`
pub async fn get_future_by_symbol(
&self,
request: GetFutureBySymbolRequest,
) -> anyhow::Result<GetFutureBySymbolResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("trsrv")
.push("futures");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetFutureBySymbolRequest::parse_response(response).await?)
}
/// Instrument Definition Detail
///
/// Returns a list of security definitions for the given conids.
///
/// * Path: `GET /trsrv/secdef`
pub async fn get_instrument_definition(
&self,
request: GetInstrumentDefinitionRequest,
) -> anyhow::Result<GetInstrumentDefinitionResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("trsrv")
.push("secdef");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetInstrumentDefinitionRequest::parse_response(response).await?)
}
/// Trading Schedule By Symbol
///
/// Returns the trading schedule up to a month for the requested contract.
///
/// * Path: `GET /trsrv/secdef/schedule`
pub async fn get_trading_schedule_get_trsrv_secdef_schedule(
&self,
request: GetTradingScheduleGetTrsrvSecdefScheduleRequest,
) -> anyhow::Result<GetTradingScheduleGetTrsrvSecdefScheduleResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("trsrv")
.push("secdef")
.push("schedule");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetTradingScheduleGetTrsrvSecdefScheduleRequest::parse_response(response).await?)
}
/// Search Stocks By Symbol
///
/// Returns an object contains all stock contracts for given symbol(s)
///
/// * Path: `GET /trsrv/stocks`
pub async fn get_stock_by_symbol(
&self,
request: GetStockBySymbolRequest,
) -> anyhow::Result<GetStockBySymbolResponse> {
request.validate().context("parameter validation")?;
let mut url = self.base_url.clone();
url.path_segments_mut()
.map_err(|()| anyhow::anyhow!("URL cannot be a base"))?
.push("trsrv")
.push("stocks");
let response = self.client.get(url).query(&request.query).send().await?;
Ok(GetStockBySymbolRequest::parse_response(response).await?)
}
}