Getting Started

Setup

Prerequisites

Installation

NuGet ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜์„ธ์š”:

dotnet add package KiwoomRestApi.Net
Tip: NuGet ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž ์ฝ˜์†”์—์„œ๋„ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: Install-Package KiwoomRestApi.Net

Basic Project Setup

using KiwoomRestApi.Net.Clients; var appKey = "YOUR_APP_KEY"; var secretKey = "YOUR_SECRET_KEY"; var isMock = true; // ์‹ค๊ฑฐ๋ž˜์˜ ๊ฒฝ์šฐ false๋กœ ์„ค์ • // ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ var client = KiwoomRestApiClient.Create(appKey, secretKey, isMock);

Basic Usage

Data

Getting Stock Information

์‚ผ์„ฑ์ „์ž(005930)์˜ ๊ธฐ๋ณธ ์ฃผ์‹ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์™€ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค:

using KiwoomRestApi.Net.Enums.StockInfo; // ์‚ผ์„ฑ์ „์ž(005930) ์ฃผ์‹ ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ var stockInfo = await client.StockInfo.GetStockInfoAsync( stockCode: "005930", date: DateTime.Today, marginLoanType: KiwoomStockInfoMarginLoanType.Loan ); if (stockInfo.IsSuccess) { Console.WriteLine($"์ฃผ์‹๋ช…: {stockInfo.Data?.StockName}"); Console.WriteLine($"ํ˜„์žฌ๊ฐ€: {stockInfo.Data?.CurrentPrice:N0} KRW"); Console.WriteLine($"๋ณ€๋™๋ฅ : {stockInfo.Data?.ChangeRate:F2}%"); Console.WriteLine($"๊ฑฐ๋ž˜๋Ÿ‰: {stockInfo.Data?.Volume:N0}"); } else { Console.WriteLine($"์˜ค๋ฅ˜: {stockInfo.ReturnMessage}"); }

Understanding the Response

๋ชจ๋“  API ํ˜ธ์ถœ์€ KiwoomRestApiResponse<T> ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค:

PropertyTypeDescription
IsSuccessboolAPI ํ˜ธ์ถœ ์„ฑ๊ณต ์—ฌ๋ถ€
DataT?์‘๋‹ต ๋ฐ์ดํ„ฐ
ReturnMessagestring?์‘๋‹ต ๋ฉ”์‹œ์ง€
ApiIdstringAPI ์‹๋ณ„์ž
ContYnboolํŽ˜์ด์ง€๋„ค์ด์…˜ ์—ฐ์† ํ”Œ๋ž˜๊ทธ
NextKeystring๋‹ค์Œ ํŽ˜์ด์ง€ ํ‚ค

Account Management

Data

Getting Account Balance

using KiwoomRestApi.Net.Enums.Account; // ํ‰๊ฐ€ ์ž”๊ณ  ๊ฐ€์ ธ์˜ค๊ธฐ var balances = await client.Account.GetEvaluationBalancesAsync( queryType: KiwoomAccountEvaluationBalanceQueryType.Aggregate, domesticStockExchangeType: KiwoomAccountDomesticStockExchangeType2.Krx ); if (balances.IsSuccess) { foreach (var balance in balances.Data?.Items) { Console.WriteLine($"์ด์ž์‚ฐ: {balance.TotalEvaluationAmount:N0} KRW"); Console.WriteLine($"์ด ์†์ต: {balance.TotalEvaluationProfitLossAmount:N0} KRW"); Console.WriteLine($"์†์ต๋ฅ : {balance.TotalProfitRate:F2}%"); } }

Getting Daily Status

// ์ผ๋ณ„ ๊ณ„์ขŒ ์ƒํƒœ ๊ฐ€์ ธ์˜ค๊ธฐ var dailyStatus = await client.Account.GetDailyStatusAsync(); if (dailyStatus.IsSuccess) { Console.WriteLine($"์ž…๊ธˆ์•ก: {dailyStatus.Data?.DepositAmount:N0} KRW"); Console.WriteLine($"์ด ๋งค์ˆ˜: {dailyStatus.Data?.BuyAmount:N0} KRW"); Console.WriteLine($"์ด ๋งค๋„: {dailyStatus.Data?.SellAmount:N0} KRW"); }
Warning: ์ผ๋ถ€ ๊ณ„์ขŒ API๋Š” ๋ชจ์˜ํˆฌ์ž ๋ชจ๋“œ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ „์ฒด ๊ธฐ๋Šฅ์„ ์œ„ํ•ด ์‹ค์ œ API ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

Stock Information

Data

Market Data & Quotes

