This article is about the connection of the Clearstream Digital Instruments API. We will use Visual Studio 2022 Community Edition to implement the basic functions. We will also demonstrate only the actual connection to obtain the Bearer Token as well as a call to the API to determine the stored Instrument Templates. However, all further calls should then be easier to develop with the help of this example.

This example is divided into several sections. First, we will explain the necessary preconditions that are required for successful “tracing”. In the second step we will show the most important code parts that are necessary to obtain the bearer token as well as for the actual API call.

P12 Certificates

Normally, Clearstream provides users of its API with the necessary certificates (PEM), which are required to access the authentication system as well as to call the API. In .NET, we use the P12 format to hold the appropriate certificates.

These certificates normally are bound to real people, so consider keeping them secured.

To get a call off to clearstream, one needs to do the following steps:

  1. Prepare and load the needed certificates from disk for the api calls.
  2. Get the authorization and authentication from clearstream. The result of this will be a bearer token that is returned from clearstream. NOTE: this token will expire after a certain amount of time, so we will have to redo this step once the token will expire.
  3. Make the api call with the bearer token attached in the headers of our api call.
  4. Evaluate the result from the call

We will go now through the steps to achieve this. For implementation we will use C#.

This will be our method to get our bearer token:

        /// <summary>
        /// Get Elibility Token
        /// </summary>
        /// <returns></returns>
        private static async Task<Token> GetElibilityTokenAsync()
        {
            string scopeDi = "allow digital-instruments";
            string username = "myusername";
            string password = "mypass";
            string certPw = "clearstream";

            #region Private Member
            //private static string clearstreamApiEndpointUrl = "https://api.clearstream.com/";
            string clearstreamApiEndpointUrl = "https://api-test.clearstream.com/";
            #endregion

            Token? tok = null;

            // configure endpoint and certificate
            try
            {
                var remoteAddress = $"{clearstreamApiEndpointUrl}authmanager/oauth2/access_token";
                var certFile = @".\Cert\P12\xact-api-credentials-3des.p12";
                X509Certificate2Collection certificates = new();
                certificates.Import(certFile, certPw, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);

                // values to pass on to service
                var values = new Dictionary<string, string>
                        {
                            { "grant_type", "password" },
                            //{ "scope", scope},
                            {"scope", scopeDi },
                            { "username", username},
                            { "password", password},
                        };

                // encode it in url form...
                var data = new FormUrlEncodedContent(values);

                // use modern http client implementation to call endpoint
                using var httpHandler = new HttpClientHandler();

                httpHandler.ClientCertificates.Add(certificates[0]);
                //httpHandler.Proxy = proxy;

                using var client = new HttpClient(httpHandler);
                // handle communiction with API
                var response = await client.PostAsync(remoteAddress, data);

                // get our response content
                var responseContent = await response.Content.ReadAsStringAsync();

                // get our token
                tok = JsonSerializer.Deserialize<Token>(responseContent);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Exception: {ex.Message}.");
            }

            return tok;
        }

Next is the refresh logic. You WILL need this as the bearer token from Clearstream will expire after a define timespan. In such a case you will get an http respone 403 back from the service. In such a case you basically have to renew the token for your service again.

There are multiple strategies thinkable to deal with this:

  • Renew the token shortly before it expires
  • If an http status code 403 comes back from Clearstream, react by renewing the token at this point in time.

I do prefer to renew before the actual expiration, as this approach prevents an unsuccessful web API call (that you will pay with your next Clearstream invoice). But of course you can choose the strategy that fits your needs the most.

        /// <summary>
        /// Get our refresh token
        /// </summary>
        /// <param name="originalToken"></param>
        /// <returns></returns>
        private static async Task<Token?> GetRefreshTokenAsync(Token originalToken)
        {
            string username = "username";
            string certPw = "clearstream";

            #region Private Member
            //private static string clearstreamApiEndpointUrl = "https://api.clearstream.com/";
            string clearstreamApiEndpointUrl = "https://api-test.clearstream.com/";
            #endregion

            Token? tok = null;

            // First create a proxy object
            // only necessary IF you need proxy to get from your network out to the internet
            var proxy = new WebProxy
            {
                Address = new Uri($"http://myproxy:port"),
                BypassProxyOnLocal = false,
                UseDefaultCredentials = false,
                Credentials = CredentialCache.DefaultNetworkCredentials
            };

            // configure endpoint and certificate
            try
            {
                var remoteAddress = $"{clearstreamApiEndpointUrl}authmanager/oauth2/access_token";
                var certFile = @"./Cert/P12/xact-api-credentials-3des.p12";
                X509Certificate2Collection certificates = new X509Certificate2Collection();
                certificates.Import(certFile, certPw, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);

                // values to pass on to service
                var values = new Dictionary<string, string>
                {
                    { "grant_type", "refresh_token" },{"refresh_token",originalToken.refresh_token},
                    { "username", username},
                };

                // encode it in url form...
                var data = new FormUrlEncodedContent(values);

                // use modern http client implementation to call endpoint
                using var httpHandler = new HttpClientHandler();
                httpHandler.ClientCertificates.Add(certificates[0]);
                httpHandler.Proxy = proxy;

                using var client = new HttpClient(httpHandler);
                // handle communiction with API
                var response = await client.PostAsync(remoteAddress, data);

                // get our response content
                var responseContent = await response.Content.ReadAsStringAsync();

                // get our token
                tok = JsonSerializer.Deserialize<Token>(responseContent);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Exception: {ex.Message}.");
            }

            return tok;
        }

What you can see here is that we read in our certificate from a p12 file and import it using the X509 certificate collection’s import method. Alongside our request we pass additional values (that will end up in the form as form encoded one using FormUrlEncodeContent. The additional values basically tell clearstream our username and the token (yet not available at this point)

Yet the next step is to acutally call the service with the token from our previous call:

        /// <summary>
        /// Call the playground API asynchronously
        /// </summary>
        /// <param name="accessToken"></param>
        /// <returns></returns>
        static async Task<string> CallClearstreamPlaygroundApiAsync(Token accessToken)
        {
            if (accessToken == null)
            {
                throw new ArgumentNullException(nameof(accessToken));
            }

            var jsonContent = string.Empty;
            string certPw = "clearstream";

            #region Private Member
            //private static string clearstreamApiEndpointUrl = "https://api.clearstream.com/";
            string clearstreamApiEndpointUrl = "https://api-test.clearstream.com/";
            #endregion

            var remoteAddress = $"{clearstreamApiEndpointUrl}/playground/v1/echo?value=Hello%20World";

            try
            {
                var certFile = @"./Cert/P12/xact-api-credentials-3des.p12";
                X509Certificate2Collection certificates = new X509Certificate2Collection();
                certificates.Import(certFile, certPw, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);

                // values to pass on to service
                var values = new Dictionary<string, string>();

                // use modern http client implementation to call endpoint
                using var httpHandler = new HttpClientHandler();

                httpHandler.ClientCertificates.Add(certificates[0]);
                // httpHandler.Proxy = proxy;

                using var client = new HttpClient(httpHandler);

                // handle additional client header
                client.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken.access_token}");

                // handle communiction with API
                var response = await client.GetAsync(remoteAddress);

                // get our response content
                var responseContent = await response.Content.ReadAsStringAsync();

                jsonContent = responseContent;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Exception: {ex.Message}.");
            }

            return jsonContent;
        }

Please not that is prototype code. Do not simply copy paste it into your codebase and expect everything to work. Especially the certificate code etc. would need optimizations… This code is basically here to tell how to get it to work and provide code snippets to achieve the goal.

Finally the main method that puts it all together. Here we call our pervious code snippets and:

  • Prepare the certificate and load them into memory
  • Get the auth token (bearer token) from the OAuth call to the Clearstream endpoint
  • Call the Clearstream API method
  • Print out the received information from Clearstream
        /// <summary>
        /// Main entry point for 
        /// </summary>
        /// <param name="args"></param>
        static async Task Main(string[] args)
        {
            try
            {
                // string resultString = string.Empty;
                bool errorOccured = false;

                Console.WriteLine("Preparing the request...");

                // first get the access token from clearstream API
                var accessToken = await GetElibilityTokenAsync();
                if (accessToken != null && !string.IsNullOrEmpty(accessToken.access_token))
                {
                    Console.WriteLine("Received non null JWT token. Calling Clearstream API");
                    Console.WriteLine($"Token: '{accessToken.access_token}'");
                    Console.WriteLine($"Refresh Token: {accessToken.refresh_token}");
                    Console.WriteLine($"Expires in: {accessToken.expires_in}");

                    // try to call the FIRST real DI method and get the available templates
                    var templates = await GetAllTemplates(accessToken);
                    if (templates != null && templates.Count > 0)
                    {
                        Console.WriteLine("Dumping all received templates available for the account used:");

                        DiTemplate firstTemplate = templates[0];

                        Console.WriteLine($"PartyId: {firstTemplate.partyId}");
                    }

                    Console.WriteLine("Successfully called Digital Instruments API.");
                }
                else
                {
                    Console.WriteLine("Received empty JWT token. Aborting.");
                    errorOccured = true;
                }

                if (errorOccured)
                {
                    Console.WriteLine("Clearstream VNext connectivity test completed with error(s).");
                }
                else
                {
                    Console.WriteLine("Clearstream VNext connectivity test completed successfully.");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Got Exception while running the connetivity check. Message {ex.Message}, Stacktrace: {ex.StackTrace}");
                Console.WriteLine("Clearstream VNext connecivity check FAILED.");
            }
        }
    }

As you can see, the sample code writes our all available templates within DI (Digital Instruments) that you or Clearstream has defined for your within their API. Please also not that the entire API is managed by Clearstream and you have an web interface with them in order to administer your account and settings.

One final note: due to different network topologies you might not directly get from your corporate / private network out to the internet directly. Common practice is to use a web proxy in the middle to facilitate internet connectivity. In that case you have to use a proxy for you web http client calls:


            // First create a proxy object
            // only necessary IF you need proxy to get from your network out to the internet
            var proxy = new WebProxy
            {
                Address = new Uri($"http://myproxy:port"),
                BypassProxyOnLocal = false,
                UseDefaultCredentials = false,
                Credentials = CredentialCache.DefaultNetworkCredentials
            };

This creates it. To actually use it please add it to the relevant parts of your code:

                // use modern http client implementation to call endpoint
                using var httpHandler = new HttpClientHandler();

                httpHandler.ClientCertificates.Add(certificates[0]);
                // httpHandler.Proxy = proxy;

                using var client = new HttpClient(httpHandler);

                // handle additional client header
                client.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken.access_token}");

                // handle communiction with API
                var response = await client.GetAsync(remoteAddress);

That should do the trick.

As always any feedback or questions are welcome. I hope you’ll find this post useful!

Accessing Clearstream Digital Instruments API

Johannes Rest


.NET Architekt und Entwickler


Beitragsnavigation


Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert