Python client for the StoneX (CIAPI) v2 trading API
Project description
stonepy
Python client for the StoneX (CIAPI) v2 trading API.
📖 Documentation: https://aaronmgn.github.io/stonepy/
Features
- Fully typed. Every request and response is a Pydantic v2
model, and the package ships a
py.typedmarker, so editors autocomplete fields andmypychecks your calls. - Sync and async. Identical APIs on
StoneXClientandAsyncStoneXClient. - Complete coverage. All 72 documented CIAPI endpoints across 14 resource groups, using the v2 variant of every endpoint that has one.
- Batteries included. Automatic session refresh, configurable retries, client-side rate limiting, secret redaction in logs, and a clear exception hierarchy.
Project status:
stonepyis pre-1.0 (alpha). The public API may change between minor releases until 1.0; pin a version for production use.
Installation
pip install stonepy
Or with uv:
uv add stonepy
Requires Python >= 3.11. stonepy ships type information (PEP 561 py.typed), so it works out
of the box with mypy and pyright.
Quickstart
from stonepy import ClientConfig, StoneXClient
from stonepy.models import ApiLogOnRequestDTO
config = ClientConfig(base_url="https://ciapi.cityindex.com/TradingAPI")
with StoneXClient(config) as client:
session = client.session.log_on(
ApiLogOnRequestDTO(
UserName="username",
Password="password",
AppKey="app-key",
AppVersion="stonepy",
AppComments="",
)
)
print(session.status_code)
Environment-based configuration is also available:
from stonepy import ClientConfig, StoneXClient
config = ClientConfig.from_env()
with StoneXClient(config) as client:
print(client.session)
ClientConfig.from_env() reads STONEX_BASE_URL, STONEX_APP_KEY, STONEX_USERNAME,
and STONEX_PASSWORD. STONEX_BASE_URL is required unless base_url= is passed.
Authentication and Sessions
Calling client.session.log_on(...) establishes the authenticated session token that the
client attaches to every subsequent request. The token is held by the client for the life of
its context manager.
If you supply app_key, username, and password on ClientConfig (directly or via
ClientConfig.from_env()), the client also refreshes the session automatically: it
re-authenticates in the background before the token expires, controlled by
ClientConfig.proactive_refresh_seconds (default 1080.0, i.e. 18 minutes), and transparently
re-logs-on if a request is rejected with an expired-session error. Without those credentials you
must call log_on yourself and manage re-authentication.
config = ClientConfig(
base_url="https://ciapi.cityindex.com/TradingAPI",
app_key="app-key",
username="username",
password="password",
) # credentials present -> automatic proactive session refresh
Async Usage
from stonepy import AsyncStoneXClient, ClientConfig
from stonepy.models import ApiLogOnRequestDTO
config = ClientConfig(base_url="https://ciapi.cityindex.com/TradingAPI")
async with AsyncStoneXClient(config) as client:
session = await client.session.log_on(
ApiLogOnRequestDTO(
UserName="username",
Password="password",
AppKey="app-key",
AppVersion="stonepy",
AppComments="",
)
)
print(session.status_code)
Use aclose() for async clients when not using async with; use close() for sync clients.
Error Handling
All library exceptions inherit from StoneXError.
from stonepy import (
ClientConfig,
RateLimitError,
StoneXAPIError,
StoneXClient,
StoneXError,
)
from stonepy.models import ApiLogOnRequestDTO
config = ClientConfig(base_url="https://ciapi.cityindex.com/TradingAPI")
try:
with StoneXClient(config) as client:
client.session.log_on(
ApiLogOnRequestDTO(
UserName="username",
Password="password",
AppKey="app-key",
AppVersion="stonepy",
AppComments="",
)
)
except RateLimitError as exc:
print(exc.retry_after)
except StoneXAPIError as exc:
print(exc.http_status, exc.error_code, exc.error_message)
except StoneXError as exc:
print(exc)
Important subclasses include AuthenticationError, RateLimitError,
OrderRejectedError, ResponseParseError, StoneXAPIError, and TransportError.
Pagination
Paginated API methods return the page DTO documented by StoneX. For example,
client.market.list_market_search_paginated(...) accepts page, page_size, and
order_by keyword arguments and returns ListMarketSearchPaginatedResponseDTO:
page = client.market.list_market_search_paginated(
"gold",
search_by_market_code=False,
search_by_market_name=True,
spread_product_type=True,
cfd_product_type=True,
binary_product_type=False,
ascending_order=True,
include_options=False,
client_account_id=12345,
page=0,
page_size=100,
)
print(page.total_number_of_results)
API Reference
Full documentation - the guides and a complete API reference - is published at https://aaronmgn.github.io/stonepy/.
Development
uv venv
uv sync --extra dev
uv run pytest -q
uv run ruff check .
uv run ruff format --check .
uv run mypy
See CONTRIBUTING.md for the full contributor guide and CODE_OF_CONDUCT.md, and CHANGELOG.md for release notes.
Support
- Questions and bug reports: GitHub issues.
- Security: please report vulnerabilities privately - see SECURITY.md.
AI Use Disclaimer
Portions of this project, including the generated API bindings, DTO models, and documentation, were produced with the assistance of AI tooling and reviewed by a human maintainer. The library is tested against the StoneX CIAPI v2 contract but is provided "as is", without warranty of any kind (see LICENSE).
stonepy is unofficial and is not affiliated with, endorsed by, or supported by StoneX,
City Index, or GAIN Capital. Trading carries financial risk; validate all behaviour against the
official API documentation before using it with a live
account.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file stonepy-0.1.3.tar.gz.
File metadata
- Download URL: stonepy-0.1.3.tar.gz
- Upload date:
- Size: 113.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d475e3ed5eb7d5db6309afeff39f0f2ea5c6d7a66c1583d978ab888764b4a3a
|
|
| MD5 |
2ebc83d444d0d22cab7c960af67636d7
|
|
| BLAKE2b-256 |
d93c0423b4fdffc8c9c786f90a7b7a01e1834c2401670f39e6a439a1c64b37b6
|
Provenance
The following attestation bundles were made for stonepy-0.1.3.tar.gz:
Publisher:
release.yml on aaronmgn/stonepy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
stonepy-0.1.3.tar.gz -
Subject digest:
3d475e3ed5eb7d5db6309afeff39f0f2ea5c6d7a66c1583d978ab888764b4a3a - Sigstore transparency entry: 1986634535
- Sigstore integration time:
-
Permalink:
aaronmgn/stonepy@2e36980dcd413bca7f81cfa0a5e7a436454458b6 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/aaronmgn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2e36980dcd413bca7f81cfa0a5e7a436454458b6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file stonepy-0.1.3-py3-none-any.whl.
File metadata
- Download URL: stonepy-0.1.3-py3-none-any.whl
- Upload date:
- Size: 312.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
43ec79ab37c29301b5d77119ef50650346a5ff3a84241c25051604c0b42831b9
|
|
| MD5 |
953e91ed26b8241a70757de98ea83d0a
|
|
| BLAKE2b-256 |
2d113e249c1df69979aad3dda934d4bb56c6edd78bd4ba5c0689efc7b35129ea
|
Provenance
The following attestation bundles were made for stonepy-0.1.3-py3-none-any.whl:
Publisher:
release.yml on aaronmgn/stonepy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
stonepy-0.1.3-py3-none-any.whl -
Subject digest:
43ec79ab37c29301b5d77119ef50650346a5ff3a84241c25051604c0b42831b9 - Sigstore transparency entry: 1986634614
- Sigstore integration time:
-
Permalink:
aaronmgn/stonepy@2e36980dcd413bca7f81cfa0a5e7a436454458b6 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/aaronmgn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2e36980dcd413bca7f81cfa0a5e7a436454458b6 -
Trigger Event:
push
-
Statement type: