In Australia, Beaufort Fiduciaries Pty Ltd (ACN 162 139 871, AFSL No. 545124) provides wholesale clients with access to derivatives where the underlying assets are digital assets. Derivatives are complex, regulated financial products that are difficult to understand and may not be suitable for inexperienced investors. For eligibility, terms and conditions click here. Krak Pay is offered by Bit Trade Australia Pty Ltd (ACN 163 237 634), Authorised Representative of Flexewallet Pty Ltd (AFSL 448066). This information is general in nature and does not take into account your personal objectives, financial situation or needs. You should consider whether it is appropriate for you and read the relevant disclosure documents before making any decision.

Example code for C# REST and WebSocket API

Last updated: April 2, 2025

Introduction

Below is a C# example script that can be referenced for both the REST and WebSocket Implementation of the Kraken API.

It demo's the following functionality:

  • Public REST API Endpoints

  • Private REST API Endpoints

  • Public WebSocket API Subscriptions

  • Private WebSocket API Subscriptions

Installation

To run locally, you can copy/paste the code below.

Note that setting the if statement of 1 == 0 to 1 == 1 will execute the specific block of code.

Before running the script, you need to update the script with your Public and Private API Keys.

You can download this file here.

C# Code

bash

Bash

using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.WebSockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace KrakenCSharpExampleConsole
{
    class Program
    {
        static async Task Main(string[] args)
        {
            // TODO: UPDATE WITH YOUR KEYS :)
            string apiPublicKey = "YOUR_PUBLIC_KEY";
            string apiPrivateKey = "YOUR_PRIVATE_KEY";

            try
            {
                System.Console.WriteLine("|=========================================|");
                System.Console.WriteLine("|         KRAKEN.COM C# TEST APP          |");
                System.Console.WriteLine("|=========================================|");
                System.Console.WriteLine();

                #region Public REST API Examples

                if (1 == 0)
                {
                    string publicResponse = "";

                    string publicEndpoint = "SystemStatus";
                    string publicInputParameters = "";

                    // MORE PUBLIC REST EXAMPLES
                    // *

                    // string publicEndpoint = "AssetPairs";
                    // string publicInputParameters = "pair=ethusd,xbtusd";

                    // string publicEndpoint = "Ticker";
                    // string publicInputParameters = "pair=ethusd";

                    // string publicEndpoint = "Trades";
                    // string publicInputParameters = "pair=ethusd&since=0";

                    // *

                    publicResponse = await QueryPublicEndpoint(publicEndpoint, publicInputParameters);
                    System.Console.WriteLine(publicResponse);
                }

                #endregion

                #region Private REST API Examples

                if (1 == 0)
                {
                    string privateResponse = "";

                    string privateEndpoint = "Balance";
                    string privateInputParameters = "";

                    // MORE PRIVATE REST EXAMPLES
                    // *

                    // string privateEndpoint = "AddOrder";
                    // string privateInputParameters = "pair=xbteur&type=buy&ordertype=limit&price=1.00&volume=1";

                    // string privateEndpoint = "AddOrder";
                    // string privateInputParameters = "pair=xdgeur&type=sell&ordertype=limit&volume=3000&price=%2b10.0%"; // Positive Percentage Example

                    // string privateEndpoint = "AddOrder";
                    // string privateInputParameters = "pair=xdgeur&type=sell&ordertype=limit&volume=3000&price=-10.0%"; // Negative Percentage Example

                    // string privateEndpoint = "AddOrder";
                    // string privateInputParameters = "pair=xdgeur&type=buy&ordertype=market&volume=3000&userref=789"; // Userref Example

                    // string privateEndpoint = "Balance";
                    // string privateInputParameters = ""; //{"error":[]} IS SUCCESS, Means EMPTY BALANCE

                    // string privateEndpoint = "QueryOrders";
                    // string privateInputParameters = "txid=OFUSL6-GXIIT-KZ2JDJ";

                    // string privateEndpoint = "AddOrder";
                    // string privateInputParameters = "pair=xdgusd&type=buy&ordertype=market&volume=5000";

                    // string privateEndpoint = "DepositAddresses";
                    // string privateInputParameters = "asset=xbt&method=Bitcoin";

                    // string privateEndpoint = "DepositMethods";
                    // string privateInputParameters = "asset=eth";

                    // string privateEndpoint = "WalletTransfer";
                    // string privateInputParameters = "asset=xbt&to=Futures Wallet&from=Spot Wallet&amount=0.0045";

                    // string privateEndpoint = "TradesHistory";
                    // string privateInputParameters = "start=1577836800&end=1609459200";

                    // string privateEndpoint = "GetWebSocketsToken";
                    // string privateInputParameters = "";

                    // *

                    privateResponse = await QueryPrivateEndpoint(privateEndpoint, privateInputParameters, apiPublicKey, apiPrivateKey);
                    System.Console.WriteLine(privateResponse);
                }

                #endregion

                #region Public WebSocket API Examples

                if (1 == 0)
                {
                    string publicWebSocketURL = "wss://ws.kraken.com/";
                    string publicWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"ticker\"}, \"pair\": [ \"XBT/EUR\",\"ETH/USD\" ]}";

                    // MORE PUBLIC WEBSOCKET EXAMPLES
                    // *

                    // string publicWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"interval\": 1440, \"name\": \"ohlc\"}, \"pair\": [ \"XBT/EUR\"]}";

                    // string publicWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"spread\"}, \"pair\": [ \"XBT/EUR\",\"ETH/USD\" ]}";

                    // *

                    await OpenAndStreamWebSocketSubscription(publicWebSocketURL, publicWebSocketSubscriptionMsg);
                }

                #endregion

                #region Private WebSocket API Examples

                if (1 == 0)
                {
                    string privateWebSocketURL = "wss://ws-auth.kraken.com/";

                    // GET AND EXTRACT THE WEBSOCKET TOKEN FROM THE JSON RESPONSE
                    string webSocketRestResponseJSON = await QueryPrivateEndpoint("GetWebSocketsToken", "", apiPublicKey, apiPrivateKey);

                    var splits = webSocketRestResponseJSON.Split(new string[] { "\"token\":\"", "\"}}" }, StringSplitOptions.None);
                    string webSocketToken = splits[1];

                    string privateWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"ownTrades\", \"token\": \"#TOKEN#\"}}";

                    // MORE PRIVATE WEBSOCKET EXAMPLES
                    // *

                    // #TOKEN# IS A PLACEHOLDER

                    // string privateWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"openOrders\", \"token\": \"#TOKEN#\"}}";

                    // string privateWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"balances\", \"token\": \"#TOKEN#\"}}";

                    // string addOrderExample = "{\"event\":\"addOrder\",\"reqid\":1234,\"ordertype\":\"limit\",\"pair\":\"XBT/EUR\",\"token\":\"#TOKEN#\",\"type\":\"buy\",\"volume\":\"1\", \"price\":\"1.00\"}";

                    // *

                    // REPLACE PLACEHOLDER WITH TOKEN
                    privateWebSocketSubscriptionMsg = privateWebSocketSubscriptionMsg.Replace("#TOKEN#", webSocketToken);
                    await OpenAndStreamWebSocketSubscription(privateWebSocketURL, privateWebSocketSubscriptionMsg);
                }

                #endregion

                System.Console.WriteLine();
                System.Console.WriteLine("|=========================================|");
                System.Console.WriteLine("|      END OF PROGRAM, HAVE A NICE DAY :) |");
                System.Console.WriteLine("|=========================================|");
                System.Console.WriteLine();
            }
            catch (Exception e)
            {
                System.Console.WriteLine();
                System.Console.WriteLine("AN EXCEPTION OCCURRED :(");
                System.Console.WriteLine(e.ToString());
            }
        }

        #region Public REST API Endpoints

        private static async Task<string> QueryPublicEndpoint(string endpointName, string inputParameters)
        {
            string jsonData;
            string baseDomain = "https://api.kraken.com";
            string publicPath = "/0/public/";
            string apiEndpointFullURL = baseDomain + publicPath + endpointName + "?" + inputParameters;

            using (HttpClient client = new HttpClient())
            {
                jsonData = await client.GetStringAsync(apiEndpointFullURL);
            }
            return jsonData;
        }

        #endregion

        #region Private REST API Endpoints

        private static async Task<string> QueryPrivateEndpoint(string endpointName, string inputParameters, string apiPublicKey, string apiPrivateKey)
        {
            string baseDomain = "https://api.kraken.com";
            string privatePath = "/0/private/";

            string apiEndpointFullURL = baseDomain + privatePath + endpointName;
            string nonce = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
            if (!string.IsNullOrWhiteSpace(inputParameters))
            {
                inputParameters = "&" + inputParameters;
            }
            string apiPostBodyData = "nonce=" + nonce + inputParameters;
            string signature = CreateAuthenticationSignature(apiPrivateKey, privatePath, endpointName, nonce, inputParameters);

            string jsonData;
            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Clear();
                client.DefaultRequestHeaders.Add("API-Key", apiPublicKey);
                client.DefaultRequestHeaders.Add("API-Sign", signature);
                client.DefaultRequestHeaders.Add("User-Agent", "KrakenDotNet Client");

                StringContent data = new StringContent(apiPostBodyData, Encoding.UTF8, "application/x-www-form-urlencoded");
                HttpResponseMessage response = await client.PostAsync(apiEndpointFullURL, data);
                jsonData = response.Content.ReadAsStringAsync().Result;
            }
            return jsonData;
        }

        #endregion

        #region Authentication Algorithm

        public static string CreateAuthenticationSignature(string apiPrivateKey, string apiPath, string endpointName, string nonce, string inputParams)
        {
            byte[] sha256Hash = ComputeSha256Hash(nonce, inputParams);
            byte[] sha512Hash = ComputeSha512Hash(apiPrivateKey, sha256Hash, apiPath, endpointName, nonce, inputParams);
            string signatureString = Convert.ToBase64String(sha512Hash);
            return signatureString;
        }

        private static byte[] ComputeSha256Hash(string nonce, string inputParams)
        {
            byte[] sha256Hash;
            string sha256HashData = nonce.ToString() + "nonce=" + nonce.ToString() + inputParams;

            using (var sha = SHA256.Create())
            {
                sha256Hash = sha.ComputeHash(Encoding.UTF8.GetBytes(sha256HashData));
            }
            return sha256Hash;
        }

        private static byte[] ComputeSha512Hash(string apiPrivateKey, byte[] sha256Hash, string apiPath, string endpointName, string nonce, string inputParams)
        {
            string apiEndpointPath = apiPath + endpointName;
            byte[] apiEndpointPathBytes = Encoding.UTF8.GetBytes(apiEndpointPath);
            byte[] sha512HashData = apiEndpointPathBytes.Concat(sha256Hash).ToArray();
            HMACSHA512 encryptor = new HMACSHA512(Convert.FromBase64String(apiPrivateKey));
            byte[] sha512Hash = encryptor.ComputeHash(sha512HashData);
            return sha512Hash;
        }

        #endregion

        #region WebSocket API

        private static async Task OpenAndStreamWebSocketSubscription(string connectionURL, string webSocketSubscription)
        {
            try
            {
                ClientWebSocket webSocketClient = new ClientWebSocket();
                CancellationTokenSource stoppingToken = new CancellationTokenSource();

                // OPEN CONNECTION
                await webSocketClient.ConnectAsync(new Uri(connectionURL), CancellationToken.None);
                System.Console.WriteLine("WEBSOCKET CONNECTION OPEN!");

                // SEND SUBSCRIPTION MESSAGE
                System.Console.WriteLine("WEBSOCKET SUBSCRIPTION MESSAGE:");
                System.Console.WriteLine(webSocketSubscription);
                if (webSocketClient.State == WebSocketState.Open)
                {
                    await webSocketClient.SendAsync(Encoding.UTF8.GetBytes(webSocketSubscription), WebSocketMessageType.Text, true, stoppingToken.Token);
                }

                // RECEIVE AND PRINT MESSAGE
                do
                {
                    await ReceiveMessage(webSocketClient, stoppingToken.Token);
                } while (webSocketClient.State == WebSocketState.Open);

                // CLOSE CONNECTION
                await webSocketClient.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "", stoppingToken.Token);
            }
            catch (OperationCanceledException)
            {
                // DO NOTHING - ASSUME WAS REQUESTED
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private static async Task ReceiveMessage(ClientWebSocket socket, CancellationToken stoppingToken)
        {
            var buffer = new ArraySegment<byte>(new byte[2048]);
            while (!stoppingToken.IsCancellationRequested)
            {
                WebSocketReceiveResult result;
                using (var ms = new MemoryStream())
                {
                    do
                    {
                        result = await socket.ReceiveAsync(buffer, stoppingToken);
                        ms.Write(buffer.Array, buffer.Offset, result.Count);
                    } while (!result.EndOfMessage);

                    if (result.MessageType == WebSocketMessageType.Close)
                    {
                        break;
                    }

                    string wsMsg = "";
                    ms.Seek(0, SeekOrigin.Begin);
                    using (var reader = new StreamReader(ms, Encoding.UTF8))
                    {
                        wsMsg = await reader.ReadToEndAsync();
                    }
                    string msgTime = DateTime.Now.ToString("dd-MMM-yyyy HH:mm:ss") + ": ";
                    System.Console.WriteLine(msgTime + wsMsg);
                }
            }
        }

        #endregion
    }
}

Need more help?