All authenticated endpoints require a JWT. STX.Sdk acquires, caches, and refreshes the token for you — in most apps you call LoginAsync once at startup and never touch the token directly. The sections below cover the cases where you need more control.
Simple login
using STX.Sdk.Services;
var login = serviceProvider.GetRequiredService<STXLoginService>();
var user = await login.LoginAsync(
email: "you@example.com",
password: "your-password");
Console.WriteLine($"Logged in as {user.UserId}");
LoginAsync returns an STXUserDataCollection with the following fields:
| Field | Description |
|---|
Token | Bearer token attached to every subsequent GraphQL call |
RefreshToken | Used by STXTokenService.RefreshTokenAsync |
UserId, UserUid, SessionId | Identifiers used by WebSocket channel subscriptions |
CurrentLoginAt | Timestamp of the login event |
PromptTncAcceptance | true when the user still needs to accept updated T&Cs |
The token is automatically cached in STXUserStorage and attached to every subsequent GraphQL call. You never need to pass it manually.
Two-factor authentication
If the account has 2FA enabled, the initial LoginAsync call returns partial user data. Authentication is not complete until you confirm the one-time code:
var partial = await login.LoginAsync(email, password);
if (partial.PromptTwoFactor)
{
Console.Write("2FA code: ");
var code = Console.ReadLine();
var tokenService = serviceProvider.GetRequiredService<STXTokenService>();
var confirmed = await tokenService.Confirm2FAAsync(
code: code!,
sessionId: partial.SessionId,
email: email);
Console.WriteLine($"Authenticated: {confirmed.UserId}");
}
The 2FA flow calls the same confirm2Fa GraphQL mutation used by other SportsX SDK clients.
Keep the session alive
Long-running bots should refresh the JWT before it expires. Pass keepSessionAlive: true and the SDK’s STXSessionBackgroundService handles refresh in the background:
await login.LoginAsync(
email,
password,
keepSessionAlive: true);
Two requirements apply:
- The service provider must be hosted under
Host.CreateDefaultBuilder so background services actually run.
- Credentials stay in memory in
STXUserStorage so the background service can re-login if the refresh token itself expires.
Manual token refresh
If you prefer explicit control over refresh timing — for example in a minimal script that doesn’t run under a full host — wrap your trading calls like this:
async Task<T> WithSession<T>(Func<Task<T>> call)
{
try { return await call(); }
catch (STXTokenExpiredException)
{
await _tokens.RefreshTokenAsync();
return await call();
}
catch (STXSessionExpiredException)
{
await _login.LoginAsync(_email, _password);
return await call();
}
}
Accept terms and conditions
If PromptTncAcceptance is true after login, subsequent authenticated calls will fail until the user accepts the latest terms. Pass checkTermsAndConditions: true to surface the T&Cs text for display:
await login.LoginAsync(
email,
password,
checkTermsAndConditions: true);
Once the user has explicitly agreed in your UI, record their acceptance:
var tnc = serviceProvider.GetRequiredService<STXTermsAndConditionsService>();
var latest = await tnc.GetTermsAndConditionsAsync();
await tnc.AcceptTermsAndConditionsAsync(latest.Version);
Only call AcceptTermsAndConditionsAsync after the user has read and agreed to the terms in your UI. Accepting on their behalf without consent may violate applicable regulations.
Logout
There is no server-side logout call. To end the session, clear the stored token:
var storage = serviceProvider.GetRequiredService<STXUserStorage>();
storage.Clear();
This also stops any active background services and closes WebSocket channels on their next tick.
Authentication errors
| Exception | Cause | Recovery |
|---|
STXWrongCredentialsException | Email or password rejected | Prompt the user for fresh credentials |
STXTokenExpiredException | JWT expired; refresh token still valid | Call STXTokenService.RefreshTokenAsync |
STXSessionExpiredException | Both token and refresh token expired | Call STXLoginService.LoginAsync again |
STXGeoComplyException | Geo-compliance check failed | User is outside a permitted jurisdiction — surface to your UI |
See Errors & retries for the full exception list and recovery patterns.