Skip to main content

Limeint Trade API — Python SDK

Limeint's Python SDK for the gRPC Trade API. It wraps the generated stubs with:

  • a single TradeAPIClient / AsyncTradeAPIClient entry point,
  • automatic JWT issuance and background refresh (via AuthService.SubscribeJwtRenewal),
  • a from_rpc_error() helper for typed errors,
  • exponential-backoff retries for UNAVAILABLE and server-approved rate-limit retries.

Service methods are invoked directly on the generated stubs, without an extra request or response translation layer.

Installation

Python 3.10 or newer is required.

This checkout currently targets 2.18.2, which is on PyPI. Create and activate a virtual environment, then install it:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install limeint-sdk==2.18.2

The PyPI distribution is limeint-sdk; the Python import name is trade_api.

Quick start

The first program authenticates and prints the account IDs visible to the secret. It is bounded and does not place an order.

Save this as quickstart.py:

import os

from trade_api import TradeAPIClient
from trade_api.auth_messages import TokenDetailsRequest


secret = os.environ["TRADE_API_SECRET"]

with TradeAPIClient(secret=secret) as client:
    token = client.get_token()
    if token is None:
        raise RuntimeError("Authentication did not return a token")

    details = client.auth.TokenDetails(TokenDetailsRequest(token=token))
    print("Available account IDs:", list(details.account_ids))

Run it inside the activated virtual environment:

TRADE_API_SECRET=... python quickstart.py

If authentication fails, confirm that the secret is active. An empty account list means the token does not expose a trading account; it may still be usable for market data if it has the required entitlement.

To fetch one of the discovered accounts, extend the program like this:

import os

from trade_api import TradeAPIClient
from trade_api.accounts import GetAccountRequest
from trade_api.auth_messages import TokenDetailsRequest


with TradeAPIClient(secret=os.environ["TRADE_API_SECRET"]) as client:
    token = client.get_token()
    if token is None:
        raise RuntimeError("Authentication did not return a token")

    details = client.auth.TokenDetails(TokenDetailsRequest(token=token))
    if not details.account_ids:
        raise RuntimeError("This secret exposes no accounts")

    account_id = details.account_ids[0]
    account = client.accounts.GetAccount(GetAccountRequest(account_id=account_id))
    print(account)

Asyncio quick start

import asyncio
import os

from trade_api import AsyncTradeAPIClient
from trade_api.auth_messages import TokenDetailsRequest


async def main() -> None:
    async with AsyncTradeAPIClient(secret=os.environ["TRADE_API_SECRET"]) as client:
        token = client.get_token()
        if token is None:
            raise RuntimeError("Authentication did not return a token")

        details = await client.auth.TokenDetails(TokenDetailsRequest(token=token))
        print("Available account IDs:", list(details.account_ids))


asyncio.run(main())

Subscribe to market data

Streaming RPCs return iterators. This synchronous example runs until Ctrl-C; leaving the context manager closes the channel and token-renewal stream:

import os

from trade_api import TradeAPIClient
from trade_api.market_data import SubscribeQuoteRequest


with TradeAPIClient(secret=os.environ["TRADE_API_SECRET"]) as client:
    for tick in client.market_data.SubscribeQuote(
        SubscribeQuoteRequest(symbols=["AAPL@XNAS"])
    ):
        print(tick)

The repository also includes focused examples for authentication and accounts, async quote streaming, and real order placement with cancellation. They live in a standalone consumer project that installs the published package by default.

Available services

The client currently exposes these Trade API services as sub-clients:

Attribute gRPC service What it does
client.auth AuthService Token issuance + details (usually automatic).
client.accounts AccountsService Accounts, positions, trades, transactions.
client.assets AssetsService Instruments, exchanges, schedules, options.
client.market_data MarketDataService Bars, quotes, order book, trade streams.
client.orders OrdersService Place / cancel orders, order + trade streams.
client.reports ReportsService Account reports.
client.metrics UsageMetricsService API usage / quota metrics.

The protobuf contracts also contain CorporateActionsService, but the current Python client does not yet expose it as a sub-client. The Node.js SDK does.

API reference

Every RPC belonging to the services listed below is exposed directly on its sub-client. Request and response message types are re-exported from short, per-service modules:

Module Use with
trade_api.accounts client.accounts.*
trade_api.assets client.assets.*
trade_api.market_data client.market_data.*
trade_api.orders client.orders.* (includes Side)
trade_api.reports client.reports.*
trade_api.metrics client.metrics.*
trade_api.auth_messages client.auth.* (rarely needed — JWT handled automatically)

