fyers
¶
Classes:
| Name | Description |
|---|---|
FyersAPIException |
Raised for Fyers broker API errors. |
FyersBlockedError |
Fyers, or Cloudflare in front of it, refused a request with HTTP 429: a rate limit or a ban on this address. |
FyersAPI |
Fyers API class |
FyersAPIException
¶
Bases: BrokerAPIException
Raised for Fyers broker API errors.
Example programs
"""Catches the `FyersAPIException` that `FyersAPI` raises when Fyers refuses the access token.
When Fyers answers with an HTTP error, `FyersAPI`'s `_request` raises `FyersAPIException` instead of returning an answer. Fyers puts its own negative error number in `code` and the explanation in `message`, and `_request` copies both into the exception.
The real constructor reads the broker's settings from MongoDB, probes `GET /api/v3/profile`, and logs in to Fyers with a five step exchange of an OTP, a TOTP and a PIN when the stored token no longer works. This program must never log in, so a small subclass, `FyersAPIWithoutLogin`, skips that constructor and is handed the settings and a stand-in for Redis that already holds the stored login. `requests.request` is replaced, only while each request is sent, by a stand-in server that records the request and answers with a recorded-looking Fyers response, so nothing reaches the network. Here the stand-in server answers with the HTTP 401 Fyers sends for a token it no longer accepts.
Notice that `code` holds Fyers's own error code rather than the HTTP status, so a caller can tell an expired token from other refusals.
Run it from the project root:
python examples/stock_brokers/api/fyers/FyersAPIException/example_1_catching_a_refused_token.py
"""
import json
import logging
import unittest.mock
import requests
from stock_brokers.api.fyers import (
FyersAPI,
FyersAPIException,
)
STORED_LOGIN = {
'broker_name': 'fyers',
'access_token': 'morning-token',
'last_login': '2026-09-30 07:00:05',
}
REFUSAL = {
's': 'error',
'code': -16,
'message': 'Could not authenticate the user',
}
class SharedLoginCache:
"""A dictionary-backed stand-in for Redis, holding the `last_login` hash that every process reads its token from.
Attributes:
hashes (dict): Each hash name mapped to a dictionary of its fields.
"""
def __init__(self):
"""Starts with nothing stored.
Returns:
None: This method returns nothing.
"""
self.hashes = {}
def hget(self, name, key):
"""Reads one field of a hash.
Args:
name (str): The hash name.
key (str): The field name.
Returns:
str | None: The stored value, or None when there is none.
"""
fields = self.hashes.get(name, {})
return fields.get(key)
def hset(self, name, key, value):
"""Writes one field of a hash, as a login does.
Args:
name (str): The hash name.
key (str): The field name.
value (str): The value to store.
Returns:
int: Always 1, the number of fields Redis reports written.
"""
if name not in self.hashes:
self.hashes[name] = {}
self.hashes[name][key] = value
return 1
class RecordedBrokerServer:
"""A stand-in for `requests.request` that answers every call with one recorded Fyers response and remembers what was sent.
Attributes:
status_code (int): The HTTP status every answer carries.
content_type (str): The Content-Type header every answer carries.
body (str): The body every answer carries.
calls (list): One dictionary per request, holding its method, URL, headers, body and certificate setting.
"""
def __init__(self, status_code, content_type, body):
"""Holds the answer to give.
Args:
status_code (int): The HTTP status every answer carries.
content_type (str): The Content-Type header every answer carries.
body (str): The body every answer carries.
Returns:
None: This method returns nothing.
"""
self.status_code = status_code
self.content_type = content_type
self.body = body
self.calls = []
def request(self, method, url, **options):
"""Records one request and answers it, in place of `requests.request`.
Args:
method (str): The HTTP method.
url (str): The URL requested.
**options (Any): The remaining `requests.request` arguments, such as `headers` and `data`.
Returns:
requests.Response: The recorded answer.
"""
self.calls.append({
'method': method,
'url': url,
'headers': options.get('headers'),
'data': options.get('data'),
'verify': options.get('verify'),
})
response = requests.Response()
response.status_code = self.status_code
response.headers['Content-Type'] = self.content_type
response._content = self.body.encode('utf-8')
response.url = url
return response
class FyersAPIWithoutLogin(FyersAPI):
"""A `FyersAPI` that is handed its settings and cache instead of loading them and logging in.
The real constructor reads the `fyers` settings document from MongoDB and then logs in to Fyers if the stored token no longer works. This subclass sets the same attributes from what it is given and does nothing else, so every request it makes still runs `FyersAPI`'s own `_request`.
"""
def __init__(self, cache, settings, stored_login):
"""Sets the attributes the real constructor would have loaded.
MongoDB is left out because the stored login is handed in here and is already in the cache, which is the first place `_current_login` looks.
Args:
cache (SharedLoginCache): The stand-in for Redis, already holding the stored login.
settings (dict): The broker's settings document.
stored_login (dict): The broker's `last_login` document, as the real constructor reads it from MongoDB.
Returns:
None: This method returns nothing.
"""
self._broker_name = 'fyers'
self._cache = cache
self._mongo_db = None
self._logger = logging.getLogger('fyers')
self._settings = settings
self._last_login = stored_login
class CatchingARefusedTokenExample:
"""Sends a request that Fyers refuses and prints the exception it raises.
Attributes:
server (RecordedBrokerServer): The stand-in for Fyers's API, answering with a refusal.
api (FyersAPIWithoutLogin): The API object being shown.
"""
def __init__(self):
"""Stores an expired login and builds the API object and the stand-in server.
Returns:
None: This method returns nothing.
"""
cache = SharedLoginCache()
cache.hset('last_login', 'fyers', json.dumps(STORED_LOGIN))
settings = {
'app_id': 'XB1234ABCD-100',
}
self.server = RecordedBrokerServer(401, 'application/json', json.dumps(REFUSAL))
self.api = FyersAPIWithoutLogin(cache, settings, STORED_LOGIN)
def run(self):
"""Sends the request, catches the exception and prints its fields.
Returns:
None: This method returns nothing.
"""
print(f'Fyers answers HTTP {self.server.status_code} with: {self.server.body}')
with unittest.mock.patch('requests.request', self.server.request):
try:
self.api.get(url='https://api-t1.fyers.in/api/v3/profile')
except FyersAPIException as error:
print(f'Caught: {type(error).__name__}')
print(f'code: {error.code}')
print(f'message: {error.message}')
if __name__ == '__main__':
CatchingARefusedTokenExample().run()
It prints:
"""Catches a gateway error from Fyers through the base class that every broker's exception shares.
A load balancer in front of Fyers's API sometimes answers with an HTML page instead of JSON, for example a 502 Bad Gateway while the service behind it restarts. `FyersAPI`'s `_request` cannot read an error code from such a page, so it raises `FyersAPIException` with the HTTP status as `code` and the page's text as `message`.
Every broker's exception class derives from `BrokerAPIException`, so code that talks to several brokers can catch that one class and still read `code` and `message`. This program catches it that way.
The real constructor reads the broker's settings from MongoDB, probes `GET /api/v3/profile`, and logs in to Fyers with a five step exchange of an OTP, a TOTP and a PIN when the stored token no longer works. This program must never log in, so a small subclass, `FyersAPIWithoutLogin`, skips that constructor and is handed the settings and a stand-in for Redis that already holds the stored login. `requests.request` is replaced, only while each request is sent, by a stand-in server that records the request and answers with a recorded-looking Fyers response, so nothing reaches the network.
Notice that the exception caught as `BrokerAPIException` is still a `FyersAPIException`, and that its `code` is the integer 502 rather than a code of Fyers's own.
Run it from the project root:
python examples/stock_brokers/api/fyers/FyersAPIException/example_2_catching_a_gateway_error.py
"""
import json
import logging
import unittest.mock
import requests
from stock_brokers.api.base import (
BrokerAPIException,
)
from stock_brokers.api.fyers import (
FyersAPI,
FyersAPIException,
)
STORED_LOGIN = {
'broker_name': 'fyers',
'access_token': 'morning-token',
'last_login': '2026-09-30 07:00:05',
}
GATEWAY_PAGE = '<html><head><title>502 Bad Gateway</title></head><body><center><h1>502 Bad Gateway</h1></center></body></html>'
class SharedLoginCache:
"""A dictionary-backed stand-in for Redis, holding the `last_login` hash that every process reads its token from.
Attributes:
hashes (dict): Each hash name mapped to a dictionary of its fields.
"""
def __init__(self):
"""Starts with nothing stored.
Returns:
None: This method returns nothing.
"""
self.hashes = {}
def hget(self, name, key):
"""Reads one field of a hash.
Args:
name (str): The hash name.
key (str): The field name.
Returns:
str | None: The stored value, or None when there is none.
"""
fields = self.hashes.get(name, {})
return fields.get(key)
def hset(self, name, key, value):
"""Writes one field of a hash, as a login does.
Args:
name (str): The hash name.
key (str): The field name.
value (str): The value to store.
Returns:
int: Always 1, the number of fields Redis reports written.
"""
if name not in self.hashes:
self.hashes[name] = {}
self.hashes[name][key] = value
return 1
class RecordedBrokerServer:
"""A stand-in for `requests.request` that answers every call with one recorded Fyers response and remembers what was sent.
Attributes:
status_code (int): The HTTP status every answer carries.
content_type (str): The Content-Type header every answer carries.
body (str): The body every answer carries.
calls (list): One dictionary per request, holding its method, URL, headers, body and certificate setting.
"""
def __init__(self, status_code, content_type, body):
"""Holds the answer to give.
Args:
status_code (int): The HTTP status every answer carries.
content_type (str): The Content-Type header every answer carries.
body (str): The body every answer carries.
Returns:
None: This method returns nothing.
"""
self.status_code = status_code
self.content_type = content_type
self.body = body
self.calls = []
def request(self, method, url, **options):
"""Records one request and answers it, in place of `requests.request`.
Args:
method (str): The HTTP method.
url (str): The URL requested.
**options (Any): The remaining `requests.request` arguments, such as `headers` and `data`.
Returns:
requests.Response: The recorded answer.
"""
self.calls.append({
'method': method,
'url': url,
'headers': options.get('headers'),
'data': options.get('data'),
'verify': options.get('verify'),
})
response = requests.Response()
response.status_code = self.status_code
response.headers['Content-Type'] = self.content_type
response._content = self.body.encode('utf-8')
response.url = url
return response
class FyersAPIWithoutLogin(FyersAPI):
"""A `FyersAPI` that is handed its settings and cache instead of loading them and logging in.
The real constructor reads the `fyers` settings document from MongoDB and then logs in to Fyers if the stored token no longer works. This subclass sets the same attributes from what it is given and does nothing else, so every request it makes still runs `FyersAPI`'s own `_request`.
"""
def __init__(self, cache, settings, stored_login):
"""Sets the attributes the real constructor would have loaded.
MongoDB is left out because the stored login is handed in here and is already in the cache, which is the first place `_current_login` looks.
Args:
cache (SharedLoginCache): The stand-in for Redis, already holding the stored login.
settings (dict): The broker's settings document.
stored_login (dict): The broker's `last_login` document, as the real constructor reads it from MongoDB.
Returns:
None: This method returns nothing.
"""
self._broker_name = 'fyers'
self._cache = cache
self._mongo_db = None
self._logger = logging.getLogger('fyers')
self._settings = settings
self._last_login = stored_login
class CatchingAGatewayErrorExample:
"""Sends a request that a gateway answers with an HTML error page and catches the result as a `BrokerAPIException`.
Attributes:
server (RecordedBrokerServer): The stand-in for Fyers's API, answering with a gateway error.
api (FyersAPIWithoutLogin): The API object being shown.
"""
def __init__(self):
"""Stores a login and builds the API object and the stand-in server.
Returns:
None: This method returns nothing.
"""
cache = SharedLoginCache()
cache.hset('last_login', 'fyers', json.dumps(STORED_LOGIN))
settings = {
'app_id': 'XB1234ABCD-100',
}
self.server = RecordedBrokerServer(502, 'text/html; charset=utf-8', GATEWAY_PAGE)
self.api = FyersAPIWithoutLogin(cache, settings, STORED_LOGIN)
def run(self):
"""Sends the request, catches the exception through the base class and prints what it holds.
Returns:
None: This method returns nothing.
"""
with unittest.mock.patch('requests.request', self.server.request):
try:
self.api.get(url='https://api-t1.fyers.in/api/v3/profile')
except BrokerAPIException as error:
print(f'Caught as BrokerAPIException: {type(error).__name__}')
print(f'Is an instance of FyersAPIException: {isinstance(error, FyersAPIException)}')
print(f'code: {error.code!r}')
print(f'message: {error.message}')
if __name__ == '__main__':
CatchingAGatewayErrorExample().run()
It prints:
BrokerAPIException represents an exception condition related to Broker API calls
-code: (string) error code
-message: (string) error message
Example programs
"""Raises a `BrokerAPIException` and reads the code and message it carries.
`BrokerAPIException` is what every broker class raises, through its own subclass, when a broker refuses a request. It holds the broker's error `code` and a `message`, both optional, and passes both to `Exception` as well, so they also appear in `args` and in the exception's text.
This program raises one with a Kite-style code and message, as `ZerodhaAPI` does for an expired token, and one with neither, and prints what a handler can read from each. It needs no data store, no network and no broker.
Notice that the code and message are plain attributes, and that an exception raised without them still has both, set to None.
Run it from the project root:
python examples/stock_brokers/api/base/BrokerAPIException/example_1_raising_and_reading_an_error.py
"""
from stock_brokers.api.base import (
BrokerAPIException,
)
class RaisingAndReadingAnErrorExample:
"""Raises two exceptions and prints what each holds.
Attributes:
errors (list): The exceptions to raise, one with a code and message and one without.
"""
def __init__(self):
"""Builds the exceptions to raise.
Returns:
None: This method returns nothing.
"""
self.errors = [
BrokerAPIException(code='TokenException', message='Incorrect `api_key` or `access_token`.'),
BrokerAPIException(),
]
def run(self):
"""Raises each exception, catches it and prints its fields.
Returns:
None: This method returns nothing.
"""
for error_to_raise in self.errors:
try:
raise error_to_raise
except BrokerAPIException as error:
print(f'code: {error.code!r}')
print(f'message: {error.message!r}')
print(f'args: {error.args!r}')
print(f'text: {error}')
print()
if __name__ == '__main__':
RaisingAndReadingAnErrorExample().run()
It prints:
"""Handles the errors of several brokers with one `except BrokerAPIException` clause.
Each broker module defines its own exception class, such as `DhanAPIException` or `ZerodhaAPIException`, and every one of them derives from `BrokerAPIException`. Code that works across brokers, such as a script that polls every broker's funds, can therefore catch the base class once and still read the broker's `code` and `message`, and use the exception's class to say which broker refused.
This program raises three brokers' exceptions with the codes and messages those brokers send for an expired token, catches them all with one handler, and prints what the handler sees. It needs no data store, no network and no broker.
Notice that every exception is caught by the same clause, and that each keeps its broker's own code: Dhan's `errorType`, Kite's `error_type` and Noren's `stat`.
Run it from the project root:
python examples/stock_brokers/api/base/BrokerAPIException/example_2_one_handler_for_every_broker.py
"""
from stock_brokers.api.base import (
BrokerAPIException,
)
from stock_brokers.api.dhan import (
DhanAPIException,
)
from stock_brokers.api.flattrade import (
FlattradeAPIException,
)
from stock_brokers.api.zerodha import (
ZerodhaAPIException,
)
class RefusingBroker:
"""A stand-in for one broker's API object whose every request is refused with that broker's exception.
Attributes:
broker_name (str): The broker's name.
refusal (BrokerAPIException): The exception every request raises.
"""
def __init__(self, broker_name, refusal):
"""Holds the broker's name and the refusal.
Args:
broker_name (str): The broker's name.
refusal (BrokerAPIException): The exception every request raises.
Returns:
None: This method returns nothing.
"""
self.broker_name = broker_name
self.refusal = refusal
def get(self, url):
"""Refuses the request.
Args:
url (str): The URL requested.
Returns:
dict: Never returns.
Raises:
BrokerAPIException: Always, the broker's own subclass of it.
"""
raise self.refusal
class OneHandlerExample:
"""Asks every broker for its funds and handles every refusal in one place.
Attributes:
brokers (list): The stand-in brokers to ask.
"""
def __init__(self):
"""Builds the refusing brokers.
Returns:
None: This method returns nothing.
"""
self.brokers = [
RefusingBroker('dhan', DhanAPIException(code='Invalid_Authentication', message='Client ID or user generated access token is invalid or expired.')),
RefusingBroker('zerodha', ZerodhaAPIException(code='TokenException', message='Incorrect `api_key` or `access_token`.')),
RefusingBroker('flattrade', FlattradeAPIException(code='Not_Ok', message='Session Expired : Invalid Session Key')),
]
def run(self):
"""Sends one request to each broker and prints each refusal.
Returns:
None: This method returns nothing.
"""
for broker in self.brokers:
try:
broker.get(url='/funds')
except BrokerAPIException as error:
print(f'{broker.broker_name}: {type(error).__name__} code={error.code} message={error.message}')
if __name__ == '__main__':
OneHandlerExample().run()
It prints:
dhan: DhanAPIException code=Invalid_Authentication message=Client ID or user generated access token is invalid or expired.
zerodha: ZerodhaAPIException code=TokenException message=Incorrect `api_key` or `access_token`.
flattrade: FlattradeAPIException code=Not_Ok message=Session Expired : Invalid Session Key
Source code in stock_brokers/api/base.py
FyersBlockedError
¶
Bases: FyersAPIException
Fyers, or Cloudflare in front of it, refused a request with HTTP 429: a rate limit or a ban on this address.
Example programs
"""Shows `FyersBlockedError` raised for Cloudflare's ban page and for Fyers' own rate limit, and that neither is taken for a dead session.
`FyersAPI` checks its stored token with the profile when it is built, and logs in again only when Fyers says the session is dead: codes -8, -15, -16 or -17, or HTTP 401. Before 2026-09-30 it logged in on any refusal, so Cloudflare's HTTP 429 ban page started a login into the ban, and every restart of every poller sent another, which kept the ban going all day. Any HTTP 429 now raises `FyersBlockedError`, and the pollers wait it out. This program sends nothing: it hands `_request` a stand-in response through a stand-in for `requests.request`, and asks `_is_dead_session` about each refusal.
Notice that both 429 answers raise `FyersBlockedError`, which no login follows, while the expired token's -16 and the 401 are the only dead sessions.
Run it from the project root:
python examples/stock_brokers/api/fyers/FyersBlockedError/example_1_a_ban_page_is_not_a_bad_token.py
"""
import stock_brokers.api.fyers as fyers_module
from stock_brokers.api.fyers import (
FyersAPI,
FyersAPIException,
FyersBlockedError,
)
class StandInResponse:
"""A response with a status, a content type and a body.
Attributes:
status_code (int): The HTTP status.
headers (dict): The headers, with `Content-Type`.
content (bytes): The body.
"""
def __init__(self, status_code, content_type, body):
"""Builds the response.
Args:
status_code (int): The HTTP status.
content_type (str): The content type.
body (str): The body.
Returns:
None: This method returns nothing.
"""
self.status_code = status_code
self.headers = {
'Content-Type': content_type,
}
self.content = body.encode()
def json(self):
"""The body decoded as JSON.
Returns:
object: The body.
"""
return fyers_module.json_lib.loads(self.content)
class StandInRequests:
"""Stands in for the `requests` module, answering every request with one response.
Attributes:
response (StandInResponse): The response to give.
"""
def __init__(self, response):
"""Builds the stand-in.
Args:
response (StandInResponse): The response.
Returns:
None: This method returns nothing.
"""
self.response = response
def request(self, **options):
"""Answers with the response.
Args:
**options: The request's options.
Returns:
StandInResponse: The response.
"""
del options
return self.response
class OfflineFyersAPI(FyersAPI):
"""A Fyers API object built without any store, holding a stand-in login."""
def __init__(self):
"""Holds a stand-in login and settings instead of reading MongoDB and Redis.
Returns:
None: This method returns nothing.
"""
self._settings = {
'app_id': 'STANDIN-100',
}
self._last_login = {
'access_token': 'stand-in-token',
}
def _current_login(self):
"""The stand-in login.
Returns:
dict: The login.
"""
return self._last_login
class ABanPageIsNotABadTokenExample:
"""Sends four stand-in refusals through `_request` and classifies them.
Attributes:
api (OfflineFyersAPI): The API object.
answers (list): `(description, StandInResponse)` tuples.
"""
def __init__(self):
"""Builds the API object and the four answers.
Returns:
None: This method returns nothing.
"""
self.api = OfflineFyersAPI()
self.answers = [
('Cloudflare ban page', StandInResponse(429, 'text/html', '<html>Error 1015: you are being rate limited by Cloudflare</html>')),
('Fyers rate limit', StandInResponse(429, 'application/json', '{"s": "error", "code": 429, "message": "request limit reached"}')),
('expired token', StandInResponse(401, 'application/json', '{"s": "error", "code": -16, "message": "Could not authenticate the user"}')),
('plain HTTP 401', StandInResponse(401, 'text/plain', 'Unauthorized')),
]
def run(self):
"""Prints what each refusal raises and whether it counts as a dead session.
Returns:
None: This method returns nothing.
"""
original_requests = fyers_module.requests
try:
for description, response in self.answers:
fyers_module.requests = StandInRequests(response)
try:
self.api._request('GET', 'https://api-t1.fyers.in/api/v3/profile')
except FyersBlockedError as error:
print(f'{description}: FyersBlockedError, dead session {self.api._is_dead_session(error)}')
except FyersAPIException as error:
print(f'{description}: FyersAPIException {error.args[0]}, dead session {self.api._is_dead_session(error)}')
finally:
fyers_module.requests = original_requests
if __name__ == '__main__':
ABanPageIsNotABadTokenExample().run()
It prints:
"""Shows a login step refused with HTTP 429 raising `FyersBlockedError`, so the caller waits instead of starting another login.
A Fyers login is five requests: send the OTP, verify it, verify the PIN, get an auth code, and validate it. When any of them is refused with HTTP 429, `_refuse_if_blocked` raises `FyersBlockedError` naming the step, and the pollers recognise it as a ban and pause for thirty minutes. A step refused any other way still raises plain `FyersAPIException`, as before. This program checks three stand-in responses without sending anything.
Notice that only the 429 raises, and that its message names the step and mentions Cloudflare, which is what the pollers' `is_block` looks for.
Run it from the project root:
python examples/stock_brokers/api/fyers/FyersBlockedError/example_2_a_login_step_refused.py
"""
from stock_brokers.api.fyers import (
FyersAPI,
FyersBlockedError,
)
class StandInResponse:
"""A response with a status and a body.
Attributes:
status_code (int): The HTTP status.
text (str): The body.
"""
def __init__(self, status_code, text):
"""Builds the response.
Args:
status_code (int): The HTTP status.
text (str): The body.
Returns:
None: This method returns nothing.
"""
self.status_code = status_code
self.text = text
class OfflineFyersAPI(FyersAPI):
"""A Fyers API object built without any store or request."""
def __init__(self):
"""Builds nothing.
Returns:
None: This method returns nothing.
"""
class ALoginStepRefusedExample:
"""Checks three login-step responses.
Attributes:
api (OfflineFyersAPI): The API object.
"""
def __init__(self):
"""Builds the API object.
Returns:
None: This method returns nothing.
"""
self.api = OfflineFyersAPI()
def run(self):
"""Prints what each response leads to.
Returns:
None: This method returns nothing.
"""
responses = [
('OTP sent', StandInResponse(200, '{"request_key": "abc"}')),
('OTP refused by a ban', StandInResponse(429, '<html>error code: 1015</html>')),
('OTP refused for a wrong ID', StandInResponse(400, '{"s": "error"}')),
]
for description, response in responses:
try:
self.api._refuse_if_blocked(response, 'Sending the login OTP')
print(f'{description}: carries on to the next check')
except FyersBlockedError as error:
print(f'{description}: FyersBlockedError {error.args[0]}: {error.args[1][:90]}')
if __name__ == '__main__':
ALoginStepRefusedExample().run()
It prints:
BrokerAPIException represents an exception condition related to Broker API calls
-code: (string) error code
-message: (string) error message
Example programs
"""Raises a `BrokerAPIException` and reads the code and message it carries.
`BrokerAPIException` is what every broker class raises, through its own subclass, when a broker refuses a request. It holds the broker's error `code` and a `message`, both optional, and passes both to `Exception` as well, so they also appear in `args` and in the exception's text.
This program raises one with a Kite-style code and message, as `ZerodhaAPI` does for an expired token, and one with neither, and prints what a handler can read from each. It needs no data store, no network and no broker.
Notice that the code and message are plain attributes, and that an exception raised without them still has both, set to None.
Run it from the project root:
python examples/stock_brokers/api/base/BrokerAPIException/example_1_raising_and_reading_an_error.py
"""
from stock_brokers.api.base import (
BrokerAPIException,
)
class RaisingAndReadingAnErrorExample:
"""Raises two exceptions and prints what each holds.
Attributes:
errors (list): The exceptions to raise, one with a code and message and one without.
"""
def __init__(self):
"""Builds the exceptions to raise.
Returns:
None: This method returns nothing.
"""
self.errors = [
BrokerAPIException(code='TokenException', message='Incorrect `api_key` or `access_token`.'),
BrokerAPIException(),
]
def run(self):
"""Raises each exception, catches it and prints its fields.
Returns:
None: This method returns nothing.
"""
for error_to_raise in self.errors:
try:
raise error_to_raise
except BrokerAPIException as error:
print(f'code: {error.code!r}')
print(f'message: {error.message!r}')
print(f'args: {error.args!r}')
print(f'text: {error}')
print()
if __name__ == '__main__':
RaisingAndReadingAnErrorExample().run()
It prints:
"""Handles the errors of several brokers with one `except BrokerAPIException` clause.
Each broker module defines its own exception class, such as `DhanAPIException` or `ZerodhaAPIException`, and every one of them derives from `BrokerAPIException`. Code that works across brokers, such as a script that polls every broker's funds, can therefore catch the base class once and still read the broker's `code` and `message`, and use the exception's class to say which broker refused.
This program raises three brokers' exceptions with the codes and messages those brokers send for an expired token, catches them all with one handler, and prints what the handler sees. It needs no data store, no network and no broker.
Notice that every exception is caught by the same clause, and that each keeps its broker's own code: Dhan's `errorType`, Kite's `error_type` and Noren's `stat`.
Run it from the project root:
python examples/stock_brokers/api/base/BrokerAPIException/example_2_one_handler_for_every_broker.py
"""
from stock_brokers.api.base import (
BrokerAPIException,
)
from stock_brokers.api.dhan import (
DhanAPIException,
)
from stock_brokers.api.flattrade import (
FlattradeAPIException,
)
from stock_brokers.api.zerodha import (
ZerodhaAPIException,
)
class RefusingBroker:
"""A stand-in for one broker's API object whose every request is refused with that broker's exception.
Attributes:
broker_name (str): The broker's name.
refusal (BrokerAPIException): The exception every request raises.
"""
def __init__(self, broker_name, refusal):
"""Holds the broker's name and the refusal.
Args:
broker_name (str): The broker's name.
refusal (BrokerAPIException): The exception every request raises.
Returns:
None: This method returns nothing.
"""
self.broker_name = broker_name
self.refusal = refusal
def get(self, url):
"""Refuses the request.
Args:
url (str): The URL requested.
Returns:
dict: Never returns.
Raises:
BrokerAPIException: Always, the broker's own subclass of it.
"""
raise self.refusal
class OneHandlerExample:
"""Asks every broker for its funds and handles every refusal in one place.
Attributes:
brokers (list): The stand-in brokers to ask.
"""
def __init__(self):
"""Builds the refusing brokers.
Returns:
None: This method returns nothing.
"""
self.brokers = [
RefusingBroker('dhan', DhanAPIException(code='Invalid_Authentication', message='Client ID or user generated access token is invalid or expired.')),
RefusingBroker('zerodha', ZerodhaAPIException(code='TokenException', message='Incorrect `api_key` or `access_token`.')),
RefusingBroker('flattrade', FlattradeAPIException(code='Not_Ok', message='Session Expired : Invalid Session Key')),
]
def run(self):
"""Sends one request to each broker and prints each refusal.
Returns:
None: This method returns nothing.
"""
for broker in self.brokers:
try:
broker.get(url='/funds')
except BrokerAPIException as error:
print(f'{broker.broker_name}: {type(error).__name__} code={error.code} message={error.message}')
if __name__ == '__main__':
OneHandlerExample().run()
It prints:
dhan: DhanAPIException code=Invalid_Authentication message=Client ID or user generated access token is invalid or expired.
zerodha: ZerodhaAPIException code=TokenException message=Incorrect `api_key` or `access_token`.
flattrade: FlattradeAPIException code=Not_Ok message=Session Expired : Invalid Session Key
Source code in stock_brokers/api/base.py
FyersAPI
¶
Bases: BrokerAPI
Fyers API class
Fyers API class
Example programs
"""Reads the account profile from Fyers's REST API with a stored access token.
`FyersAPI` is the object every Fyers script talks to the broker through. Its `get`, `post`, `put`, `patch` and `delete` methods all go through the broker's own `_request`, which adds the credentials of the login in force, sends the request, and wraps a successful answer in a dictionary with `status`, `code`, `data` and a `timestamp`.
The real constructor reads the broker's settings from MongoDB, probes `GET /api/v3/profile`, and logs in to Fyers with a five step exchange of an OTP, a TOTP and a PIN when the stored token no longer works. This program must never log in, so a small subclass, `FyersAPIWithoutLogin`, skips that constructor and is handed the settings and a stand-in for Redis that already holds the stored login. `requests.request` is replaced, only while each request is sent, by a stand-in server that records the request and answers with a recorded-looking Fyers response, so nothing reaches the network.
Notice the headers the request carried, which were built from the stored login and, where the broker needs them, from the settings, and that `data` holds only the `data` object, because `_request` unwraps the envelope Fyers puts around every answer. The `timestamp` is left out of the output because it is the moment the program ran.
Run it from the project root:
python examples/stock_brokers/api/fyers/FyersAPI/example_1_reading_the_profile.py
"""
import json
import logging
import unittest.mock
import requests
from stock_brokers.api.fyers import (
FyersAPI,
)
STORED_LOGIN = {
'broker_name': 'fyers',
'access_token': 'morning-token',
'last_login': '2026-09-30 07:00:05',
}
RECORDED_ANSWER = {
's': 'ok',
'code': 200,
'message': '',
'data': {
'fy_id': 'XD00001',
'name': 'DEMO USER',
'email_id': 'demo.user@example.com',
'totp': True,
'pwd_to_expire': 90,
'ddpi_enabled': False,
'mtf_enabled': False,
},
}
class SharedLoginCache:
"""A dictionary-backed stand-in for Redis, holding the `last_login` hash that every process reads its token from.
Attributes:
hashes (dict): Each hash name mapped to a dictionary of its fields.
"""
def __init__(self):
"""Starts with nothing stored.
Returns:
None: This method returns nothing.
"""
self.hashes = {}
def hget(self, name, key):
"""Reads one field of a hash.
Args:
name (str): The hash name.
key (str): The field name.
Returns:
str | None: The stored value, or None when there is none.
"""
fields = self.hashes.get(name, {})
return fields.get(key)
def hset(self, name, key, value):
"""Writes one field of a hash, as a login does.
Args:
name (str): The hash name.
key (str): The field name.
value (str): The value to store.
Returns:
int: Always 1, the number of fields Redis reports written.
"""
if name not in self.hashes:
self.hashes[name] = {}
self.hashes[name][key] = value
return 1
class RecordedBrokerServer:
"""A stand-in for `requests.request` that answers every call with one recorded Fyers response and remembers what was sent.
Attributes:
status_code (int): The HTTP status every answer carries.
content_type (str): The Content-Type header every answer carries.
body (str): The body every answer carries.
calls (list): One dictionary per request, holding its method, URL, headers, body and certificate setting.
"""
def __init__(self, status_code, content_type, body):
"""Holds the answer to give.
Args:
status_code (int): The HTTP status every answer carries.
content_type (str): The Content-Type header every answer carries.
body (str): The body every answer carries.
Returns:
None: This method returns nothing.
"""
self.status_code = status_code
self.content_type = content_type
self.body = body
self.calls = []
def request(self, method, url, **options):
"""Records one request and answers it, in place of `requests.request`.
Args:
method (str): The HTTP method.
url (str): The URL requested.
**options (Any): The remaining `requests.request` arguments, such as `headers` and `data`.
Returns:
requests.Response: The recorded answer.
"""
self.calls.append({
'method': method,
'url': url,
'headers': options.get('headers'),
'data': options.get('data'),
'verify': options.get('verify'),
})
response = requests.Response()
response.status_code = self.status_code
response.headers['Content-Type'] = self.content_type
response._content = self.body.encode('utf-8')
response.url = url
return response
class FyersAPIWithoutLogin(FyersAPI):
"""A `FyersAPI` that is handed its settings and cache instead of loading them and logging in.
The real constructor reads the `fyers` settings document from MongoDB and then logs in to Fyers if the stored token no longer works. This subclass sets the same attributes from what it is given and does nothing else, so every request it makes still runs `FyersAPI`'s own `_request`.
"""
def __init__(self, cache, settings, stored_login):
"""Sets the attributes the real constructor would have loaded.
MongoDB is left out because the stored login is handed in here and is already in the cache, which is the first place `_current_login` looks.
Args:
cache (SharedLoginCache): The stand-in for Redis, already holding the stored login.
settings (dict): The broker's settings document.
stored_login (dict): The broker's `last_login` document, as the real constructor reads it from MongoDB.
Returns:
None: This method returns nothing.
"""
self._broker_name = 'fyers'
self._cache = cache
self._mongo_db = None
self._logger = logging.getLogger('fyers')
self._settings = settings
self._last_login = stored_login
class ReadingTheProfileExample:
"""Sends one authenticated request through `FyersAPI` and prints what went out and what came back.
Attributes:
cache (SharedLoginCache): The stand-in for Redis, holding the stored login.
server (RecordedBrokerServer): The stand-in for Fyers's API.
api (FyersAPIWithoutLogin): The API object being shown.
"""
def __init__(self):
"""Stores the morning login and builds the API object and the stand-in server.
Returns:
None: This method returns nothing.
"""
self.cache = SharedLoginCache()
self.cache.hset('last_login', 'fyers', json.dumps(STORED_LOGIN))
settings = {
'app_id': 'XB1234ABCD-100',
}
self.server = RecordedBrokerServer(200, 'application/json', json.dumps(RECORDED_ANSWER))
self.api = FyersAPIWithoutLogin(self.cache, settings, STORED_LOGIN)
def run(self):
"""Sends the request and prints the request and the answer.
Returns:
None: This method returns nothing.
"""
with unittest.mock.patch('requests.request', self.server.request):
answer = self.api.get(url='https://api-t1.fyers.in/api/v3/profile')
call = self.server.calls[0]
print(f'Request: {call["method"]} {call["url"]}')
print('Headers sent:')
for name, value in call['headers'].items():
print(f' {name}: {value}')
print(f'Status: {answer["status"]}')
print(f'HTTP code: {answer["code"]}')
print('Data:')
print(json.dumps(answer['data'], indent=4))
if __name__ == '__main__':
ReadingTheProfileExample().run()
It prints:
Request: GET https://api-t1.fyers.in/api/v3/profile
Headers sent:
Content-Type: application/json
Authorization: XB1234ABCD-100:morning-token
Status: success
HTTP code: 200
Data:
{
"fy_id": "XD00001",
"name": "DEMO USER",
"email_id": "demo.user@example.com",
"totp": true,
"pwd_to_expire": 90,
"ddpi_enabled": false,
"mtf_enabled": false
}
"""Picks up an access token another process obtained, on the very next request.
Every Fyers script builds its own `FyersAPI`, and more than one of them may log in during a day. A login writes the new token to MongoDB and then to the Redis `last_login` hash, and `FyersAPI`'s `_request` reads that hash again before every request, keeping whichever login is newer by its `last_login` time. So a token obtained by any process is used by every other one without restarting anything.
The program sends two requests through one API object. Between them it writes a newer login into the stand-in for Redis, as another process's login would.
The real constructor reads the broker's settings from MongoDB, probes `GET /api/v3/profile`, and logs in to Fyers with a five step exchange of an OTP, a TOTP and a PIN when the stored token no longer works. This program must never log in, so a small subclass, `FyersAPIWithoutLogin`, skips that constructor and is handed the settings and a stand-in for Redis that already holds the stored login. `requests.request` is replaced, only while each request is sent, by a stand-in server that records the request and answers with a recorded-looking Fyers response, so nothing reaches the network.
Notice that the second request carries the newer token although the object was never rebuilt.
Run it from the project root:
python examples/stock_brokers/api/fyers/FyersAPI/example_2_using_a_newer_login.py
"""
import json
import logging
import unittest.mock
import requests
from stock_brokers.api.fyers import (
FyersAPI,
)
STORED_LOGIN = {
'broker_name': 'fyers',
'access_token': 'morning-token',
'last_login': '2026-09-30 07:00:05',
}
NEWER_LOGIN = {
'broker_name': 'fyers',
'access_token': 'noon-token',
'last_login': '2026-09-30 12:30:41',
}
RECORDED_ANSWER = {
's': 'ok',
'code': 200,
'message': '',
'fund_limit': [
{
'id': 1,
'title': 'Total Balance',
'equityAmount': 125000.0,
'commodityAmount': 0.0,
},
{
'id': 10,
'title': 'Available Balance',
'equityAmount': 118250.5,
'commodityAmount': 0.0,
},
],
}
class SharedLoginCache:
"""A dictionary-backed stand-in for Redis, holding the `last_login` hash that every process reads its token from.
Attributes:
hashes (dict): Each hash name mapped to a dictionary of its fields.
"""
def __init__(self):
"""Starts with nothing stored.
Returns:
None: This method returns nothing.
"""
self.hashes = {}
def hget(self, name, key):
"""Reads one field of a hash.
Args:
name (str): The hash name.
key (str): The field name.
Returns:
str | None: The stored value, or None when there is none.
"""
fields = self.hashes.get(name, {})
return fields.get(key)
def hset(self, name, key, value):
"""Writes one field of a hash, as a login does.
Args:
name (str): The hash name.
key (str): The field name.
value (str): The value to store.
Returns:
int: Always 1, the number of fields Redis reports written.
"""
if name not in self.hashes:
self.hashes[name] = {}
self.hashes[name][key] = value
return 1
class RecordedBrokerServer:
"""A stand-in for `requests.request` that answers every call with one recorded Fyers response and remembers what was sent.
Attributes:
status_code (int): The HTTP status every answer carries.
content_type (str): The Content-Type header every answer carries.
body (str): The body every answer carries.
calls (list): One dictionary per request, holding its method, URL, headers, body and certificate setting.
"""
def __init__(self, status_code, content_type, body):
"""Holds the answer to give.
Args:
status_code (int): The HTTP status every answer carries.
content_type (str): The Content-Type header every answer carries.
body (str): The body every answer carries.
Returns:
None: This method returns nothing.
"""
self.status_code = status_code
self.content_type = content_type
self.body = body
self.calls = []
def request(self, method, url, **options):
"""Records one request and answers it, in place of `requests.request`.
Args:
method (str): The HTTP method.
url (str): The URL requested.
**options (Any): The remaining `requests.request` arguments, such as `headers` and `data`.
Returns:
requests.Response: The recorded answer.
"""
self.calls.append({
'method': method,
'url': url,
'headers': options.get('headers'),
'data': options.get('data'),
'verify': options.get('verify'),
})
response = requests.Response()
response.status_code = self.status_code
response.headers['Content-Type'] = self.content_type
response._content = self.body.encode('utf-8')
response.url = url
return response
class FyersAPIWithoutLogin(FyersAPI):
"""A `FyersAPI` that is handed its settings and cache instead of loading them and logging in.
The real constructor reads the `fyers` settings document from MongoDB and then logs in to Fyers if the stored token no longer works. This subclass sets the same attributes from what it is given and does nothing else, so every request it makes still runs `FyersAPI`'s own `_request`.
"""
def __init__(self, cache, settings, stored_login):
"""Sets the attributes the real constructor would have loaded.
MongoDB is left out because the stored login is handed in here and is already in the cache, which is the first place `_current_login` looks.
Args:
cache (SharedLoginCache): The stand-in for Redis, already holding the stored login.
settings (dict): The broker's settings document.
stored_login (dict): The broker's `last_login` document, as the real constructor reads it from MongoDB.
Returns:
None: This method returns nothing.
"""
self._broker_name = 'fyers'
self._cache = cache
self._mongo_db = None
self._logger = logging.getLogger('fyers')
self._settings = settings
self._last_login = stored_login
class UsingANewerLoginExample:
"""Sends a request, lets another process log in, and sends another through the same object.
Attributes:
cache (SharedLoginCache): The stand-in for Redis, holding the shared login.
server (RecordedBrokerServer): The stand-in for Fyers's API.
api (FyersAPIWithoutLogin): The API object being shown.
"""
def __init__(self):
"""Stores the morning login and builds the API object and the stand-in server.
Returns:
None: This method returns nothing.
"""
self.cache = SharedLoginCache()
self.cache.hset('last_login', 'fyers', json.dumps(STORED_LOGIN))
settings = {
'app_id': 'XB1234ABCD-100',
}
self.server = RecordedBrokerServer(200, 'application/json', json.dumps(RECORDED_ANSWER))
self.api = FyersAPIWithoutLogin(self.cache, settings, STORED_LOGIN)
def credential(self, call):
"""The credential one recorded request carried.
Args:
call (dict): One request recorded by the stand-in server.
Returns:
str: The `Authorization` header.
"""
return call['headers']['Authorization']
def run(self):
"""Sends a request, writes a newer login, sends another request and prints what each carried.
Returns:
None: This method returns nothing.
"""
with unittest.mock.patch('requests.request', self.server.request):
self.api.get(url='https://api-t1.fyers.in/api/v3/funds')
print(f'First request carried: {self.credential(self.server.calls[0])}')
self.cache.hset('last_login', 'fyers', json.dumps(NEWER_LOGIN))
print('Another process logged in again at 12:30:41 and wrote its login to Redis.')
with unittest.mock.patch('requests.request', self.server.request):
answer = self.api.get(url='https://api-t1.fyers.in/api/v3/funds')
print(f'Second request carried: {self.credential(self.server.calls[1])}')
print(f'Request: {self.server.calls[1]["method"]} {self.server.calls[1]["url"]}')
print(f'Status: {answer["status"]}, HTTP code: {answer["code"]}')
print('Data:')
print(json.dumps(answer['data'], indent=4))
if __name__ == '__main__':
UsingANewerLoginExample().run()
It prints:
First request carried: XB1234ABCD-100:morning-token
Another process logged in again at 12:30:41 and wrote its login to Redis.
Second request carried: XB1234ABCD-100:noon-token
Request: GET https://api-t1.fyers.in/api/v3/funds
Status: success, HTTP code: 200
Data:
{
"s": "ok",
"code": 200,
"message": "",
"fund_limit": [
{
"id": 1,
"title": "Total Balance",
"equityAmount": 125000.0,
"commodityAmount": 0.0
},
{
"id": 10,
"title": "Available Balance",
"equityAmount": 118250.5,
"commodityAmount": 0.0
}
]
}
Methods:
| Name | Description |
|---|---|
get |
HTTP GET API call to Broker's API server. |
post |
HTTP POST API call to Broker's API server. |
put |
HTTP PUT API call to Broker's API server. |
patch |
HTTP PATCH API call to Broker's API server. |
delete |
HTTP DELETE API call to Broker's API server. |
Source code in stock_brokers/api/fyers.py
_is_dead_session
¶
Whether a refused profile request means the stored token no longer works, which a login fixes.
Only Fyers' own session codes and HTTP 401 count. A ban, a rate limit or a server error is not fixed by logging in, and a login sent while Cloudflare is blocking this address only renews the block.
exception: (FyersAPIException) the refusal.
Source code in stock_brokers/api/fyers.py
_refuse_if_blocked
¶
Raise FyersBlockedError when a login step was refused with HTTP 429, so the caller waits instead of trying again at once.
response: (requests.Response) the step's response.step: (str) what the step was doing, for the message.
Source code in stock_brokers/api/fyers.py
_log_in
¶
Log in to Fyers with the OTP, TOTP and PIN flow, and store the day's access token in MongoDB and Redis.
Raises FyersBlockedError when a step is refused with HTTP 429, and FyersAPIException when a step fails any other way.
Source code in stock_brokers/api/fyers.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | |
_request
¶
_request(method, url, params=None, data=None, headers=None, cookies=None, files=None, auth=None, timeout=None, allow_redirects=None, proxies=None, hooks=None, stream=None, verify=None, cert=None, json=None, verbose=False)
Private generic REST API request to Broker API server. This is specialized into GET, POST, PUT, PATCH and DELETE by public methods.
method: HTTP method to use for the request.url: URL of the API endpoint.params: Dictionary of parameters to be sent as part of the request.data: Dictionary, bytes, or file-like object to send in the body of the request.headers: Dictionary of HTTP headers to be sent with the request.cookies: Dictionary of cookies to be sent with the request.files: Dictionary of files to be sent with the request.auth: Authentication tuple or object to be sent with the request.timeout: Timeout value for the request.allow_redirects: Boolean value indicating whether redirects should be allowed.proxies: Dictionary of proxy settings for the request.hooks: Dictionary of hooks to be called during the request lifecycle.stream: Boolean value indicating whether response content should be streamed.verify: Boolean value indicating whether SSL certificate verification should be performed.cert: Certificate file or tuple containing certificate and key files for client-side SSL certificate verification.json: JSON data to send in the body of the request.verbose: If set to True, the request and response are logged.
Source code in stock_brokers/api/fyers.py
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | |
_current_login
¶
The login in force right now, read on every request rather than once at construction.
Any process that logs a broker in writes the new login to MongoDB and then to the Redis
last_login hash. Reading that hash here, on every request, means a token another process
has just obtained is used by this object's very next request, rather than a token loaded at
construction being sent long after it has been replaced.
Redis is the one place a token is read from, and a login the only thing that writes it. Constructors do not copy MongoDB into it, because that would race a login: a process that read MongoDB just before another logged in, and wrote Redis just after, would put the old token back for everyone.
The newer of this object's login and Redis's is used, by their last_login time. The
shared login normally wins. This object's own wins only when it is genuinely newer - a
login this object has just made, or one whose write to Redis failed while its write to
MongoDB, which this object was built from, succeeded. When either time cannot be read,
Redis is trusted.
When Redis holds nothing for the broker, the login is read from MongoDB and written into Redis only if that field is still empty, so it can fill the cache but never overwrite a login that lands in between. When neither store can be read, the object keeps what it has.
Returns:
| Type | Description |
|---|---|
dict | None
|
The |
Source code in stock_brokers/api/base.py
_login_moment
staticmethod
¶
When a login document was made, or None when that cannot be read.
Brokers stamp last_login with local time, some with microseconds and some without.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
document
|
dict | None
|
A |
required |
Returns:
| Type | Description |
|---|---|
datetime | None
|
The moment of the login. |
Source code in stock_brokers/api/base.py
get
¶
get(url, params=None, data=None, headers=None, cookies=None, files=None, auth=None, timeout=None, allow_redirects=None, proxies=None, hooks=None, stream=None, verify=None, cert=None, json=None, verbose=False)
HTTP GET API call to Broker's API server. This queries the Broker's API server for some information. Most responses are JSON encoded. Only a few are CSV encoded.
url: URL of the API endpoint.params: Dictionary of parameters to be sent as part of the request.data: Dictionary, bytes, or file-like object to send in the body of the request.headers: Dictionary of HTTP headers to be sent with the request.cookies: Dictionary of cookies to be sent with the request.files: Dictionary of files to be sent with the request.auth: Authentication tuple or object to be sent with the request.timeout: Timeout value for the request.allow_redirects: Boolean value indicating whether redirects should be allowed.proxies: Dictionary of proxy settings for the request.hooks: Dictionary of hooks to be called during the request lifecycle.stream: Boolean value indicating whether response content should be streamed.verify: Boolean value indicating whether SSL certificate verification should be performed.cert: Certificate file or tuple containing certificate and key files for client-side SSL certificate verification.json: JSON data to send in the body of the request.verbose: If set to True, the request and response are logged.
Example usage
Source code in stock_brokers/api/base.py
post
¶
post(url, params=None, data=None, headers=None, cookies=None, files=None, auth=None, timeout=None, allow_redirects=None, proxies=None, hooks=None, stream=None, verify=None, cert=None, json=None, verbose=False)
HTTP POST API call to Broker's API server. This carries out some action using Broker's API server such as placing an order. Responses are JSON encoded.
url: URL of the API endpoint.params: Dictionary of parameters to be sent as part of the request.data: Dictionary, bytes, or file-like object to send in the body of the request.headers: Dictionary of HTTP headers to be sent with the request.cookies: Dictionary of cookies to be sent with the request.files: Dictionary of files to be sent with the request.auth: Authentication tuple or object to be sent with the request.timeout: Timeout value for the request.allow_redirects: Boolean value indicating whether redirects should be allowed.proxies: Dictionary of proxy settings for the request.hooks: Dictionary of hooks to be called during the request lifecycle.stream: Boolean value indicating whether response content should be streamed.verify: Boolean value indicating whether SSL certificate verification should be performed.cert: Certificate file or tuple containing certificate and key files for client-side SSL certificate verification.json: JSON data to send in the body of the request.verbose: If set to True, the request and response are logged.
Example usage
Source code in stock_brokers/api/base.py
put
¶
put(url, params=None, data=None, headers=None, cookies=None, files=None, auth=None, timeout=None, allow_redirects=None, proxies=None, hooks=None, stream=None, verify=None, cert=None, json=None, verbose=False)
HTTP PUT API call to Broker's API server. This modifies something using Broker's API server such as modifying an order. Responses are JSON encoded.
url: URL of the API endpoint.params: Dictionary of parameters to be sent as part of the request.data: Dictionary, bytes, or file-like object to send in the body of the request.headers: Dictionary of HTTP headers to be sent with the request.cookies: Dictionary of cookies to be sent with the request.files: Dictionary of files to be sent with the request.auth: Authentication tuple or object to be sent with the request.timeout: Timeout value for the request.allow_redirects: Boolean value indicating whether redirects should be allowed.proxies: Dictionary of proxy settings for the request.hooks: Dictionary of hooks to be called during the request lifecycle.stream: Boolean value indicating whether response content should be streamed.verify: Boolean value indicating whether SSL certificate verification should be performed.cert: Certificate file or tuple containing certificate and key files for client-side SSL certificate verification.json: JSON data to send in the body of the request.verbose: If set to True, the request and response are logged.
Example usage
Source code in stock_brokers/api/base.py
patch
¶
patch(url, params=None, data=None, headers=None, cookies=None, files=None, auth=None, timeout=None, allow_redirects=None, proxies=None, hooks=None, stream=None, verify=None, cert=None, json=None, verbose=False)
HTTP PATCH API call to Broker's API server. This updates something using Broker's API server such as modifying an order. Responses are JSON encoded.
url: URL of the API endpoint.params: Dictionary of parameters to be sent as part of the request.data: Dictionary, bytes, or file-like object to send in the body of the request.headers: Dictionary of HTTP headers to be sent with the request.cookies: Dictionary of cookies to be sent with the request.files: Dictionary of files to be sent with the request.auth: Authentication tuple or object to be sent with the request.timeout: Timeout value for the request.allow_redirects: Boolean value indicating whether redirects should be allowed.proxies: Dictionary of proxy settings for the request.hooks: Dictionary of hooks to be called during the request lifecycle.stream: Boolean value indicating whether response content should be streamed.verify: Boolean value indicating whether SSL certificate verification should be performed.cert: Certificate file or tuple containing certificate and key files for client-side SSL certificate verification.json: JSON data to send in the body of the request.verbose: If set to True, the request and response are logged.
Example usage
Source code in stock_brokers/api/base.py
delete
¶
delete(url, params=None, data=None, headers=None, cookies=None, files=None, auth=None, timeout=None, allow_redirects=None, proxies=None, hooks=None, stream=None, verify=None, cert=None, json=None, verbose=False)
HTTP DELETE API call to Broker's API server. This deletes something using Broker's API server such as cancelling an order or invalidating an access token. Responses are JSON encoded.
url: URL of the API endpoint.params: Dictionary of parameters to be sent as part of the request.data: Dictionary, bytes, or file-like object to send in the body of the request.headers: Dictionary of HTTP headers to be sent with the request.cookies: Dictionary of cookies to be sent with the request.files: Dictionary of files to be sent with the request.auth: Authentication tuple or object to be sent with the request.timeout: Timeout value for the request.allow_redirects: Boolean value indicating whether redirects should be allowed.proxies: Dictionary of proxy settings for the request.hooks: Dictionary of hooks to be called during the request lifecycle.stream: Boolean value indicating whether response content should be streamed.verify: Boolean value indicating whether SSL certificate verification should be performed.cert: Certificate file or tuple containing certificate and key files for client-side SSL certificate verification.json: JSON data to send in the body of the request.verbose: If set to True, the request and response are logged.
Example usage