// ํ˜„์žฌ ์‹œ์žฅ ํ˜ธ๊ฐ€ ๊ฐ€์ ธ์˜ค๊ธฐ var quote = await client.MarketCondition.GetQuoteAsync("005930"); if (quote.IsSuccess) { Console.WriteLine($"ํ˜„์žฌ๊ฐ€: {quote.Data?.CurrentPrice}"); Console.WriteLine($"์ตœ์šฐ์ˆ˜ ๋งค์ˆ˜๊ฐ€: {quote.Data?.BuyPrice1}"); Console.WriteLine($"์ตœ์šฐ์ˆ˜ ๋งค๋„๊ฐ€: {quote.Data?.SellPrice1}"); } // ํ˜ธ๊ฐ€์ฐฝ ๊ฐ€์ ธ์˜ค๊ธฐ var orderBook = await client.MarketCondition.GetOrderBookListAsync("005930"); if (orderBook.IsSuccess) { Console.WriteLine("ํ˜ธ๊ฐ€์ฐฝ:"); var quotes = orderBook.Data; for (int i = 0; i < 5; i++) { Console.WriteLine($" ๋งค๋„ {i+1}: {quotes?.SellQuotes[i].Price} ({quotes?.SellQuotes[i].Quantity})"); } Console.WriteLine(" --------------------"); for (int i = 0; i < 5; i++) { Console.WriteLine($" ๋งค์ˆ˜ {i+1}: {quotes?.BuyQuotes[i].Price} ({quotes?.BuyQuotes[i].Quantity})"); } }

Ranking Information

using KiwoomRestApi.Net.Enums.RankingInfo; // ์ƒ์œ„ ์ƒ์Šน์ข… ๊ฐ€์ ธ์˜ค๊ธฐ var gainers = await client.RankingInfo.GetChangeRateTopsAsync( marketType: KiwoomRankingInfoMarketType.All, sortType: KiwoomRankingInfoChangeSortType.Up, minVolume: 100, stockCondition: KiwoomRankingInfoStockCondition.All, creditCondition: KiwoomRankingInfoCreditCondition.All, isIncludeUpDown: true, priceCondition: KiwoomRankingInfoPriceCondition.All, minTransactionAmount: 1000, stockExchangeType: KiwoomRankingInfoStockExchangeType.Unified ); if (gainers.IsSuccess) { Console.WriteLine("์ƒ์œ„ ์ƒ์Šน์ข…:"); foreach (var stock in gainers.Data?.Items.Take(5) ?? Enumerable.Empty<KiwoomRankingInfoGetChangeRateTopItem>()) { Console.WriteLine($"{stock.StockName}: {stock.ChangeRate:F2}% ({stock.CurrentPrice})"); } } // ๊ฑฐ๋ž˜๋Ÿ‰ ์ƒ์œ„ ์ข…๋ชฉ ๊ฐ€์ ธ์˜ค๊ธฐ var activeStocks = await client.RankingInfo.GetTodayVolumeTopsAsync( marketType: KiwoomRankingInfoMarketType.All, sortType: KiwoomRankingInfoVolumeSortType.Volume, stockCondition: KiwoomRankingInfoStockCondition.All, creditCondition: KiwoomRankingInfoCreditCondition.All, minVolume: 100, priceCondition: KiwoomRankingInfoPriceCondition2.All, minTransactionAmount: 1000, marketOpenType: KiwoomRankingInfoMarketOpenType.All, stockExchangeType: KiwoomRankingInfoStockExchangeType.Unified ); if (activeStocks.IsSuccess) { Console.WriteLine("๊ฑฐ๋ž˜๋Ÿ‰ ์ƒ์œ„ ์ข…๋ชฉ:"); foreach (var stock in activeStocks.Data?.Items.Take(5) ?? Enumerable.Empty<KiwoomRankingInfoGetTodayVolumeTopItem>()) { Console.WriteLine($"{stock.StockName}: {stock.Volume:N0} ์ฃผ"); } }

Trading Operations

Trading
Important: ๊ฑฐ๋ž˜ ์ž‘์—…์€ ์‹ค์ œ API ํ‚ค๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ ์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ๋ชจ์˜ํˆฌ์ž ๋ชจ๋“œ๋กœ ์‹œ์ž‘ํ•˜์„ธ์š”.

Placing Orders

