Overview
This is a comprehensive guide for interacting with the Kiwoom Securities REST API. It includes OAuth 2.0 authentication, stock basic information lookup (ka10001), account asset status (kt00004), daily balance return rate (ka01690), mock investment/real trading environment management, and Rate Limiting handling.
Installation
npx dlabs install trading-tools
Environment Configuration
.env File Configuration
In the project root, if there is no .env file, copy this skill's .env.exampleto create it:
# 프로젝트 루트로 이동
cd /path/to/your-project
# .env 파일이 없으면 스킬의 .env.example 복사
if [ ! -f .env ]; then
cp .claude/skills/kiwoom-api/.env.example .env
echo "✅ .env 파일 생성됨. API 키를 입력하세요."
fi
# .env 파일 편집
nano .env # 또는 vim, code 등
Required environment variables:
# 거래 환경: mock (모의투자) | prod (실전투자)
TRADING_ENV=mock
# API 인증 정보 (openapi.kiwoom.com에서 발급)
KIWOOM_REST_API_KEY=your_api_key
KIWOOM_REST_API_SECRET=your_api_secret
# 계좌번호 (모의투자: 50으로 시작)
KIWOOM_ACCOUNT_NO=5012345678
Environment Switching
.env In the TRADING_ENV file, change the
# 모의투자 (기본값, 권장)
TRADING_ENV=mock
# 실전투자 (신중히!)
TRADING_ENV=prod
API endpoints by environment:
| Environment | TRADING_ENV | Base URL |
|---|---|---|
| Mock Investment | mock |
https://mockapi.kiwoom.com |
| Real Trading | prod |
https://api.kiwoom.com |
Authentication (OAuth 2.0)
Token Issuance
import httpx
import os
from dotenv import load_dotenv
# 프로젝트 루트의 .env 로드
load_dotenv()
api_key = os.getenv("KIWOOM_REST_API_KEY")
api_secret = os.getenv("KIWOOM_REST_API_SECRET")
trading_env = os.getenv("TRADING_ENV", "mock")
# Base URL 결정
base_url = (
"https://mockapi.kiwoom.com" if trading_env == "mock"
else "https://api.kiwoom.com"
)
# 토큰 발급
url = f"{base_url}/oauth2/token"
data = {
"grant_type": "client_credentials",
"appkey": api_key,
"secretkey": api_secret
}
response = httpx.post(url, json=data, timeout=30.0)
result = response.json()
if result.get('return_code') == 0:
token = result['token']
print(f"Token: {token}")
else:
print(f"Error: {result.get('return_msg')}")
Token Caching
Tokens are valid for about 1 hour. Cache the token to prevent unnecessary reissuance:
import time
class KiwoomAPIClient:
def __init__(self):
self.token = None
self.token_expires = None
def _get_token(self) -> str:
# 캐시된 토큰이 유효하면 재사용
if self.token and self.token_expires:
if time.time() < self.token_expires:
return self.token
# 토큰 발급
# ... (위 코드 참조)
self.token = result['token']
self.token_expires = time.time() + 3600
return self.token
Stock Data Lookup (ka10001)
Basic Information Lookup
def get_stock_info(self, stock_code: str) -> dict:
"""
주식기본정보요청 (ka10001)
Args:
stock_code: 종목코드 6자리 (예: "005930" 삼성전자)
Returns:
주가 정보 딕셔너리
"""
token = self._get_token()
url = f"{self.base_url}/api/dostk/stkinfo"
headers = {
"Content-Type": "application/json;charset=UTF-8",
"api-id": "ka10001",
"authorization": f"Bearer {token}"
}
body = {"stk_cd": stock_code}
response = httpx.post(url, headers=headers, json=body, timeout=30.0)
result = response.json()
if result.get('return_code') == 0:
return result
else:
raise Exception(f"API 오류: {result.get('return_msg')}")
Response Data Structure
{
"return_code": 0,
"return_msg": "정상적으로 처리되었습니다",
"stk_cd": "005930",
"stk_nm": "삼성전자",
"cur_prc": "-160400",
"pred_pre": "-8700",
"flu_rt": "-5.14",
"trde_qty": "31734276",
"mac": "9512858",
"per": "32.47",
"eps": "4950",
"pbr": "2.77",
"roe": "9.0",
"bps": "57930",
"250hgst": "+169400",
"250lwst": "-50800"
}
Account Asset Lookup
Asset Summary Lookup (get_asset_summary)
See your asset status at a glance before starting to invest:
from kiwoom_api_client_template import KiwoomAPIClient
client = KiwoomAPIClient()
summary = client.get_asset_summary()
print(f"환경: {summary['environment']}")
print(f"예수금: {summary['deposit']:,}원")
print(f"추정예탁자산: {summary['estimated_asset']:,}원")
print(f"보유종목: {summary['holdings_count']}개")
print(f"누적손익: {summary['cumulative_pnl']:+,}원 ({summary['cumulative_pnl_pct']:+.2f}%)")
Account Evaluation Status (kt00004, get_account_evaluation)
Detailed evaluation status by held stock:
data = client.get_account_evaluation()
# 계좌 요약
s = data["summary"]
# deposit, d2_deposit, total_evaluation, total_asset,
# total_purchase, estimated_asset,
# today_pnl, monthly_pnl, cumulative_pnl,
# today_pnl_pct, monthly_pnl_pct, cumulative_pnl_pct
# 보유종목 리스트
for h in data["holdings"]:
print(f"{h['name']} | {h['quantity']}주 | 손익: {h['pnl_pct']:+.2f}%")
# code, name, quantity, avg_price, current_price,
# evaluation, pnl_amount, pnl_pct, purchase_amount
Daily Balance Return Rate (ka01690, get_daily_balance_pnl)
Balance and return rate as of a specific date:
# 오늘 기준
daily = client.get_daily_balance_pnl()
# 특정 일자
daily = client.get_daily_balance_pnl("20260207")
s = daily["summary"]
# total_purchase, total_evaluation, total_pnl, total_pnl_pct,
# deposit, estimated_asset, cash_ratio
for h in daily["holdings"]:
print(f"{h['name']} | 비중: {h['buy_ratio']:.1f}% | 수익률: {h['pnl_pct']:+.2f}%")
# code, name, current_price, quantity, avg_price,
# buy_ratio, evaluation, eval_ratio, pnl_amount, pnl_pct
Settlement Balance Lookup (kt00005, get_settlement_balance) - Real Trading Only
Settlement balance, deposit, and credit/loan status of executed orders:
# ⚠️ 실전투자 전용 - 모의투자에서는 Exception 발생
client = KiwoomAPIClient(use_mock=False) # 실전투자 명시
data = client.get_settlement_balance()
# 계좌 요약
s = data["summary"]
# deposit, deposit_d1, deposit_d2, orderable_cash,
# withdrawable, unsettled_cash,
# total_buy_amount, total_evaluation,
# total_pnl, total_pnl_pct,
# substitute_amount, credit_collateral_rate
# 종목별 체결잔고
for h in data["holdings"]:
print(f"{h['name']} | 결제잔고: {h['settlement_balance']}주 | 현잔고: {h['current_quantity']}주")
# code, name, settlement_balance, current_quantity,
# current_price, avg_price, purchase_amount,
# evaluation, pnl_amount, pnl_pct,
# credit_type, loan_date, expire_date
Account API Comparison
| API | Method | Mock Investment | Purpose |
|---|---|---|---|
| kt00004 | get_account_evaluation() |
Supported | Current held stocks + profit/loss status |
| ka01690 | get_daily_balance_pnl() |
Supported | Balance as of a specific date + weight by stock |
| kt00005 | get_settlement_balance() |
Not supported | Settlement balance (real trading only) |
Rate Limiting Management
The Kiwoom Securities API has a request count limit. To prevent HTTP 429 errors:
import time
def get_multiple_stocks(self, stock_codes: list, delay: float = 1.0) -> dict:
"""
여러 종목 조회 (Rate Limiting 대응)
Args:
stock_codes: 종목코드 리스트
delay: 요청 간 대기 시간 (초)
Returns:
종목별 데이터 딕셔너리
"""
results = {}
for i, code in enumerate(stock_codes):
if i > 0:
time.sleep(delay) # 첫 요청 제외하고 대기
try:
results[code] = self.get_stock_info(code)
except Exception as e:
results[code] = {"error": str(e)}
return results
Recommendations:
- Wait at least 0.5–1 second between requests
- Increase the wait time when an HTTP 429 error occurs
- Batch processing is recommended for consecutive lookups
Using the Client Template
A reusable client template is provided:
# 템플릿 위치
.claude/skills/kiwoom-api/assets/kiwoom_api_client_template.py
Template Features:
- Automatic OAuth token caching and renewal
- Environment variable-based configuration (uses project root .env)
- Built-in error handling
- Stock basic information lookup (ka10001)
- Account evaluation status lookup (kt00004)
- Daily balance return rate lookup (ka01690)
- Settlement balance lookup (kt00005, real trading only)
- Asset summary lookup (kt00004 wrapping)
How to Use:
from kiwoom_api_client_template import KiwoomAPIClient
client = KiwoomAPIClient() # .env 기준 자동 결정
client = KiwoomAPIClient(use_mock=True) # 명시적 모의투자
# 주식 정보
data = client.get_stock_info("005930")
# 자산 현황 (가장 자주 쓰는 메서드)
summary = client.get_asset_summary()
print(f"예수금: {summary['deposit']:,}원")
# 상세 계좌 평가
evaluation = client.get_account_evaluation()
# 일별 잔고 수익률
daily = client.get_daily_balance_pnl("20260207")
Safety Rules
Mock Investment (Recommended)
- Development and Testing
- Strategy Validation
- Backtesting
- Unlimited Experimentation
Live Investment (Caution)
- Only After Validation
- Start with a Small Amount
- Focus on Inquiry API
- Extremely Cautious with Trading API
Stock Code Format
# KRX (국내 주식)
"005930" # 삼성전자
# NASDAQ
"039490_NX" # 셀트리온
# NYSE
"039490_AL" # 셀트리온
Response Code
| return_code | Meaning |
|---|---|
| 0 | Normal Processing |
| 2 | Input Value Error |
| 3 | Authentication Failed |
| 5 | Rate Limit Exceeded |
Troubleshooting
Authentication Failed (return_code: 3)
.envCheck API Key/Secret in FileTRADING_ENVCheck Settings (mock/prod)- Reissue Token on Expiration
Rate Limit Exceeded (return_code: 5)
- Increase delay between requests
- Use batch processing
- Remove unnecessary requests
Invalid Stock Code (return_code: 2)
- Check 6-digit number format
- Check KRX exchange code
kt00005 Execution Balance Mock Investment Not Supported (return_code: 20)
- Cause: kt00005 is not supported in mock investment
- Message:
모의투자에서는 해당업무가 제공되지 않습니다 - Alternative: Check holdings/balance with kt00004 (Account Evaluation Status)
ka01690 Weekend/Holiday Empty Data
- Cause: No market data on weekends/holidays
- Message:
서비스 TR을 확인 바랍니다(return_code: 0 but data is empty) - Alternative: Query with the previous business day (Friday) date
find_project_root() .env not found
- Cause: In the skill subdirectory,
.env.exampleis matched before the project root's.envmatched before - Solution:
.envsearch first, then.env.examplemodify to search as fallback
Resources
references/
api_endpoints.md - Detailed specification of Kiwoom Securities REST API endpoints. Includes OAuth, stock information, account, and trading APIs.
account.md - Detailed specification of account-related API (ka01690 Daily Balance Profit Rate).
environment_config.md - Environment setup and management guide. Includes environment variable list and how to check environment in Python.
market_price.md - Detailed specification of market data API (order book, daily/weekly/monthly/minute, minute, quote table information, subscription rights).
ranking.md - Detailed specification of ranking information API (top order book remaining volume, order book remaining volume surge, remaining volume rate surge, trading volume surge, top daily change rate).
institution.md - Detailed specification of institutional/foreign trading trends API (foreign per stock, institutional).
sector.md - Detailed specification of sector program trading API.
short_selling.md - Detailed specification of short selling trend API.
stock_info.md - Detailed specification of stock information API (real-time rankings, basic information, trading members, execution information, credit trading, daily trading, new high/low, upper/lower limit, near high/low, price surge/drop, trading volume renewal, concentration of supply, high/low PER).
misc.md - Detailed specification of other APIs (token issuance/revocation).
assets/
kiwoom_api_client_template.py - Reusable Kiwoom API client template. Includes OAuth authentication, token caching, and implementations of the stock information (ka10001), account evaluation (kt00004), daily balance (ka01690), and execution balance (kt00005) APIs.
API Endpoint Summary
| API ID | Purpose | URL | Mock Investment |
|---|---|---|---|
| au10001 | Token Issuance | /oauth2/token |
Supported |
| ka10001 | Basic Stock Information | /api/dostk/stkinfo |
Supported |
| kt00004 | Account Evaluation Status | /api/dostk/acnt |
Supported |
| ka01690 | Daily Balance Return Rate | /api/dostk/acnt |
Supported |
| kt00005 | Execution Balance | /api/dostk/acnt |
Not Supported (Live Trading Only) |
| kt10000 | Buy Order | /api/dostk/ordr |
Supported |
| kt10001 | Sell Order | /api/dostk/ordr |
Supported |
Order API Parameter Specification
Buy (kt10000) / Sell (kt10001) Common
Endpoint: /api/dostk/ordr
**All parameter values must be strings (String)**. If you send an integer as is, 타입 불일치 error occurs.
body = {
"dmst_stex_tp": "KRX", # 거래소 구분 (필수)
"stk_cd": "005930", # 종목코드 (필수)
"ord_qty": "4", # 주문수량 (필수, 문자열!)
"ord_uv": "0", # 주문단가 (필수, 시장가="0")
"trde_tp": "3", # 매매구분 (필수)
}
Parameter Details
| Parameter | Description | 값 | Remarks |
|---|---|---|---|
dmst_stex_tp |
Exchange Type | "KRX", "NXT", "SOR" |
1511 error if omitted |
stk_cd |
Stock Code | "005930" |
6-character string |
ord_qty |
Order Quantity | "4" |
Must be a string, 1517 error if int |
ord_uv |
Order Price | "0" (Market Price), "50000" (Limit Price) |
Must be a string |
trde_tp |
Trade Type | "0"=Limit Price, "3"=Market Price, "5"=Conditional Limit Price |
Caution: Incorrect Parameter Name
If you use a name different from the official API, 필수입력 파라미터 error occurs:
| Incorrect Name | Correct Name | Error |
|---|---|---|
qty |
ord_qty |
1511: Required Input Parameter |
ordr_prc |
ord_uv |
1511: Required Input Parameter |
trd_dvsn |
trde_tp |
1511: Required Input Parameter |
Unnecessary Parameter
| Parameter | Reason Unnecessary |
|---|---|
acnt_no |
Account information included in OAuth token |
Response Example
{
"ord_no": "0362917",
"dmst_stex_tp": "KRX",
"return_code": 0,
"return_msg": "KRX 매수주문이 완료되었습니다."
}
Live Trading Prerequisites
- On openapi.kiwoom.com, Designated Terminal IP Registration required (error 8050 if not registered)
curl ifconfig.meCheck current IP and register