The original deeply-nested paths (trade_api.proto.grpc.tradeapi.v1.<service>.<service>_service_pb2) still work and remain the source of truth.

Legend: ▶ unary · ⇉ server-stream · ⇄ bidi-stream

client.authAuthService

Method Kind Purpose
Auth(AuthRequest) Exchange API secret for a JWT. Called for you on construction.
TokenDetails(TokenDetailsRequest) Inspect a JWT — expiry, market-data permissions, visible account IDs.
SubscribeJwtRenewal(SubscribeJwtRenewalRequest) Stream of refreshed JWTs. Consumed for you in the background.

client.accountsAccountsService

Method Kind Purpose
GetAccount(GetAccountRequest) Account info: equity, cash, positions, margin.
Trades(TradesRequest) Historical trades for an account.
Transactions(TransactionsRequest) Cash movements and other non-trade transactions.
SubscribeAccount(GetAccountRequest) Streaming account updates.

client.assetsAssetsService

Method Kind Purpose
Exchanges(ExchangesRequest) List of supported exchanges.
Assets(AssetsRequest) Tradable instruments (filtered).
AllAssets(AllAssetsRequest) Full instrument catalog.
GetAsset(GetAssetRequest) Single instrument by symbol.
GetAssetParams(GetAssetParamsRequest) Trading parameters for an instrument.
OptionsChain(OptionsChainRequest) Options chain for an underlying.
Schedule(ScheduleRequest) Trading session schedule.
Clock(ClockRequest) Server clock (use for time-aligned operations).
GetConstituents(GetConstituentsRequest) Index constituents.

client.market_dataMarketDataService

Method Kind Purpose
Bars(BarsRequest) OHLC candles (any timeframe via TimeFrame enum).
LastQuote(QuoteRequest) Most recent quote snapshot.
OrderBook(OrderBookRequest) Order book snapshot.
LatestTrades(LatestTradesRequest) Most recent trades for a symbol.
SubscribeQuote(SubscribeQuoteRequest) Live quote stream.
SubscribeOrderBook(SubscribeOrderBookRequest) Live order-book updates.
SubscribeLatestTrades(SubscribeLatestTradesRequest) Live trades stream.
SubscribeBars(SubscribeBarsRequest) Live candle stream.

client.ordersOrdersService

Method Kind Purpose
PlaceOrder(Order) Place market / limit / stop / stop-limit / multi-leg order.
PlaceSLTPOrder(SLTPOrder) Place an SL/TP (stop-loss + take-profit) order.
CancelOrder(CancelOrderRequest) Cancel an active order.
GetOrders(OrdersRequest) List active orders for an account.
GetOrder(GetOrderRequest) Single order by ID.
SubscribeOrders(SubscribeOrdersRequest) Live order-state updates.
SubscribeTrades(SubscribeTradesRequest) Live execution / fill stream.
SubscribeOrderTrade(stream OrderTradeRequest) Bidi stream — order + trade events, request-driven.

client.reportsReportsService

Method Kind Purpose
CreateAccountReport(CreateAccountReportRequest) Generate an account report (async — returns a job handle).
GetAccountReportInfo(GetAccountReportInfoRequest) Poll report status.
SubscribeAccountReportInfo(SubscribeAccountReportInfoRequest) Stream report status updates instead of polling.

client.metricsUsageMetricsService

Method Kind Purpose
GetUsageMetrics(GetUsageMetricsRequest) API usage / quota stats for the current token.

Client lifecycle

Operation Sync Async
Construct TradeAPIClient(secret, *, endpoint=DEFAULT_ENDPOINT, retry_policy=DEFAULT_POLICY, channel_options=None) AsyncTradeAPIClient(secret, ...) — same args
Start immediate, blocks for initial JWT await client.start() — or use async with
Current JWT client.get_token()str | None client.get_token()str | None (sync read of cached snapshot)
Close client.close() await client.close()
Context manager with TradeAPIClient(...) as client: async with AsyncTradeAPIClient(...) as client:
Testing (no TLS) TradeAPIClient.for_testing(secret, endpoint="localhost:50051") AsyncTradeAPIClient.for_testing(secret, endpoint="localhost:50051")

for_testing(...) opens an insecure (plaintext) channel against an in-process fake server. Never use against api.limeint.eu — it sends your JWT in clear.