using KiwoomRestApi.Net.Enums.Order; // ๋งค์ˆ˜ ์ฃผ๋ฌธ ์˜ˆ์ œ (์‹œ์žฅ๊ฐ€) var buyOrder = await client.Order.PlaceOrderAsync( KiwoomOrderType.Buy, KiwoomOrderDomesticStockExchangeType.Krx, stockCode: "005930", orderQuantity: 10, KiwoomOrderTransactionType.Market ); if (buyOrder.IsSuccess) { Console.WriteLine($"์ฃผ๋ฌธ ์„ฑ๊ณต. ์ฃผ๋ฌธ๋ฒˆํ˜ธ: {buyOrder.Data?.OrderId}"); } // ์ง€์ •๊ฐ€ ์ฃผ๋ฌธ ์˜ˆ์ œ var limitOrder = await client.Order.PlaceOrderAsync( KiwoomOrderType.Buy, KiwoomOrderDomesticStockExchangeType.Krx, stockCode: "005930", orderQuantity: 10, KiwoomOrderTransactionType.Limit, orderPrice: 75000 // ์ง€์ •๊ฐ€ );

Order Management

// ๋ฏธ์ฒด๊ฒฐ ์ฃผ๋ฌธ ๊ฐ€์ ธ์˜ค๊ธฐ var unfilledOrders = await client.Account.GetUnfilledOrdersAsync( KiwoomAccountQueryType.All, KiwoomAccountTransactionType.All, KiwoomAccountStockExchangeType.Unified ); if (unfilledOrders.IsSuccess) { foreach (var order in unfilledOrders.Data?.Items) { Console.WriteLine($"์ฃผ๋ฌธ: {order.OrderId} - {order.StockName}"); Console.WriteLine($"์œ ํ˜•: {order.TaskType}, ์ˆ˜๋Ÿ‰: {order.OrderQuantity}"); } } // ์ฃผ๋ฌธ ์ทจ์†Œ var cancelResult = await client.Order.CancelOrderAsync( KiwoomOrderDomesticStockExchangeType.Krx, originalOrderId: "YOUR_ORDER_NUMBER", stockCode: "005930", cancelQuantity: 5 ); // ์ฃผ๋ฌธ ์ˆ˜์ • var modifyResult = await client.Order.ModifyOrderAsync( KiwoomOrderDomesticStockExchangeType.Krx, originalOrderId: "YOUR_ORDER_NUMBER", stockCode: "005930", modifyQuantity: 15, modifyPrice: 76000 );

Chart Data

Data

Basic Charts

๋‹ค์–‘ํ•œ ์ฃผ๊ธฐ์˜ ์ฐจํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

using KiwoomRestApi.Net.Enums.Chart; var stockCode = "005930"; var date = new DateTime(2026, 3, 1); // ์ผ๋ด‰ ์ฐจํŠธ var daily = await client.Chart.GetDailyChartsAsync(stockCode, date, false); // ์ฃผ๋ด‰ ์ฐจํŠธ var weekly = await client.Chart.GetWeeklyChartsAsync(stockCode, date, false); // ์›”๋ด‰ ์ฐจํŠธ var monthly = await client.Chart.GetMonthlyChartsAsync(stockCode, date, false); // ๋ถ„๋ด‰ ์ฐจํŠธ (15๋ถ„) var minute = await client.Chart.GetMinuteChartsAsync(stockCode, 15, date, false); // ํ‹ฑ ์ฐจํŠธ (30ํ‹ฑ) var tick = await client.Chart.GetTickChartsAsync(stockCode, 30, false);

Range Charts

ํŠน์ • ๊ธฐ๊ฐ„์˜ ์ฐจํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:

var startDate = new DateTime(2026, 1, 1); var endDate = new DateTime(2026, 3, 6); // ๊ธฐ๊ฐ„๋ณ„ ์ผ๋ด‰ ์ฐจํŠธ var dailyRange = await client.Chart.GetDailyChartsByRangeAsync(stockCode, startDate, endDate, false); // ๊ธฐ๊ฐ„๋ณ„ ๋ถ„๋ด‰ ์ฐจํŠธ var minuteRange = await client.Chart.GetMinuteChartsByRangeAsync(stockCode, 15, startDate, endDate, false);

Industry Charts

// ์—…์ข… ์ผ๋ด‰ ์ฐจํŠธ var industryDaily = await client.Chart.GetIndustryDailyChartsAsync( KiwoomChartIndustryCode.Kospi200, date); // ์—…์ข… ๋ถ„๋ด‰ ์ฐจํŠธ (15๋ถ„) var industryMinute = await client.Chart.GetIndustryMinuteChartsAsync( KiwoomChartIndustryCode.Kospi200, 15, date);

Gold Spot Charts

