Important: This is the latest version. Information about older versions can be found here.
The v3 C# SDK is a universal SDK that provides access to LUSID and to all the other applications in the FINBOURNE platform from a single package in .NET 8+ environments.
You no longer need to install and authenticate to separate SDKs to integrate LUSID with applications such as Drive, Workflow Service, Luminesce and so on.
Installation
To get started, install the universal SDK from NuGet:
dotnet add package Finbourne.SdkNote the following:
.NET 8 or later is required.
We recommend pinning the SDK to an exact version to control when you take updates and make your builds repeatable. Note this is a new package, so the version number starts at
0.0.1.Alternatively, you can download the source by cloning the Github repo. If you do, note the
mainbranch may not always correspond to the latest REST API version.
Using directives
Add using directives for the API factory and endpoints and models for all the FINBOURNE applications you intend to use, for example:
// General:
using Finbourne.Sdk.Extensions; // Required for API factory
using Finbourne.Sdk.Client; // For error handling
// To use LUSID:
using Finbourne.Sdk.Services.Lusid.Api; // Endpoints
using Finbourne.Sdk.Services.Lusid.Model; // Models
// To use the Workflow Service:
using Finbourne.Sdk.Services.Workflow.Api; // Endpoints
using Finbourne.Sdk.Services.Workflow.Model; // ModelsAuthentication
The most secure method is OAuth2. If you haven’t already, create a SDK application encapsulating a client ID, secret and token URL, and store them with the credentials of a valid LUSID user as either environment variables or in a secrets file. The SDK uses these credentials to obtain a short-lived access token from FINBOURNE's identity provider (Okta) on demand, which it can then refresh periodically.
Note: If environment variables are set, they are preferred over a secrets file. More information.
You can use a long-lived personal access token (PAT) instead of OAuth2, but note this is less secure.
Using environment variables
All applications share a FBN_BASE_URL pointing to the root of your LUSID domain, for example acme-prod.lusid.com:
# OAuth2 (more secure):
setx FBN_BASE_URL "https://acme-prod.lusid.com" # Root of your FBN domain
setx FBN_TOKEN_URL "https://acme-prod.identity.lusid.com/oauth2/.../v1/token" # Okta token endpoint
setx FBN_USERNAME "..."
setx FBN_PASSWORD "..."
setx FBN_CLIENT_ID "..."
setx FBN_CLIENT_SECRET "..."
# PAT:
setx FBN_BASE_URL "https://acme-prod.lusid.com"
setx FBN_ACCESS_TOKEN "..."Using a secrets file
A secrets file is a JSON document with profiles, one per LUSID domain you wish to connect to. Note the file must have at least one default profile. You can switch between profiles to connect to different domains dynamically.
The following example has two profiles: default connects to an acme-prod.lusid.com domain (authenticating using OAuth2) and a second staging profile connects to an acme-sit.lusid.com domain (authenticating using a PAT):
{
"profiles": {
"default": {
"baseUrl": "https://acme-prod.lusid.com/",
"tokenUrl": "https://acme-prod.identity.lusid.com/oauth2/.../v1/token",
"username": "...",
"password": "...",
"clientId": "...",
"clientSecret": "..."
},
"staging": {
"baseUrl": "https://acme-sit.lusid.com",
"accessToken": "..."
}
}
}The active profile is determined in the following order:
The
FBN_PROFILEenvironment variable, if set.The
profile_nameparameter when you instantiate the SDK, if specified (see below).The
defaultprofile.
Instantiation
Build an API factory using ApiFactoryBuilder(). A single API factory instance is thread-safe and can be shared across your application.
If you are using environment variables you can call Build() with no arguments. If using a secrets file:
You must pass the path to
Build().You can optionally pass the name of a profile to connect to a particular LUSID domain dynamically. More configuration options
Synchronous SDK
string secretsFile = "/path/to/secrets.json";
string profile = "staging";
IApiFactory apiFactory = new ApiFactoryBuilder().Build(
apiSecretsFilename: secretsFile,
profileName: profile
);
// Get API instances for the applications you intend to use:
var instrumentsApi = apiFactory.Api<InstrumentsApi>();
var taskDefinitionsApi = apiFactory.Api<TaskDefinitionsApi>();
// Call methods:
var listInstrResponse = instrumentsApi.ListInstruments();Asynchronous SDK
The SDK has full asynchronous support. Call *Async method variants with await, so for example ListInstrumentsAsync() instead of ListInstruments():
string secretsFile = "/path/to/secrets.json";
IApiFactory apiFactory = new ApiFactoryBuilder().Build(apiSecretsFilename: secretsFile);
// Get API instances for the applications you intend to use:
var instrumentsApi = apiFactory.Api<InstrumentsApi>();
var taskDefinitionsApi = apiFactory.Api<TaskDefinitionsApi>();
// Call methods:
var listInstrResponse = await instrumentsApi.ListInstrumentsAsync();Configuration
You can optionally configure timeout and rate limit retry settings using ConfigurationOptions, either globally or as overrides per API call:
// Set globally:
var myOptions = new ConfigurationOptions
{
TimeoutMs = 9999, // Default is 1800000 (30 minutes)
RateLimitRetries = 50 // Default is 2
};
IApiFactory apiFactory = new ApiFactoryBuilder().Build(opts: myOptions);
// Overrides per API call:
var myOption = new ConfigurationOptions { TimeoutMs = 8888 };
var listInstrResponse = instrumentsApi.ListInstruments(opts: myOption);Note you can also set these as environment variables, but ConfigurationOptions is preferred if you do both.
Hello world
The following example authenticates to the synchronous SDK using environment variables and calls the ListInstruments() method to invoke the ListInstruments API, writing certain fields to the command line:
using Finbourne.Sdk.Extensions;
using Finbourne.Sdk.Client;
using Finbourne.Sdk.Services.Lusid.Api;
// Instantiate:
IApiFactory apiFactory = new ApiFactoryBuilder().Build();
// Build Instruments API and list first five instruments:
try
{
var instrumentsApi = apiFactory.Api<InstrumentsApi>();
var listInstrResponse = instrumentsApi.ListInstruments(limit: 5);
foreach (var instrument in listInstrResponse.Values)
{
Console.WriteLine($"LUID: {instrument.LusidInstrumentId}");
Console.WriteLine($"Name: {instrument.Name}");
Console.WriteLine($"Asset Class: {instrument.AssetClass}");
Console.WriteLine("---");
}
}
catch (ApiException e)
{
Console.WriteLine(e);
}
For more information on FINBOURNE APIs, start with the articles in this KB, our API sandbox, and library of Jupyter Notebooks.
Appendix A: Migration checklist
If you are upgrading from v2:
If using environment variables, replace per-application variables such as
FBN_LUSID_API_URLandFBN_WORKFLOW_API_URLwithFBN_BASE_URL, and point to the root of your domain (without an/apisuffix).If using a secrets file, make sure the JSON document matches the new profile specification. Also replace per-application keys such as
lusidUrlandworkflowUrlwithbaseUrl, and point to the root of your domain (without an/apisuffix).Replace all per-application packages (for example
Lusid.Sdk,Finbourne.Workflow.Sdk) with the singleFinbourne.Sdkpackage.Update all
usingdirectives to theFinbourne.Sdk.*namespace.
Appendix B: Environment variable reference
| Root of the LUSID domain to connect to |
| Okta token URL for OAuth2 flow |
| LUSID user name for OAuth2 flow |
| LUSID user password for OAuth2 flow |
| Client ID for OAuth2 flow |
| Client secret for OAuth2 flow |
| Personal access token (less secure than OAuth2) |
| Application name header |
| Sets the active profile in a |
| Timeout configuration option |
| Rate limit retries configuration option |