Skip to main content
The first release of stx-python authenticates with account email and password, exchanging them for a short-lived JWT. API-key / signed-request auth is not yet supported — until it lands, use a dedicated account for production bots and don’t share your personal credentials.

How it works

  1. The first authenticated call triggers a login mutation: email + password in, JWT out.
  2. The JWT is cached on the User singleton — shared across STX, AsyncSTX, and STXWebSocket in the same process.
  3. Every subsequent call attaches Authorization: Bearer <jwt>.
  4. JWTs are valid for 60 minutes. The SDK preemptively refreshes at minute 59 via the newToken mutation. You do not have to handle expiry.

Where credentials come from

The SDK resolves credentials with this precedence (highest wins):
1

Keyword arguments

STX(region="ontario", env="staging",
    email="you@example.com", password="...")
Explicit, highest precedence. Useful in tests and scripts. Don’t hard-code passwords in production code.
2

Environment variables

export STX_EMAIL="you@example.com"
export STX_PASSWORD="your-password"
STX(region="ontario", env="staging")   # picks up env vars
Recommended for CI and containers.
3

Profile file

~/.stx/credentials — AWS-CLI-style INI format:
[default]
email = you@example.com
password = your-password

[prod-bot]
email = bot@example.com
password = bot-password
STX(region="ontario", env="staging")                 # uses [default]
STX(region="ontario", env="production", profile="prod-bot")
Recommended for local development.
4

Defaults

No defaults — if none of the above provide credentials, the SDK raises STXAuthenticationFailedException on the first authenticated call.

Two-factor authentication

If the account has 2FA enabled, the first call raises STXTwoFactorRequiredException. Catch it, collect the code that arrived via email, and call confirm2Fa:
from stx import STX
from stx.exceptions import STXTwoFactorRequiredException

client = STX(region="ontario", env="staging",
             email="you@example.com", password="...")

try:
    client.marketInfos()
except STXTwoFactorRequiredException:
    code = input("2FA code from email: ")
    client.confirm2Fa(params={"code": code})
    client.marketInfos()   # now works
The 2FA session_id is cached on the User singleton alongside the JWT, so subsequent calls in the same process don’t re-prompt.
For headless bots, use a service account without 2FA enabled. The 2FA flow is interactive by design.

Token lifetime

Value
Server-declared JWT lifetime60 minutes
SDK-side refresh trigger59 minutes
Refresh mutationnewToken
Shared across clients?Yes — same process, same singleton
You can force a fresh token (for example, if the user’s password was rotated externally):
from stx.user import User

User().clear()               # drops cached JWT + session
client.marketInfos()         # next call re-authenticates

Sharing auth across clients

The User singleton means one login covers all three clients:
from stx import STX, AsyncSTX, STXWebSocket

# Logs in once — JWT is cached on the singleton.
sync_client = STX(region="ontario", env="staging",
                  email="you@example.com", password="...")
sync_client.marketInfos()

# These re-use the cached JWT — no second login.
async_client = AsyncSTX(region="ontario", env="staging")
ws_client    = STXWebSocket(region="ontario", env="staging")

Troubleshooting

The server rejected your credentials. Check:
  • Is STX_EMAIL / STX_PASSWORD pointing at the right env? (staging vs production accounts are distinct.)
  • Did you recently rotate the password?
  • Try logging in through the web app with the same credentials.
The 2FA session_id isn’t being cached between script invocations. The singleton is process-scoped — if you’re running a fresh Python process each time, 2FA will prompt every time. Use a service account without 2FA for CI/bots.
Make sure the env vars are named exactly STX_EMAIL and STX_PASSWORD (not STX_USERNAME or similar). Check with echo $STX_EMAIL in the same shell you’re running Python from.
This should be rare — the SDK refreshes at 59 minutes automatically. If you see it, it usually means the newToken refresh itself failed (for example, the account was disabled, or the server was momentarily unreachable). The next call will attempt a fresh login.

Security best practices

  1. Never commit credentials to git. Use env vars or a profile file in ~/.stx/, both .gitignore’d by convention.
  2. Rotate on compromise. Log in to the web app and change the password — the SDK will re-authenticate on the next call.
  3. Use a dedicated account for bots. Don’t share your personal login with automation.
  4. Set file permissions on ~/.stx/credentials. Chmod to 600:
    chmod 600 ~/.stx/credentials
    
  5. Prefer staging during development. env="production" touches real balances.

Next

Configuration

Regions, environments, and profile files in detail.

Errors & retries

The full exception hierarchy and retry policy.