using KiwoomRestApi.Net.Enums.Chart; // ๊ธˆํ˜„๋ฌผ ํ‹ฑ ์ฐจํŠธ var goldTick = await client.Chart.GetGoldSpotTickChartsAsync( KiwoomGoldSpotStockCode.Gold_1kg, 10, true); // ๊ธˆํ˜„๋ฌผ ์ผ๋ด‰ ์ฐจํŠธ var goldDaily = await client.Chart.GetGoldSpotDailyChartsAsync( KiwoomGoldSpotStockCode.Gold_1kg, date, true);

Real-time Data

WebSocket

Setting up WebSocket Client

using KiwoomRestApi.Net.Enums.WebSocket; // ์†Œ์ผ“ ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ var socketClient = KiwoomSocketClient.Create(client.Token, isMock: true); // ์‹ค์‹œ๊ฐ„ ์ฃผ์‹ ์ฒด๊ฒฐ ๋ฐ์ดํ„ฐ ๊ตฌ๋… await socketClient.WebSocket.SubscribeAsync( serviceNames: [KiwoomWebSocketServiceName.StockTrade], parameters: ["005930", "000660", "035420"], groupId: "1" );

Handling Real-time Events

// ์ฃผ์‹ ์ฒด๊ฒฐ ์ด๋ฒคํŠธ socketClient.OnRealtimeStockTradeReceived += (realtimeData) => { foreach (var data in realtimeData) { Console.WriteLine($"[{data.Item}] {data.Values.CurrentPrice} " + $"({data.Values.ChangeRate:F2}%) " + $"๊ฑฐ๋ž˜๋Ÿ‰: {data.Values.AccumulatedVolume:N0}"); } }; // ์ฃผ๋ฌธ ์ฒด๊ฒฐ ์ด๋ฒคํŠธ socketClient.OnRealtimeOrderTradeReceived += (orderData) => { foreach (var order in orderData) { Console.WriteLine($"์ฃผ๋ฌธ ์—…๋ฐ์ดํŠธ: {order.Values.OrderId} - {order.Values.OrderStatus}"); } }; // ์ž”๊ณ  ์ด๋ฒคํŠธ socketClient.OnRealtimeBalanceReceived += (balanceData) => { foreach (var balance in balanceData) { Console.WriteLine($"์ž”๊ณ  ์—…๋ฐ์ดํŠธ: {balance.Values.StockName}"); Console.WriteLine($"๋ณด์œ  ์ˆ˜๋Ÿ‰: {balance.Values.HoldingQuantity}"); } };

Available Services

ServiceEnum ValueDescription
์ฃผ์‹ ์ฒด๊ฒฐStockTrade์‹ค์‹œ๊ฐ„ ์ฃผ์‹ ์ฒด๊ฒฐ ๋ฐ์ดํ„ฐ
์ฃผ์‹ ํ˜ธ๊ฐ€OrderBook์‹ค์‹œ๊ฐ„ ํ˜ธ๊ฐ€ ๋ฐ์ดํ„ฐ
์ž”๊ณ Balance์‹ค์‹œ๊ฐ„ ์ž”๊ณ  ๋ณ€๋™
์ฃผ๋ฌธ ์ฒด๊ฒฐOrderTrade์‹ค์‹œ๊ฐ„ ์ฃผ๋ฌธ ์ฒด๊ฒฐ
VI ๋ฐœ๋™ViEventVI(๋ณ€๋™์„ฑ ์™„ํ™”์žฅ์น˜) ๋ฐœ๋™
ETF NAVEtfNavETF NAV ๋ฐ์ดํ„ฐ

Advanced Features

Advanced

Pagination

๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ ํŽ˜์ด์ง€๋„ค์ด์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

// ์ฒซ ํŽ˜์ด์ง€ ์กฐํšŒ var firstPage = await client.Chart.GetTickChartsAsync("005930", 1, false); // ๋‹ค์Œ ํŽ˜์ด์ง€๊ฐ€ ์žˆ์œผ๋ฉด if (firstPage.ContYn) { client.ContYn = true; client.NextKey = firstPage.NextKey; var secondPage = await client.Chart.GetTickChartsAsync("", 1, false); // ์ดˆ๊ธฐํ™” client.ContYn = false; client.NextKey = ""; }

Pagination Loop

๋ชจ๋“  ํŽ˜์ด์ง€๋ฅผ ์ˆœํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค:

// ๋ชจ๋“  ํŽ˜์ด์ง€๋ฅผ ์ˆœํšŒํ•˜๋Š” ๋ฃจํ”„ var response = await client.Chart.GetTickChartsAsync("005930", 1, false); while (response.IsSuccess) { foreach (var item in response.Data?.Items ?? Enumerable.Empty<KiwoomChartGetTickChartItem>()) { Console.WriteLine($"{item.CurrentPrice}"); } if (!response.ContYn) break; client.ContYn = true; client.NextKey = response.NextKey; response = await client.Chart.GetTickChartsAsync("", 1, false); } client.ContYn = false; client.NextKey = "";

