uex-lib
Python client for the UEX Corp API with TTL caching and pluggable HTTP transports
Installation
uv add uex-lib # or: pip install uex-lib
The base package has no third-party dependencies. The sync client uses the standard library, and the async client needs one of:
uv add "uex-lib[httpx]"
uv add "uex-lib[aiohttp]"
Requires Python 3.11 or newer.
Usage
import asyncio
from uex import AsyncClient
async def main():
async with AsyncClient() as uex:
prices = await uex.commodities.prices(id_terminal=1)
for price in prices:
print(price.commodity_name, price.price_sell)
route = await uex.commodities.routes(id_commodity=1)
vehicles = await uex.vehicles.list(id_company=195)
asyncio.run(main())
The sync client has the same surface:
from uex import Client
with Client() as uex:
versions = uex.game_versions.current()
for system in uex.universe.star_systems():
print(system.code, system.name)
Endpoints that need an app token or a user secret key raise AuthRequired locally if the credential is missing, rather than making a doomed request:
from uex import Client
with Client(token="app-token", secret_key="user-secret-key") as uex:
balance = uex.user.wallet_balance()
trades = uex.user.trades()
Every list or detail response comes back as one of the typed models under uex.models, keeping the raw payload on .raw so a field the model hasn't caught up to is still reachable.
Caching
The client caches every public GET response. Freshness comes from the API's own Cache-Control: max-age, falling back to a documented TTL per endpoint when the header is missing (30 minutes for most prices, 12 hours for terminals and vehicles, a day for static reference data). Responses behind a user secret key are never cached.
The default store is SQLite in $XDG_CACHE_HOME/uex/ (or %LOCALAPPDATA%\uex\ on Windows), so a bot and a script can share one file. An in-process LRU sits in front of it.
If the API is down or returns a 5xx after retries, an expired entry is served with meta.stale = True.
from uex import Client, MemoryStore, SqliteStore, LruFront
uex = Client() # SQLite + LRU, the default
uex = Client(cache=MemoryStore()) # per-process only
uex = Client(cache=LruFront(SqliteStore("/srv/uex.db")))
uex = Client(cache=None) # no caching at all
uex.commodities.prices(id_terminal=1, fresh=True) # bypass the cache for one call
uex.purge_cache(endpoint="commodities_prices") # drop one endpoint's cache
Bring your own HTTP library
The client never imports an HTTP library. It talks to a transport with one method, send(Request) -> Response, and ships adapters for urllib (default for the sync client), httpx and aiohttp. Pass your own if you already have a configured session:
import aiohttp
from uex import AsyncClient
from uex.transports.aiohttp import AiohttpTransport
session = aiohttp.ClientSession()
uex = AsyncClient(transport=AiohttpTransport(session))
Website links
uex.trade_routes_url() and uex.trade_route_detail_url() build links to the UEX Corp website's trade route finder rather than calling the API, so you can hand a pre-filled search or a specific route to a person:
from uex import trade_routes_url, trade_route_detail_url
trade_routes_url(id_vehicle=147, investment=20_000)
# -> "https://uexcorp.space/trade/routes/?id_vehicle=147&investment=20%2C000"
route = await uex.commodities.routes(id_commodity=1)
trade_route_detail_url(route[0].code)
# -> "https://uexcorp.space/trade/route?code=9db9ca68"
Development
uv sync --all-extras --dev
uv run pytest # offline, fixture-driven
UEX_NETWORK=1 uv run pytest tests/contract # live transport checks
uv run tox # full matrix, lint, types
uv run python scripts/refresh_fixtures.py # re-record fixtures from the live API
Attribution
Data comes from UEX Corp. This is a fan project and is not affiliated with or endorsed by UEX Corp, Cloud Imperium Games, or Star Citizen.
Contributing
Issues and pull requests are welcome at Garulf/uex-lib.
License
MIT
Metadata
Release files for uex-lib 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| uex_lib-0.1.0.tar.gz | 149.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| uex_lib-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 190.3 kB
Release files / uex_lib-0.1.0.tar.gz
| Download URL | uex_lib-0.1.0.tar.gz |
|---|---|
| Size | 149.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f25df6f20033ad3a25c5889c8f45e8f926f6efa78955fd43f5a26ea01c70e604
|
|
BLAKE2b-256 checksum How to use checksums |
3d39f69bf34584c8ef8f74c17c5ebc76c198b6582a3545e9da4dbb89798662e1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency logRelease files / uex_lib-0.1.0-py3-none-any.whl
| Download URL | uex_lib-0.1.0-py3-none-any.whl |
|---|---|
| Size | 40.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a08b4829cb5fe8bb4039797206f3f2e2d68b959a3bf268dd13283b2938b3f6e7
|
|
BLAKE2b-256 checksum How to use checksums |
30e46bebabcc57db5141ba03031f67723ad62deb6a6cc1454908a5740d67530e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency log