Installing or upgrading to the v3 C# SDK

Prev Next

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.Sdk

Note 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 main branch 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;    // Models

Authentication

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:

  1. The FBN_PROFILE environment variable, if set.

  2. The profile_name parameter when you instantiate the SDK, if specified (see below).

  3. The default profile.

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_URL and FBN_WORKFLOW_API_URL with FBN_BASE_URL, and point to the root of your domain (without an /api suffix).

  • If using a secrets file, make sure the JSON document matches the new profile specification. Also replace per-application keys such as lusidUrl and workflowUrl with baseUrl, and point to the root of your domain (without an /api suffix).

  • Replace all per-application packages (for example Lusid.Sdk, Finbourne.Workflow.Sdk) with the single Finbourne.Sdk package.

  • Update all using directives to the Finbourne.Sdk.* namespace.

Appendix B: Environment variable reference

FBN_BASE_URL

Root of the LUSID domain to connect to

FBN_TOKEN_URL

Okta token URL for OAuth2 flow

FBN_USERNAME

LUSID user name for OAuth2 flow

FBN_PASSWORD

LUSID user password for OAuth2 flow

FBN_CLIENT_ID

Client ID for OAuth2 flow

FBN_CLIENT_SECRET

Client secret for OAuth2 flow

FBN_ACCESS_TOKEN

Personal access token (less secure than OAuth2)

FBN_APP_NAME

Application name header

FBN_PROFILE

Sets the active profile in a secrets.json file

FBN_TIMEOUT_MS

Timeout configuration option

FBN_RATE_LIMIT_RETRIES

Rate limit retries configuration option