Gold Spot Trading

using KiwoomRestApi.Net.Enums.Order; using KiwoomRestApi.Net.Enums.Chart; // ๊ธˆํ˜„๋ฌผ ๋งค์ˆ˜ ์ฃผ๋ฌธ var goldBuy = await client.Order.GoldSpotPlaceOrderAsync( KiwoomOrderType.Buy, KiwoomGoldSpotStockCode.MiniGold_100g, orderQuantity: 1, KiwoomOrderGoldSpotTransactionType.Normal ); // ๊ธˆํ˜„๋ฌผ ์ž”๊ณ  ์กฐํšŒ var goldBalances = await client.Account.GetGoldEvaluationBalancesAsync(); // ๊ธˆํ˜„๋ฌผ ์˜ˆ์ˆ˜๊ธˆ ์กฐํšŒ var goldDeposit = await client.Account.GetGoldDepositAsync( KiwoomAccountEvaluationBalanceQueryType.Aggregate, KiwoomAccountDomesticStockExchangeType.All );

Condition Search

// ์กฐ๊ฑด๊ฒ€์ƒ‰ ๋ชฉ๋ก ์กฐํšŒ await socketClient.WebSocket.GetConditionSearchListAsync(); // ์กฐ๊ฑด๊ฒ€์ƒ‰ ์‹ค์‹œ๊ฐ„ ๊ตฌ๋… await socketClient.WebSocket.GetConditionSearchRequestRealtimeAsync(1);

Error Handling

Advanced

Handling API Errors

try { var result = await client.StockInfo.GetStockInfoAsync( stockCode: "005930", date: DateTime.Today, marginLoanType: KiwoomStockInfoMarginLoanType.Loan ); if (!result.IsSuccess) { Console.WriteLine($"API Error [{result.ApiId}]: {result.ReturnMessage}"); return; } // ์„ฑ๊ณต ์ฒ˜๋ฆฌ Console.WriteLine($"Stock: {result.Data?.StockName}"); } catch (HttpRequestException ex) { Console.WriteLine($"HTTP Error: {ex.Message}"); } catch (TaskCanceledException) { Console.WriteLine("Request timed out."); } catch (Exception ex) { Console.WriteLine($"Unexpected error: {ex.Message}"); }
Note: API ์˜ค๋ฅ˜๋Š” IsSuccess == false๋กœ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜ ๋“ฑ์€ ์˜ˆ์™ธ๋กœ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

Best Practices

Setup

Connection Management

// IDisposable์„ ํ™œ์šฉํ•œ ์ ์ ˆํ•œ ํ•ด์ œ using var client = KiwoomRestApiClient.Create(appKey, secretKey, isMock); using var socketClient = KiwoomSocketClient.Create(client.Token, isMock); // API ํ˜ธ์ถœ...

Rate Limiting

API ํ˜ธ์ถœ ์‹œ ์†๋„ ์ œํ•œ์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค:

// PagingDelay ์†์„ฑ์„ ํ™œ์šฉํ•œ ํŽ˜์ด์ง€๋„ค์ด์…˜ ์ง€์—ฐ client.PagingDelay = 1000; // ํŽ˜์ด์ง€ ๊ฐ„ 1์ดˆ ์ง€์—ฐ (ms) // ๋˜๋Š” SemaphoreSlim์„ ์‚ฌ์šฉํ•œ ์ˆ˜๋™ ์ œํ•œ private readonly SemaphoreSlim _semaphore = new(1, 1); public async Task<T> ExecuteWithLimitAsync<T>(Func<Task<T>> apiCall) { await _semaphore.WaitAsync(); try { var result = await apiCall(); await Task.Delay(TimeSpan.FromMilliseconds(100)); return result; } finally { _semaphore.Release(); } }
Pro Tip: ๊ฐœ๋ฐœ ๋ฐ ํ…Œ์ŠคํŠธ ์‹œ์—๋Š” ํ•ญ์ƒ ๋ชจ์˜ํˆฌ์ž ๋ชจ๋“œ๋กœ ์‹œ์ž‘ํ•˜์„ธ์š”. ํ”„๋กœ๋•์…˜ ์ค€๋น„๊ฐ€ ๋˜์—ˆ์„ ๋•Œ๋งŒ ์‹ค์ œ API ํ‚ค๋กœ ์ „ํ™˜ํ•˜์„ธ์š”.