Error handling

SDK calls raise raw grpc.RpcError instances. Use from_rpc_error() when your application benefits from the SDK's typed TradeAPIError hierarchy:

import grpc
from trade_api import TradeAPIClient, RateLimitError, from_rpc_error

with TradeAPIClient(secret="...") as client:
    try:
        client.accounts.GetAccount(GetAccountRequest(account_id="A12345"))
    except grpc.RpcError as raw:
        err = from_rpc_error(raw)
        if isinstance(err, RateLimitError):
            ...
        raise err

Exception classes: AuthError (401), PermissionDeniedError (403), InvalidArgumentError (400), NotFoundError (404), RateLimitError (429), InternalError (500), ServiceUnavailableError (503), DeadlineExceededError (504). All inherit from TradeAPIError.

Retries

Unary RPCs retry UNAVAILABLE automatically with exponential backoff and jitter. RESOURCE_EXHAUSTED is retried only when the server supplies grpc-retry-pushback-ms; otherwise the SDK returns the rate-limit error instead of amplifying the throttle. Streaming RPCs are not retried — the caller is expected to reconnect at a meaningful boundary, such as the last received bar.

Override the policy:

from trade_api import TradeAPIClient, RetryPolicy

policy = RetryPolicy(max_attempts=6, initial_backoff=0.5, max_backoff=10.0)
client = TradeAPIClient(secret="...", retry_policy=policy)

Local build

From the repository root:

cd sdk/python
uv sync --locked
uv run ./scripts/generate_proto.sh
uv run ruff check trade_api tests
uv run mypy trade_api
uv run pytest

scripts/generate_proto.sh compiles the .proto files in ../../proto/ into trade_api/proto/. Re-run it whenever the protos change.

Layout

sdk/python/
├── pyproject.toml
├── uv.lock
├── README.md
├── LICENSE
├── scripts/
│   └── generate_proto.sh      # protoc invocation (contributors only)
└── trade_api/
    ├── __init__.py
    ├── client.py               # TradeAPIClient (sync)
    ├── aio.py                  # AsyncTradeAPIClient
    ├── auth.py                 # JWT lifecycle
    ├── retry.py                # retry policy + interceptors
    ├── exceptions.py           # typed errors
    ├── _insecure_auth.py       # plaintext test-channel authentication
    ├── _metadata.py            # Authorization header plumbing
    ├── _services.py            # lazy generated-service registry
    ├── accounts.py             # message re-exports (per-service)
    ├── assets.py
    ├── auth_messages.py
    ├── market_data.py
    ├── orders.py
    ├── reports.py
    ├── metrics.py
    └── proto/                  # generated by CI; ships in wheel and sdist

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

limeint_sdk-2.18.2.tar.gz (114.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

limeint_sdk-2.18.2-py3-none-any.whl (135.4 kB view details)

Uploaded Python 3

File details

Details for the file limeint_sdk-2.18.2.tar.gz.

File metadata

  • Download URL: limeint_sdk-2.18.2.tar.gz
  • Upload date:
  • Size: 114.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for limeint_sdk-2.18.2.tar.gz
Algorithm Hash digest
SHA256 d18e62479feaa3b1a69dfc51549e8236173981e4a5656e2a272496e218f5a69b
MD5 6b04fb3699de2449da672e34fd4b558e
BLAKE2b-256 78798bcaa9cec6639eda6a2dca40575e8d639aa6c93ebeee002484b64203b559

See more details on using hashes here.

Provenance

The following attestation bundles were made for limeint_sdk-2.18.2.tar.gz:

Publisher: publish_python.yml on limeint/tradingapi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file limeint_sdk-2.18.2-py3-none-any.whl.

File metadata

  • Download URL: limeint_sdk-2.18.2-py3-none-any.whl
  • Upload date:
  • Size: 135.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for limeint_sdk-2.18.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b3eb42ca99d9960d937549056c66e8e5c120bd547cabbdda6628e9a71c83c901
MD5 fae6b20dc803ff92fa96bbf071f8ca1e
BLAKE2b-256 14662562f08e0a4a1215ea3edb5c3bf05aae30db58812787691d9a475b8cbb0a

See more details on using hashes here.

Provenance

The following attestation bundles were made for limeint_sdk-2.18.2-py3-none-any.whl:

Publisher: publish_python.yml on limeint/tradingapi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

2.19.1

2 files

2.19.0

2 files

This release

2.18.2 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page