Configuration
One call wires up every service, channel, and background worker the SDK provides.
Register services
Section titled “Register services”Name the environment and supply credentials. You do not need to know any URLs:
using STX.Sdk;using STX.Sdk.Auth;using STX.Sdk.Settings;using Microsoft.Extensions.DependencyInjection;
services.ConfigureSTXServices( STXEnvironment.OntarioDemo, STXApiKeyCredentials.FromPemFile(keyId, "~/.stx/ontario.pem"));The same overload exists without credentials, for email and password:
services.ConfigureSTXServices(STXEnvironment.OntarioDemo);ConfigureSTXServices adds:
- GraphQL HTTP client + typed services (
STXLoginService,STXMarketService,STXOrderService, …) - Phoenix channel classes + wrappers (
STXPortfolioChannel,STXActiveOrdersChannel, …) - User storage (
STXUserStorage) as a singleton - Two hosted background services (
STXSessionBackgroundService,STXGeoLocationBackgroundService) that the hosting framework starts automatically
Named environments
Section titled “Named environments”| Jurisdiction | Real money | |
|---|---|---|
STXEnvironment.OntarioDemo |
Ontario | No |
STXEnvironment.OntarioProduction |
Ontario | Yes |
STXEnvironment.USDemo |
United States | No |
Each one carries both the GraphQL endpoint and the WebSocket endpoint, so there is nothing to assemble by hand and no {0} placeholder to remember. Demo environments are shared by every integrator, so their order books carry real activity.
Anything else
Section titled “Anything else”For an endpoint not listed above, supply both URLs yourself:
services.ConfigureSTXServices( STXEnvironment.Custom( graphQLUri: "https://your-host/api/graphql", channelsUri: "wss://your-host/socket/websocket?token={0}&vsn=2.0.0"), credentials);Select the environment from configuration rather than code, so a deploy can swap it without recompiling:
var environment = builder.Configuration["STX:Environment"] switch{ "ontario-production" => STXEnvironment.OntarioProduction, "ontario-demo" => STXEnvironment.OntarioDemo, "us-demo" => STXEnvironment.USDemo, _ => throw new InvalidOperationException("Set STX:Environment")};
services.ConfigureSTXServices(environment, credentials);Supplying URLs directly
Section titled “Supplying URLs directly”The original overload still works and is unchanged:
services.ConfigureSTXServices( _ => builder.Configuration["STX:GraphQLUri"]!, _ => builder.Configuration["STX:ChannelsUri"]!);appsettings.json:
{ "STX": { "GraphQLUri": "https://demo.stxapp.ca/api/graphql", "ChannelsUri": "wss://demo.stxapp.ca/socket/websocket?token={0}&vsn=2.0.0" }}Override per environment with appsettings.Production.json or env vars (STX__GraphQLUri=…).
Dynamic endpoint resolution
Section titled “Dynamic endpoint resolution”If the endpoints depend on something inside DI (a tenant selector, feature flag, etc.), the overload that takes Func<IServiceProvider, string> gives you a callback:
services.ConfigureSTXServices( getGraphQLUri: sp => sp.GetRequiredService<IMyEnvResolver>().GraphQLUri, getChannelsUri: sp => sp.GetRequiredService<IMyEnvResolver>().ChannelsUri);Resolving services
Section titled “Resolving services”Register once, resolve anywhere:
public class OrderPlacer{ private readonly STXOrderService _orders; private readonly STXMarketService _markets;
public OrderPlacer(STXOrderService orders, STXMarketService markets) { _orders = orders; _markets = markets; }
public async Task PlaceAsync() { /* ... */ }}Services are registered as Transient, so they are safe to resolve per operation. Channel classes are Singleton so state (the active websocket, subscribed topics) is shared across the app.
Logging
Section titled “Logging”The SDK uses Microsoft.Extensions.Logging. Hook up the provider you prefer:
services.AddLogging(builder => builder .SetMinimumLevel(LogLevel.Information) .AddConsole());The SDK logs at Debug for every GraphQL request/response body, Information for connection lifecycle, and Warning/Error for transient + fatal issues.
GeoComply / GeoLocation
Section titled “GeoComply / GeoLocation”ConfigureSTXServices registers STX.GeoComply and STX.GeoLocation internally. For trading bots running server-side, the default behavior is usually what you want: the geolocation token is fetched lazily and cached. If you’re embedding the SDK in a client app (desktop, mobile), integrate with GeoComply’s SDK per their docs.

