# What you can do

> Every capability of the STX API mapped to stx-python calls, which exchanges offer it, and what happens where one does not.

Source: https://docs.stxapp.io/sdks/python/capabilities/

The same SDK release works against every STX exchange. Exchanges do not all offer the same features yet, so the SDK asks each one what it has, and a call that needs a missing feature raises `STXNotAvailableError` instead of an obscure HTTP error. Nothing else on the client changes.

## Every capability, and the calls for it

| You want to | Calls | Feature |
|---|---|---|
| Read markets and events | `markets()`, `iter_markets()`, `market()`, `events()`, `iter_events()` | always |
| Place, cancel and read orders | `place_order()`, `place_orders()`, `cancel_order()`, `cancel_orders()`, `cancel_all_orders()`, `orders()`, `order()` | always |
| Read your account | `me()`, `balance()`, `positions()`, `fills()`, `settlements()`, `deposits()`, `withdrawals()`, `fees()`, `account_market_stats()` | always |
| Stream market data | `ws.orderbook()`, `ws.ticker()`, `ws.trades()`, `ws.markets()`, `ws.market_stats()`, `ws.market_updates()`, `ws.market()` | always |
| Stream your account | `ws.orders()`, `ws.fills()`, `ws.positions()`, `ws.balances()`, `ws.settlements()`, `ws.account_view()` | always |
| Combos (player and maker) | `ws.rfq()`, `ws.combo_quote()`. See [Combos](/sdks/python/combos/) | `combos` |
| Connect members to your app | `oauth.OAuthClient.discover()`, `begin_authorization()`, `complete_authorization()`, `member_client()`, `unlink()`. See [Apps: connect members](/sdks/python/apps/) | `oauth.member` |
| Act as your app (catalog and market data) | `app_client()`, `client_credentials()`. See [App tokens and market data](/sdks/python/app-tokens/) | `oauth.app` |
| Sign members in with STX | `oauth.Connect`: `start()`, `finish()`. See [Sign in with STX](/sdks/python/sign-in-with-stx/) | `connect` |
| Send members to accept new terms on STX | `STXTermsRequiredException.terms_url`, `oauth.terms_url_with_return()` | `terms.stx_page` |
| Create markets | `create_markets()` with an app token. See [Create markets](/sdks/python/create-markets/) | `markets.create` |
| List market types | `market_types()` | `market_types` |
| Read an event's players and stats | `event_players()`, `stats_for()` | `event_players` |
| Leaderboard and public profile | `leaderboard()`, `leaderboard_me()`, `update_profile()` | `leaderboard` |

## Which exchange offers what

Probed with `capabilities()` on 20 October 2026. Use the call yourself for the exchange you are on: exchanges gain features with each release.

| Feature | US demo | Ontario demo | Ontario production |
|---|---|---|---|
| `oauth` | yes | no | no |
| `oauth.member` | yes | no | no |
| `oauth.app` | yes | no | no |
| `connect` | yes | no | no |
| `terms.stx_page` | yes | no | no |
| `markets.create` | yes | no | no |
| `market_types` | yes | no | no |
| `event_players` | yes | yes | yes |
| `leaderboard` | yes | no | no |

US demo was on API version 3.3.196, Ontario demo and production on 3.3.186. In Ontario an app will read public market data only and will not act for members.

## Ask an exchange

```python
from stx import STX

with STX(region="ontario", env="demo") as client:
    caps = client.capabilities()
    print(caps.host, caps.api_version)
    for feature in caps.features.values():
        print(f"{feature.id:15} {str(feature.available):5}  {feature.how}")
```

Sample output:

```text
demo.stxapp.ca 3.3.194-5
oauth           False  authorization-server metadata answers 404
oauth.member    False  no OAuth on this exchange
oauth.app       False  no OAuth on this exchange
connect         False  no OAuth on this exchange
terms.stx_page  False  no OAuth on this exchange
markets.create  False  no OAuth on this exchange
market_types    False  GET /api/v1/types answers 404 not_found
event_players   True   GET /api/v1/events/00000000-0000-0000-0000-000000000000/players answers 404 'event not found' (route exists)
leaderboard     False  GET /api/v1/leaderboard?limit=1 answers 404 'Leaderboard is not enabled'
combos          True   rfq join answered 'unauthorized' (the channel exists)
```

`capabilities()` changes nothing on the exchange: it reads the discovery documents, makes `GET` requests a missing route answers with a 404, and joins one channel that is refused at once. The answer is cached on the client; `capabilities(refresh=True)` asks again and `probe_channels=False` skips the socket. On `AsyncSTX` it is `await client.capabilities()`.

`caps.available("combos")` is True only when the exchange showed it has the feature; `caps.require("combos")` raises `STXNotAvailableError` when it is known to be absent; `caps.to_dict()` gives `{feature: True | False | None}`. `None` means it could not be decided, for example the authenticated probes on a client with no credentials, or `market_types` with an app token that lacks the `events` scope.

| Feature | Available when |
|---|---|
| `oauth` | `/.well-known/oauth-authorization-server` answers with the metadata document |
| `oauth.member` | the document offers the `authorization_code` grant and a member scope |
| `oauth.app` | the document offers the `client_credentials` grant |
| `connect` | the document lists the `openid` scope |
| `terms.stx_page` | members can connect and `terms.write` is no longer a scope |
| `markets.create` | app tokens are offered and the document lists `markets.write` |
| `market_types` | `GET /api/v1/types` answers |
| `event_players` | `GET /api/v1/events/{event_id}/players` exists |
| `leaderboard` | `GET /api/v1/leaderboard` answers |
| `combos` | the `rfq` channel exists |

## What not available looks like

`STXNotAvailableError` has `feature` (the id above), `host` and a message naming both. Captured on Ontario demo:

```python
import stx
from stx import STX, PlayerStatLine, oauth

with STX(region="ontario", env="demo") as client:
    try:
        client.market_types()
    except stx.STXNotAvailableError as exc:
        print(f"{type(exc).__name__}: {exc}  feature={exc.feature!r} host={exc.host!r}")
```

```text
STXNotAvailableError: Market types are not available on demo.stxapp.ca yet.  feature='market_types' host='demo.stxapp.ca'
```

The other calls on the same exchange:

```text
create_markets: STXNotAvailableError: Creating markets is not available on demo.stxapp.ca yet.  feature='markets.create' host='demo.stxapp.ca'
leaderboard: STXNotAvailableError: The leaderboard is not available on demo.stxapp.ca yet.  feature='leaderboard' host='demo.stxapp.ca'
OAuthClient.discover: STXNotAvailableError: OAuth is not available on demo.stxapp.ca yet.  feature='oauth' host='demo.stxapp.ca'
```

`STXCombosUnavailableException` is an `STXNotAvailableError` as well as an `STXChannelException`, so existing handlers keep working. A scope an exchange does not offer is reported the same way, with `feature` `scope:<name>`, for example `The orders.write scope is not available on demo.stxapp.ca yet.` Every not-available error derives from `STXException`; see [Errors & retries](/sdks/python/errors-and-retries/).
