snaptrade-python-sdk 11.0.121__py3-none-any.whl → 11.0.123__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,549 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ SnapTrade
5
+
6
+ Connect brokerage accounts to your app for live positions and trading
7
+
8
+ The version of the OpenAPI document: 1.0.0
9
+ Contact: api@snaptrade.com
10
+ Created by: https://snaptrade.com/
11
+ """
12
+
13
+ from dataclasses import dataclass
14
+ import typing_extensions
15
+ import urllib3
16
+ from snaptrade_client.request_before_hook import request_before_hook
17
+ import json
18
+ from urllib3._collections import HTTPHeaderDict
19
+
20
+ from snaptrade_client.api_response import AsyncGeneratorResponse
21
+ from snaptrade_client import api_client, exceptions
22
+ from datetime import date, datetime # noqa: F401
23
+ import decimal # noqa: F401
24
+ import functools # noqa: F401
25
+ import io # noqa: F401
26
+ import re # noqa: F401
27
+ import typing # noqa: F401
28
+ import typing_extensions # noqa: F401
29
+ import uuid # noqa: F401
30
+
31
+ import frozendict # noqa: F401
32
+
33
+ from snaptrade_client import schemas # noqa: F401
34
+
35
+ from snaptrade_client.model.account_order_record import AccountOrderRecord as AccountOrderRecordSchema
36
+ from snaptrade_client.model.model500_unexpected_exception_response import Model500UnexpectedExceptionResponse as Model500UnexpectedExceptionResponseSchema
37
+ from snaptrade_client.model.model404_failed_request_response import Model404FailedRequestResponse as Model404FailedRequestResponseSchema
38
+
39
+ from snaptrade_client.type.model500_unexpected_exception_response import Model500UnexpectedExceptionResponse
40
+ from snaptrade_client.type.account_order_record import AccountOrderRecord
41
+ from snaptrade_client.type.model404_failed_request_response import Model404FailedRequestResponse
42
+
43
+ # Query params
44
+ UserIdSchema = schemas.StrSchema
45
+ UserSecretSchema = schemas.StrSchema
46
+ RequestRequiredQueryParams = typing_extensions.TypedDict(
47
+ 'RequestRequiredQueryParams',
48
+ {
49
+ 'userId': typing.Union[UserIdSchema, str, ],
50
+ 'userSecret': typing.Union[UserSecretSchema, str, ],
51
+ }
52
+ )
53
+ RequestOptionalQueryParams = typing_extensions.TypedDict(
54
+ 'RequestOptionalQueryParams',
55
+ {
56
+ },
57
+ total=False
58
+ )
59
+
60
+
61
+ class RequestQueryParams(RequestRequiredQueryParams, RequestOptionalQueryParams):
62
+ pass
63
+
64
+
65
+ request_query_user_id = api_client.QueryParameter(
66
+ name="userId",
67
+ style=api_client.ParameterStyle.FORM,
68
+ schema=UserIdSchema,
69
+ required=True,
70
+ explode=True,
71
+ )
72
+ request_query_user_secret = api_client.QueryParameter(
73
+ name="userSecret",
74
+ style=api_client.ParameterStyle.FORM,
75
+ schema=UserSecretSchema,
76
+ required=True,
77
+ explode=True,
78
+ )
79
+ # Path params
80
+ AccountIdSchema = schemas.UUIDSchema
81
+ BrokerageOrderIdSchema = schemas.StrSchema
82
+ RequestRequiredPathParams = typing_extensions.TypedDict(
83
+ 'RequestRequiredPathParams',
84
+ {
85
+ 'accountId': typing.Union[AccountIdSchema, str, uuid.UUID, ],
86
+ 'brokerageOrderId': typing.Union[BrokerageOrderIdSchema, str, ],
87
+ }
88
+ )
89
+ RequestOptionalPathParams = typing_extensions.TypedDict(
90
+ 'RequestOptionalPathParams',
91
+ {
92
+ },
93
+ total=False
94
+ )
95
+
96
+
97
+ class RequestPathParams(RequestRequiredPathParams, RequestOptionalPathParams):
98
+ pass
99
+
100
+
101
+ request_path_account_id = api_client.PathParameter(
102
+ name="accountId",
103
+ style=api_client.ParameterStyle.SIMPLE,
104
+ schema=AccountIdSchema,
105
+ required=True,
106
+ )
107
+ request_path_brokerage_order_id = api_client.PathParameter(
108
+ name="brokerageOrderId",
109
+ style=api_client.ParameterStyle.SIMPLE,
110
+ schema=BrokerageOrderIdSchema,
111
+ required=True,
112
+ )
113
+ SchemaFor200ResponseBodyApplicationJson = AccountOrderRecordSchema
114
+
115
+
116
+ @dataclass
117
+ class ApiResponseFor200(api_client.ApiResponse):
118
+ body: AccountOrderRecord
119
+
120
+
121
+ @dataclass
122
+ class ApiResponseFor200Async(api_client.AsyncApiResponse):
123
+ body: AccountOrderRecord
124
+
125
+
126
+ _response_for_200 = api_client.OpenApiResponse(
127
+ response_cls=ApiResponseFor200,
128
+ response_cls_async=ApiResponseFor200Async,
129
+ content={
130
+ 'application/json': api_client.MediaType(
131
+ schema=SchemaFor200ResponseBodyApplicationJson),
132
+ },
133
+ )
134
+ SchemaFor404ResponseBodyApplicationJson = Model404FailedRequestResponseSchema
135
+
136
+
137
+ @dataclass
138
+ class ApiResponseFor404(api_client.ApiResponse):
139
+ body: Model404FailedRequestResponse
140
+
141
+
142
+ @dataclass
143
+ class ApiResponseFor404Async(api_client.AsyncApiResponse):
144
+ body: Model404FailedRequestResponse
145
+
146
+
147
+ _response_for_404 = api_client.OpenApiResponse(
148
+ response_cls=ApiResponseFor404,
149
+ response_cls_async=ApiResponseFor404Async,
150
+ content={
151
+ 'application/json': api_client.MediaType(
152
+ schema=SchemaFor404ResponseBodyApplicationJson),
153
+ },
154
+ )
155
+ SchemaFor500ResponseBodyApplicationJson = Model500UnexpectedExceptionResponseSchema
156
+
157
+
158
+ @dataclass
159
+ class ApiResponseFor500(api_client.ApiResponse):
160
+ body: Model500UnexpectedExceptionResponse
161
+
162
+
163
+ @dataclass
164
+ class ApiResponseFor500Async(api_client.AsyncApiResponse):
165
+ body: Model500UnexpectedExceptionResponse
166
+
167
+
168
+ _response_for_500 = api_client.OpenApiResponse(
169
+ response_cls=ApiResponseFor500,
170
+ response_cls_async=ApiResponseFor500Async,
171
+ content={
172
+ 'application/json': api_client.MediaType(
173
+ schema=SchemaFor500ResponseBodyApplicationJson),
174
+ },
175
+ )
176
+ _all_accept_content_types = (
177
+ 'application/json',
178
+ )
179
+
180
+
181
+ class BaseApi(api_client.Api):
182
+
183
+ def _get_user_account_order_detail_mapped_args(
184
+ self,
185
+ user_id: typing.Optional[str] = None,
186
+ user_secret: typing.Optional[str] = None,
187
+ account_id: typing.Optional[str] = None,
188
+ brokerage_order_id: typing.Optional[str] = None,
189
+ query_params: typing.Optional[dict] = {},
190
+ path_params: typing.Optional[dict] = {},
191
+ ) -> api_client.MappedArgs:
192
+ args: api_client.MappedArgs = api_client.MappedArgs()
193
+ _query_params = {}
194
+ _path_params = {}
195
+ if user_id is not None:
196
+ _query_params["userId"] = user_id
197
+ if user_secret is not None:
198
+ _query_params["userSecret"] = user_secret
199
+ if account_id is not None:
200
+ _path_params["accountId"] = account_id
201
+ if brokerage_order_id is not None:
202
+ _path_params["brokerageOrderId"] = brokerage_order_id
203
+ args.query = query_params if query_params else _query_params
204
+ args.path = path_params if path_params else _path_params
205
+ return args
206
+
207
+ async def _aget_user_account_order_detail_oapg(
208
+ self,
209
+ query_params: typing.Optional[dict] = {},
210
+ path_params: typing.Optional[dict] = {},
211
+ skip_deserialization: bool = True,
212
+ timeout: typing.Optional[typing.Union[float, typing.Tuple]] = None,
213
+ accept_content_types: typing.Tuple[str] = _all_accept_content_types,
214
+ stream: bool = False,
215
+ **kwargs,
216
+ ) -> typing.Union[
217
+ ApiResponseFor200Async,
218
+ api_client.ApiResponseWithoutDeserializationAsync,
219
+ AsyncGeneratorResponse,
220
+ ]:
221
+ """
222
+ Get account order detail
223
+ :param skip_deserialization: If true then api_response.response will be set but
224
+ api_response.body and api_response.headers will not be deserialized into schema
225
+ class instances
226
+ """
227
+ self._verify_typed_dict_inputs_oapg(RequestQueryParams, query_params)
228
+ self._verify_typed_dict_inputs_oapg(RequestPathParams, path_params)
229
+ used_path = path.value
230
+
231
+ _path_params = {}
232
+ for parameter in (
233
+ request_path_account_id,
234
+ request_path_brokerage_order_id,
235
+ ):
236
+ parameter_data = path_params.get(parameter.name, schemas.unset)
237
+ if parameter_data is schemas.unset:
238
+ continue
239
+ serialized_data = parameter.serialize(parameter_data)
240
+ _path_params.update(serialized_data)
241
+
242
+ for k, v in _path_params.items():
243
+ used_path = used_path.replace('{%s}' % k, v)
244
+
245
+ prefix_separator_iterator = None
246
+ for parameter in (
247
+ request_query_user_id,
248
+ request_query_user_secret,
249
+ ):
250
+ parameter_data = query_params.get(parameter.name, schemas.unset)
251
+ if parameter_data is schemas.unset:
252
+ continue
253
+ if prefix_separator_iterator is None:
254
+ prefix_separator_iterator = parameter.get_prefix_separator_iterator()
255
+ serialized_data = parameter.serialize(parameter_data, prefix_separator_iterator)
256
+ for serialized_value in serialized_data.values():
257
+ used_path += serialized_value
258
+
259
+ _headers = HTTPHeaderDict()
260
+ # TODO add cookie handling
261
+ if accept_content_types:
262
+ for accept_content_type in accept_content_types:
263
+ _headers.add('Accept', accept_content_type)
264
+ method = 'get'.upper()
265
+ request_before_hook(
266
+ resource_path=used_path,
267
+ method=method,
268
+ configuration=self.api_client.configuration,
269
+ path_template='/accounts/{accountId}/orders/{brokerageOrderId}',
270
+ auth_settings=_auth,
271
+ headers=_headers,
272
+ )
273
+
274
+ response = await self.api_client.async_call_api(
275
+ resource_path=used_path,
276
+ method=method,
277
+ headers=_headers,
278
+ auth_settings=_auth,
279
+ prefix_separator_iterator=prefix_separator_iterator,
280
+ timeout=timeout,
281
+ **kwargs
282
+ )
283
+
284
+ if stream:
285
+ if not 200 <= response.http_response.status <= 299:
286
+ body = (await response.http_response.content.read()).decode("utf-8")
287
+ raise exceptions.ApiStreamingException(
288
+ status=response.http_response.status,
289
+ reason=response.http_response.reason,
290
+ body=body,
291
+ )
292
+
293
+ async def stream_iterator():
294
+ """
295
+ iterates over response.http_response.content and closes connection once iteration has finished
296
+ """
297
+ async for line in response.http_response.content:
298
+ if line == b'\r\n':
299
+ continue
300
+ yield line
301
+ response.http_response.close()
302
+ await response.session.close()
303
+ return AsyncGeneratorResponse(
304
+ content=stream_iterator(),
305
+ headers=response.http_response.headers,
306
+ status=response.http_response.status,
307
+ response=response.http_response
308
+ )
309
+
310
+ response_for_status = _status_code_to_response.get(str(response.http_response.status))
311
+ if response_for_status:
312
+ api_response = await response_for_status.deserialize_async(
313
+ response,
314
+ self.api_client.configuration,
315
+ skip_deserialization=skip_deserialization
316
+ )
317
+ else:
318
+ # If response data is JSON then deserialize for SDK consumer convenience
319
+ is_json = api_client.JSONDetector._content_type_is_json(response.http_response.headers.get('Content-Type', ''))
320
+ api_response = api_client.ApiResponseWithoutDeserializationAsync(
321
+ body=await response.http_response.json() if is_json else await response.http_response.text(),
322
+ response=response.http_response,
323
+ round_trip_time=response.round_trip_time,
324
+ status=response.http_response.status,
325
+ headers=response.http_response.headers,
326
+ )
327
+
328
+ if not 200 <= api_response.status <= 299:
329
+ raise exceptions.ApiException(api_response=api_response)
330
+
331
+ # cleanup session / response
332
+ response.http_response.close()
333
+ await response.session.close()
334
+
335
+ return api_response
336
+
337
+
338
+ def _get_user_account_order_detail_oapg(
339
+ self,
340
+ query_params: typing.Optional[dict] = {},
341
+ path_params: typing.Optional[dict] = {},
342
+ skip_deserialization: bool = True,
343
+ timeout: typing.Optional[typing.Union[float, typing.Tuple]] = None,
344
+ accept_content_types: typing.Tuple[str] = _all_accept_content_types,
345
+ stream: bool = False,
346
+ ) -> typing.Union[
347
+ ApiResponseFor200,
348
+ api_client.ApiResponseWithoutDeserialization,
349
+ ]:
350
+ """
351
+ Get account order detail
352
+ :param skip_deserialization: If true then api_response.response will be set but
353
+ api_response.body and api_response.headers will not be deserialized into schema
354
+ class instances
355
+ """
356
+ self._verify_typed_dict_inputs_oapg(RequestQueryParams, query_params)
357
+ self._verify_typed_dict_inputs_oapg(RequestPathParams, path_params)
358
+ used_path = path.value
359
+
360
+ _path_params = {}
361
+ for parameter in (
362
+ request_path_account_id,
363
+ request_path_brokerage_order_id,
364
+ ):
365
+ parameter_data = path_params.get(parameter.name, schemas.unset)
366
+ if parameter_data is schemas.unset:
367
+ continue
368
+ serialized_data = parameter.serialize(parameter_data)
369
+ _path_params.update(serialized_data)
370
+
371
+ for k, v in _path_params.items():
372
+ used_path = used_path.replace('{%s}' % k, v)
373
+
374
+ prefix_separator_iterator = None
375
+ for parameter in (
376
+ request_query_user_id,
377
+ request_query_user_secret,
378
+ ):
379
+ parameter_data = query_params.get(parameter.name, schemas.unset)
380
+ if parameter_data is schemas.unset:
381
+ continue
382
+ if prefix_separator_iterator is None:
383
+ prefix_separator_iterator = parameter.get_prefix_separator_iterator()
384
+ serialized_data = parameter.serialize(parameter_data, prefix_separator_iterator)
385
+ for serialized_value in serialized_data.values():
386
+ used_path += serialized_value
387
+
388
+ _headers = HTTPHeaderDict()
389
+ # TODO add cookie handling
390
+ if accept_content_types:
391
+ for accept_content_type in accept_content_types:
392
+ _headers.add('Accept', accept_content_type)
393
+ method = 'get'.upper()
394
+ request_before_hook(
395
+ resource_path=used_path,
396
+ method=method,
397
+ configuration=self.api_client.configuration,
398
+ path_template='/accounts/{accountId}/orders/{brokerageOrderId}',
399
+ auth_settings=_auth,
400
+ headers=_headers,
401
+ )
402
+
403
+ response = self.api_client.call_api(
404
+ resource_path=used_path,
405
+ method=method,
406
+ headers=_headers,
407
+ auth_settings=_auth,
408
+ prefix_separator_iterator=prefix_separator_iterator,
409
+ timeout=timeout,
410
+ )
411
+
412
+ response_for_status = _status_code_to_response.get(str(response.http_response.status))
413
+ if response_for_status:
414
+ api_response = response_for_status.deserialize(
415
+ response,
416
+ self.api_client.configuration,
417
+ skip_deserialization=skip_deserialization
418
+ )
419
+ else:
420
+ # If response data is JSON then deserialize for SDK consumer convenience
421
+ is_json = api_client.JSONDetector._content_type_is_json(response.http_response.headers.get('Content-Type', ''))
422
+ api_response = api_client.ApiResponseWithoutDeserialization(
423
+ body=json.loads(response.http_response.data) if is_json else response.http_response.data,
424
+ response=response.http_response,
425
+ round_trip_time=response.round_trip_time,
426
+ status=response.http_response.status,
427
+ headers=response.http_response.headers,
428
+ )
429
+
430
+ if not 200 <= api_response.status <= 299:
431
+ raise exceptions.ApiException(api_response=api_response)
432
+
433
+ return api_response
434
+
435
+
436
+ class GetUserAccountOrderDetail(BaseApi):
437
+ # this class is used by api classes that refer to endpoints with operationId fn names
438
+
439
+ async def aget_user_account_order_detail(
440
+ self,
441
+ user_id: typing.Optional[str] = None,
442
+ user_secret: typing.Optional[str] = None,
443
+ account_id: typing.Optional[str] = None,
444
+ brokerage_order_id: typing.Optional[str] = None,
445
+ query_params: typing.Optional[dict] = {},
446
+ path_params: typing.Optional[dict] = {},
447
+ **kwargs,
448
+ ) -> typing.Union[
449
+ ApiResponseFor200Async,
450
+ api_client.ApiResponseWithoutDeserializationAsync,
451
+ AsyncGeneratorResponse,
452
+ ]:
453
+ args = self._get_user_account_order_detail_mapped_args(
454
+ query_params=query_params,
455
+ path_params=path_params,
456
+ user_id=user_id,
457
+ user_secret=user_secret,
458
+ account_id=account_id,
459
+ brokerage_order_id=brokerage_order_id,
460
+ )
461
+ return await self._aget_user_account_order_detail_oapg(
462
+ query_params=args.query,
463
+ path_params=args.path,
464
+ **kwargs,
465
+ )
466
+
467
+ def get_user_account_order_detail(
468
+ self,
469
+ user_id: typing.Optional[str] = None,
470
+ user_secret: typing.Optional[str] = None,
471
+ account_id: typing.Optional[str] = None,
472
+ brokerage_order_id: typing.Optional[str] = None,
473
+ query_params: typing.Optional[dict] = {},
474
+ path_params: typing.Optional[dict] = {},
475
+ ) -> typing.Union[
476
+ ApiResponseFor200,
477
+ api_client.ApiResponseWithoutDeserialization,
478
+ ]:
479
+ """ Returns the detail of a single order in the specified account. This endpoint is always realtime and does not rely on cached data. """
480
+ args = self._get_user_account_order_detail_mapped_args(
481
+ query_params=query_params,
482
+ path_params=path_params,
483
+ user_id=user_id,
484
+ user_secret=user_secret,
485
+ account_id=account_id,
486
+ brokerage_order_id=brokerage_order_id,
487
+ )
488
+ return self._get_user_account_order_detail_oapg(
489
+ query_params=args.query,
490
+ path_params=args.path,
491
+ )
492
+
493
+ class ApiForget(BaseApi):
494
+ # this class is used by api classes that refer to endpoints by path and http method names
495
+
496
+ async def aget(
497
+ self,
498
+ user_id: typing.Optional[str] = None,
499
+ user_secret: typing.Optional[str] = None,
500
+ account_id: typing.Optional[str] = None,
501
+ brokerage_order_id: typing.Optional[str] = None,
502
+ query_params: typing.Optional[dict] = {},
503
+ path_params: typing.Optional[dict] = {},
504
+ **kwargs,
505
+ ) -> typing.Union[
506
+ ApiResponseFor200Async,
507
+ api_client.ApiResponseWithoutDeserializationAsync,
508
+ AsyncGeneratorResponse,
509
+ ]:
510
+ args = self._get_user_account_order_detail_mapped_args(
511
+ query_params=query_params,
512
+ path_params=path_params,
513
+ user_id=user_id,
514
+ user_secret=user_secret,
515
+ account_id=account_id,
516
+ brokerage_order_id=brokerage_order_id,
517
+ )
518
+ return await self._aget_user_account_order_detail_oapg(
519
+ query_params=args.query,
520
+ path_params=args.path,
521
+ **kwargs,
522
+ )
523
+
524
+ def get(
525
+ self,
526
+ user_id: typing.Optional[str] = None,
527
+ user_secret: typing.Optional[str] = None,
528
+ account_id: typing.Optional[str] = None,
529
+ brokerage_order_id: typing.Optional[str] = None,
530
+ query_params: typing.Optional[dict] = {},
531
+ path_params: typing.Optional[dict] = {},
532
+ ) -> typing.Union[
533
+ ApiResponseFor200,
534
+ api_client.ApiResponseWithoutDeserialization,
535
+ ]:
536
+ """ Returns the detail of a single order in the specified account. This endpoint is always realtime and does not rely on cached data. """
537
+ args = self._get_user_account_order_detail_mapped_args(
538
+ query_params=query_params,
539
+ path_params=path_params,
540
+ user_id=user_id,
541
+ user_secret=user_secret,
542
+ account_id=account_id,
543
+ brokerage_order_id=brokerage_order_id,
544
+ )
545
+ return self._get_user_account_order_detail_oapg(
546
+ query_params=args.query,
547
+ path_params=args.path,
548
+ )
549
+
@@ -262,7 +262,7 @@ class BaseApi(api_client.Api):
262
262
  AsyncGeneratorResponse,
263
263
  ]:
264
264
  """
265
- Place equity order
265
+ Place order
266
266
  :param skip_deserialization: If true then api_response.response will be set but
267
267
  api_response.body and api_response.headers will not be deserialized into schema
268
268
  class instances
@@ -393,7 +393,7 @@ class BaseApi(api_client.Api):
393
393
  api_client.ApiResponseWithoutDeserialization,
394
394
  ]:
395
395
  """
396
- Place equity order
396
+ Place order
397
397
  :param skip_deserialization: If true then api_response.response will be set but
398
398
  api_response.body and api_response.headers will not be deserialized into schema
399
399
  class instances
@@ -249,7 +249,7 @@ class BaseApi(api_client.Api):
249
249
  AsyncGeneratorResponse,
250
250
  ]:
251
251
  """
252
- Place equity order
252
+ Place order
253
253
  :param skip_deserialization: If true then api_response.response will be set but
254
254
  api_response.body and api_response.headers will not be deserialized into schema
255
255
  class instances
@@ -380,7 +380,7 @@ class BaseApi(api_client.Api):
380
380
  api_client.ApiResponseWithoutDeserialization,
381
381
  ]:
382
382
  """
383
- Place equity order
383
+ Place order
384
384
  :param skip_deserialization: If true then api_response.response will be set but
385
385
  api_response.body and api_response.headers will not be deserialized into schema
386
386
  class instances
@@ -15,6 +15,7 @@ import typing
15
15
  from enum import Enum
16
16
  from typing_extensions import TypedDict, Literal, TYPE_CHECKING
17
17
 
18
+ from snaptrade_client.type.currency import Currency
18
19
  from snaptrade_client.type.position_symbol import PositionSymbol
19
20
 
20
21
  class RequiredPosition(TypedDict):
@@ -39,5 +40,8 @@ class OptionalPosition(TypedDict, total=False):
39
40
  # Deprecated, use the `units` field for both fractional and integer units going forward
40
41
  fractional_units: typing.Optional[typing.Union[int, float]]
41
42
 
43
+ # The 'position currency' (`price` and `average_purchase_price`). This currency can potentially be different from the 'listing currency' of the security. The 'listing currency' is what's quoted on the listing exchange, while the 'position currency' is what the brokerage uses to hold and value your position.
44
+ currency: Currency
45
+
42
46
  class Position(RequiredPosition, OptionalPosition):
43
47
  pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: snaptrade-python-sdk
3
- Version: 11.0.121
3
+ Version: 11.0.123
4
4
  Summary: Client for SnapTrade
5
5
  License: MIT
6
6
  Author: SnapTrade
@@ -30,7 +30,7 @@ Description-Content-Type: text/markdown
30
30
  Connect brokerage accounts to your app for live positions and trading
31
31
 
32
32
 
33
- [![PyPI](https://img.shields.io/badge/PyPI-v11.0.121-blue)](https://pypi.org/project/snaptrade-python-sdk/11.0.121)
33
+ [![PyPI](https://img.shields.io/badge/PyPI-v11.0.123-blue)](https://pypi.org/project/snaptrade-python-sdk/11.0.123)
34
34
  [![README.md](https://img.shields.io/badge/README-Click%20Here-green)](https://github.com/passiv/snaptrade-sdks/tree/master/sdks/python#readme)
35
35
  [![More Info](https://img.shields.io/badge/More%20Info-Click%20Here-orange)](https://snaptrade.com/)
36
36
 
@@ -49,6 +49,7 @@ Connect brokerage accounts to your app for live positions and trading
49
49
  * [`snaptrade.account_information.get_all_user_holdings`](#snaptradeaccount_informationget_all_user_holdings)
50
50
  * [`snaptrade.account_information.get_user_account_balance`](#snaptradeaccount_informationget_user_account_balance)
51
51
  * [`snaptrade.account_information.get_user_account_details`](#snaptradeaccount_informationget_user_account_details)
52
+ * [`snaptrade.account_information.get_user_account_order_detail`](#snaptradeaccount_informationget_user_account_order_detail)
52
53
  * [`snaptrade.account_information.get_user_account_orders`](#snaptradeaccount_informationget_user_account_orders)
53
54
  * [`snaptrade.account_information.get_user_account_positions`](#snaptradeaccount_informationget_user_account_positions)
54
55
  * [`snaptrade.account_information.get_user_account_recent_orders`](#snaptradeaccount_informationget_user_account_recent_orders)
@@ -111,7 +112,7 @@ Python >=3.8
111
112
  ## Installation<a id="installation"></a>
112
113
 
113
114
  ```sh
114
- pip install snaptrade-python-sdk==11.0.121
115
+ pip install snaptrade-python-sdk==11.0.123
115
116
  ```
116
117
 
117
118
  ## Getting Started<a id="getting-started"></a>
@@ -401,6 +402,46 @@ get_user_account_details_response = (
401
402
 
402
403
  ---
403
404
 
405
+ ### `snaptrade.account_information.get_user_account_order_detail`<a id="snaptradeaccount_informationget_user_account_order_detail"></a>
406
+
407
+ Returns the detail of a single order in the specified account. This endpoint is always realtime and does not rely on cached data.
408
+
409
+
410
+ #### 🛠️ Usage<a id="🛠️-usage"></a>
411
+
412
+ ```python
413
+ get_user_account_order_detail_response = (
414
+ snaptrade.account_information.get_user_account_order_detail(
415
+ user_id="snaptrade-user-123",
416
+ user_secret="adf2aa34-8219-40f7-a6b3-60156985cc61",
417
+ account_id="917c8734-8470-4a3e-a18f-57c3f2ee6631",
418
+ brokerage_order_id="66a033fa-da74-4fcf-b527-feefdec9257e",
419
+ )
420
+ )
421
+ ```
422
+
423
+ #### ⚙️ Parameters<a id="⚙️-parameters"></a>
424
+
425
+ ##### user_id: `str`<a id="user_id-str"></a>
426
+
427
+ ##### user_secret: `str`<a id="user_secret-str"></a>
428
+
429
+ ##### account_id: `str`<a id="account_id-str"></a>
430
+
431
+ ##### brokerage_order_id: `str`<a id="brokerage_order_id-str"></a>
432
+
433
+ #### 🔄 Return<a id="🔄-return"></a>
434
+
435
+ [`AccountOrderRecord`](./snaptrade_client/type/account_order_record.py)
436
+
437
+ #### 🌐 Endpoint<a id="🌐-endpoint"></a>
438
+
439
+ `/accounts/{accountId}/orders/{brokerageOrderId}` `get`
440
+
441
+ [🔙 **Back to Table of Contents**](#table-of-contents)
442
+
443
+ ---
444
+
404
445
  ### `snaptrade.account_information.get_user_account_orders`<a id="snaptradeaccount_informationget_user_account_orders"></a>
405
446
 
406
447
  Returns a list of recent orders in the specified account.