토스증권 Open API는 무엇을 열어 주는가

API는 사람 대신 프로그램이 두드리는 창구다. 평소 앱 화면에서 손으로 하던 조회와 주문을, 정해진 형식의 요청으로 보낼 수 있게 증권사가 열어 둔 문이라고 보면 된다. 앱 화면을 자동으로 클릭하는 편법과 달리 공식 통로이므로 계정 제재를 걱정할 일이 없다.
토스증권 Open API는 기능을 다섯 갈래로 나눠 둔다. 인증(Auth), 시세·종목 정보(Market Data·Stock Info·Market Info·Market Indicators·Ranking), 계좌·자산(Account·Asset), 주문(Order·Order History·Order Info), 조건주문(Conditional Order·Conditional Order History)이다. 국내(KRX)와 미국 주식이 대상이다.
시세·종목 정보는 모든 사용자에게 동일하게 제공되는 객관적 데이터라 토큰만 있으면 부를 수 있다. 현재가·호가·체결·캔들(1분봉·일봉)·상하한가, 종목 마스터, 매수 유의사항(정리매매·단기과열·투자경고·VI 발동), 환율, 국내외 장 운영 캘린더, 거래대금·등락률 랭킹, 코스피·코스닥 지수와 투자자별 매매대금까지 들어 있다.
반대로 계좌·자산, 주문, 조건주문은 내 계좌를 직접 건드리므로 토큰에 더해 계좌 식별 헤더가 필요하다. 이 글에서 다루는 자동화의 핵심이 이쪽이다.
연동 방식은 현재 REST API 하나뿐이다. 실시간 스트리밍이 필요한 웹소켓은 추후 지원 예정으로 표기돼 있어서, 지금은 필요한 시점에 직접 조회하는 폴링 방식으로 짜야 한다.
신청은 어디서, 어떻게 하는가
신청 창구는 개발자 신청 폼이 아니라 토스증권 WTS(웹 트레이딩 화면, tossinvest.com)다. 토스증권 계좌가 있는 상태로 로그인한 뒤 설정 메뉴에 들어가면 Open API 항목이 있고, 거기서 client_id와 client_secret을 직접 발급받는다. 발급 절차는 검토나 승인 대기 없이 화면에서 바로 끝난다.
여기서 client_id는 아이디, client_secret은 비밀번호에 해당한다. secret은 발급 화면을 벗어나면 다시 볼 수 없는 경우가 많으니 그 자리에서 안전한 곳에 복사해 둔다.
두 번째 단계가 진짜 관문이다. 같은 화면 아래쪽 허용 IP 관리에서 API를 호출할 IP를 등록해야 한다. 등록된 목록에 없는 IP에서 부르면 키가 아무리 맞아도 403으로 차단된다. 내 공인 IP는 터미널에서 curl ifconfig.me 한 줄로 확인할 수 있다.
집이나 사무실 회선은 공인 IP가 바뀔 수 있다는 점도 미리 알아 두는 게 좋다. 어느 날 갑자기 403이 뜨면 대개 키 문제가 아니라 IP가 바뀐 것이다. 서버나 클라우드에서 자동화를 돌릴 계획이라면 그 장비의 아웃바운드 IP를 등록해야 한다.
계정별로 순차 개방되는 구조라, 설정에 Open API 메뉴가 보이지 않으면 아직 내 계정 차례가 오지 않은 것이다. 이 경우 안내 배너의 사전 신청으로 대기 등록을 해 두면 열릴 때 알림을 받는다.
토큰을 받고 첫 호출을 해 보자
모든 호출은 OAuth 2.0 액세스 토큰을 요구한다. 발급 방식은 Client Credentials Grant인데, 사람이 로그인 화면을 거치는 방식이 아니라 프로그램이 자기 아이디와 비밀번호로 토큰을 받아 오는 방식이다. 그래서 무인 자동화에 적합하다.
토큰의 성질을 세 가지만 기억하면 된다. 유효기간은 86400초, 즉 24시간이다. 리프레시 토큰이 없으므로 만료되면 같은 엔드포인트로 다시 받으면 된다. 그리고 클라이언트당 유효한 토큰은 하나뿐이라, 새로 발급하면 이전 토큰은 즉시 무효가 된다. 여러 스크립트가 각자 토큰을 받으면 서로를 무효화하므로, 발급받은 토큰은 파일에 캐시해 두고 만료 전까지 함께 쓰는 편이 낫다.
공식 가이드의 예시는 client_id와 client_secret을 요청 본문에 담는 방식이다. 다만 내 환경에서는 본문 방식이 invalid_client로 거절돼, HTTP Basic 인증 헤더로 보내 발급에 성공했다. 둘 중 되는 쪽을 쓰면 된다.
토큰을 받았으면 계좌를 건드리지 않는 조회부터 해 본다. 종목 정보나 현재가는 토큰만으로 호출된다. 그다음 계좌 목록을 조회하면 accountSeq라는 번호가 나오는데, 이 값이 이후 보유 주식·주문·조건주문 호출에 들어가는 X-Tossinvest-Account 헤더의 값이다.
curl -s -X POST 'https://openapi.tossinvest.com/oauth2/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials' \
-d 'client_id=YOUR_CLIENT_ID' \
-d 'client_secret=YOUR_CLIENT_SECRET'
# 응답: {"access_token":"eyJ...","token_type":"Bearer","expires_in":86400}curl -s -X POST 'https://openapi.tossinvest.com/oauth2/token' \
-u "$TOSS_API_KEY:$TOSS_SECRET_KEY" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials'TOKEN=eyJ...
# 1) 종목 기본 정보 (토큰만 필요)
curl -s 'https://openapi.tossinvest.com/api/v1/stocks?symbols=005930' \
-H "Authorization: Bearer $TOKEN"
# 2) 계좌 목록 — 여기서 accountSeq를 확인한다
curl -s 'https://openapi.tossinvest.com/api/v1/accounts' \
-H "Authorization: Bearer $TOKEN"
# 3) 보유 주식 (토큰 + 계좌 헤더)
curl -s 'https://openapi.tossinvest.com/api/v1/holdings' \
-H "Authorization: Bearer $TOKEN" \
-H 'X-Tossinvest-Account: 1'Claude Code와 Codex는 무엇이고, 어떻게 설치하는가
Claude Code는 Anthropic이, Codex는 OpenAI가 만든 터미널용 AI 코딩 에이전트다. 채팅창에서 코드를 받아 내가 붙여넣는 방식이 아니라, 에이전트가 내 컴퓨터에서 직접 파일을 읽고 쓰고 명령을 실행한다. 그래서 API 연동처럼 문서를 읽고 코드를 만들고 실행해 결과를 확인하는 반복 작업에 특히 잘 맞는다.
설치는 Node.js가 깔려 있으면 한 줄이다. 터미널에서 npm install -g @anthropic-ai/claude-code 또는 npm install -g @openai/codex를 실행하고, 각각 claude와 codex 명령으로 실행한다. 첫 실행에서 로그인이나 API 키 등록을 요구하는데, Claude Code는 Claude 유료 구독 계정으로, Codex는 ChatGPT 계정이나 OpenAI API 키로 인증한다.
둘 중 하나만 있어도 충분하다. 굳이 나누자면 한쪽에서 만든 코드를 다른 쪽에 검토시키는 식으로 교차 확인을 시킬 때 두 개를 함께 쓴다. 주문을 다루는 코드라면 이 교차 검토가 값을 한다.
여기서 반드시 지킬 원칙이 하나 있다. 발급받은 키는 .env 파일에 저장하고 그 파일을 .gitignore에 넣어 저장소에 올라가지 않게 막는다. 채팅창이나 코드 안에 키를 직접 적어 두지 않는다. 증권 계좌 키는 유출되면 남이 내 계좌에 주문을 낼 수 있는 종류의 비밀이다.
또 하나, 에이전트를 승인 없이 모든 명령을 실행하는 모드로 켜 둔 채 주문 API를 다루지 않는다. 편의를 위해 그런 모드를 쓰는 사람이 많지만, 실주문이 가능한 환경에서는 명령마다 확인을 받는 기본 모드가 맞다.
# 터미널 AI 에이전트 설치 (Node.js 필요)
npm install -g @anthropic-ai/claude-code # 실행: claude
npm install -g @openai/codex # 실행: codex
# 키는 .env에 두고 저장소에서 제외한다
cat >> .env <<'EOF'
TOSS_API_KEY=발급받은_client_id
TOSS_SECRET_KEY=발급받은_client_secret
EOF
echo '.env' >> .gitignore에이전트에게 무엇을 시키면 되는가
가장 먼저 시킬 일은 공식 문서를 읽히는 것이다. 토스증권은 AI가 읽기 좋은 형태의 문서를 따로 제공한다. 스펙 원본 JSON과 마크다운 변환본이 공개돼 있어서, 에이전트에게 그 주소를 알려 주면 엔드포인트와 요청 형식을 추측하지 않고 정확히 맞춘다.
그다음은 조회부터다. "이 문서를 읽고 내 보유 종목과 평가손익을 표로 보여 주는 스크립트를 만들어 줘. 키는 .env에서 읽어"라고 말하면, 토큰 발급과 캐싱, 계좌 조회, 보유 주식 조회를 묶은 스크립트가 나온다. 실행해서 숫자가 앱 화면과 맞는지 눈으로 대조한다. 이 대조를 건너뛰면 이후 모든 자동화가 검증되지 않은 토대 위에 쌓인다.
조회가 맞아떨어지면 매매 규칙을 말로 설명한다. 예를 들어 "고점 대비 20퍼센트 빠지면 전량 매도" 같은 규칙이다. 중요한 건 규칙을 코드로 어떻게 짜느냐가 아니라, 그 규칙이 언제 어떤 값을 기준으로 판정되는지를 내가 정확히 말해 줄 수 있느냐다. 종가 기준인지 장중 가격 기준인지, 하루 몇 번 확인하는지 같은 것들이다.
마지막으로 반복해서 쓰는 작업은 에이전트의 스킬이나 명령 파일로 굳혀 둔다. 매번 같은 설명을 다시 하지 않게 되고, 안전 규칙도 그 안에 함께 박아 둘 수 있다.
토스증권 Open API 스펙을 먼저 읽어 줘.
- 스펙 JSON: https://openapi.tossinvest.com/openapi-docs/latest/openapi.json
- 개요 문서: https://openapi.tossinvest.com/openapi-docs/overview.md
읽고 나서, .env의 TOSS_API_KEY/TOSS_SECRET_KEY로 토큰을 받아
보유 주식을 종목명·수량·평가금액·손익 표로 출력하는 스크립트를 만들어 줘.
토큰은 파일에 캐시해서 24시간 재사용하고, 401이면 한 번만 재발급해.
주문 관련 코드는 아직 넣지 마.주문을 맡기기 전에 걸어야 하는 게이트
조회가 되는 순간 주문도 된다. 같은 토큰, 같은 헤더로 POST 한 번이면 실제 체결이다. 그래서 주문 코드를 만들기 전에 안전장치를 먼저 정해 두는 편이 낫다.
안전장치는 두 층으로 나눠 생각하면 정리된다. 하나는 API가 기본으로 제공하는 층이고, 다른 하나는 내가 스크립트에 얹는 층이다.
API가 제공하는 대표적인 장치가 멱등키다. 주문 생성 요청에 clientOrderId라는 값을 넣으면, 네트워크 오류로 같은 요청이 두 번 나가도 주문은 한 번만 접수된다. 같은 키로 내용이 다른 주문을 보내면 거절되므로 실수도 잡힌다. 주문 금액이 1억 원 이상이면 confirmHighValueOrder를 참으로 넣어야만 접수되는 장치도 있다.
여기에 내가 얹은 층은 다음과 같다. 기본값은 항상 연습 모드라 인자만으로는 주문이 나가지 않는다. 실주문은 실행 플래그와 종목 일치 확인을 동시에 요구한다. 주문 금액 한도를 파일에 적어 두고 넘으면 별도 플래그 없이는 거절한다. 시장가는 명시적으로 지정할 때만 열리고 기본은 지정가다. 주문 전에 매수는 가능 금액을, 매도는 매도 가능 수량을 먼저 조회해 확인한다.
이 층은 각자 자기 코드에 맞게 만들면 된다. 형태보다 원칙이 중요하다. 실주문은 사람이 한 번 더 명시적으로 확인해야 나가고, 자동화가 스스로 판단해 한도를 넘기지 못하게 한다.
| 층 | 장치 | 무엇을 막나 |
|---|---|---|
| API 기본 | clientOrderId 멱등키 | 네트워크 재시도로 같은 주문이 두 번 접수되는 것 |
| API 기본 | confirmHighValueOrder | 1억 원 이상 주문이 확인 없이 나가는 것 |
| API 기본 | 매수 가능 금액·매도 가능 수량 조회 | 잔고를 넘는 주문을 그냥 던지는 것 |
| 내 스크립트 | 연습 모드 기본값 | 인자만 잘못 넣어도 실주문이 나가는 것 |
| 내 스크립트 | 실행 플래그 + 종목 확인 동시 요구 | 다른 종목에 주문이 나가는 것 |
| 내 스크립트 | 주문 금액 한도 | 자동화가 의도보다 큰 금액을 집행하는 것 |
| 내 스크립트 | 지정가 기본, 시장가는 명시할 때만 | 호가가 얇을 때 시장가로 밀려 체결되는 것 |
curl -s -X POST 'https://openapi.tossinvest.com/api/v1/orders' \
-H "Authorization: Bearer $TOKEN" \
-H 'X-Tossinvest-Account: 1' \
-H 'Content-Type: application/json' \
-d '{
"symbol": "005930",
"side": "BUY",
"orderType": "LIMIT",
"quantity": 10,
"price": "70000",
"clientOrderId": "my-order-20260725-001"
}'조건주문 — 감시를 증권사 서버에 맡긴다

손절이나 익절을 자동화하려면 보통 가격을 계속 지켜보는 감시 프로그램이 필요하다. 문제는 그 프로그램이 도는 컴퓨터가 꺼지거나 잠들면 감시가 멈춘다는 것이다. 조건주문은 이 감시를 증권사 서버에 넘긴다.
타입은 세 가지다. SINGLE은 조건 하나만 감시한다. OCO는 두 조건을 동시에 감시하다 하나가 충족되면 나머지를 자동 취소한다. 손절선과 익절선을 함께 걸어 두는 전형적인 방식이며, 두 조건 모두 매도이고 첫 번째 감시가가 현재가보다 높고 두 번째 감시가가 현재가보다 낮아야 한다. OTO는 첫 번째 조건이 체결되면 그때부터 두 번째 조건 감시를 시작한다. 첫 번째가 매수, 두 번째가 매도인 구조라 진입과 청산을 한 번에 등록할 수 있다.
제약도 알아 둬야 한다. OCO와 OTO는 지정가만 지원하고, 한 종목에 그룹 조건주문은 하나만 걸 수 있다. 이미 조건을 충족한 가격으로 등록하면 거절된다. SINGLE은 종목당 개수 제한이 없다.
직접 만든 감시기와 비교하면 트레이드오프가 분명하다. 조건주문은 서버가 감시하니 내 컴퓨터 상태와 무관하고 반응도 빠르다. 대신 조건이 단순한 가격 기준으로 제한된다. 이동평균이나 신고가 돌파처럼 계산이 필요한 조건은 여전히 내 쪽에서 판정해 주문을 내야 한다. 실무적으로는 손절·익절 같은 방어선은 조건주문에 맡기고, 계산이 필요한 진입 판단만 내 스크립트가 맡는 조합이 편하다.
curl -s -X POST 'https://openapi.tossinvest.com/api/v1/conditional-orders' \
-H "Authorization: Bearer $TOKEN" \
-H 'X-Tossinvest-Account: 1' \
-H 'Content-Type: application/json' \
-d '{
"symbol": "005930",
"type": "SINGLE",
"quantity": 100,
"orderType": "LIMIT",
"clientOrderId": "my-cond-20260725-001",
"expireDate": "2026-09-10",
"first": {
"orderSide": "SELL",
"triggerPrice": "295",
"orderPrice": "295"
}
}'호출 한도와 에러를 다루는 법
모든 API는 클라이언트와 API 그룹 단위로 초당 요청 수가 제한된다. 시세는 초당 10회, 주문은 초당 6회인데 장 시작 직후 09:00부터 09:10까지는 초당 3회로 낮아진다. 계좌 목록 조회는 초당 1회로 가장 빡빡하다. 계좌 번호처럼 거의 바뀌지 않는 값은 한 번 받아 캐시해 두는 게 맞다.
한도를 넘기면 429가 돌아온다. 응답 헤더의 Retry-After만큼 기다렸다 재시도하고, 반복되면 1초, 2초, 4초 식으로 간격을 늘리며 약간의 무작위 지연을 섞는다. 정상 응답에도 남은 요청 수가 헤더로 오므로, 그 값이 줄어들면 미리 속도를 늦추는 편이 안전하다.
에러는 형식이 일정해서 코드만 보고 분기하면 된다. 토큰이 만료됐으면 expired-token, 잔고가 모자라면 insufficient-buying-power, 주문 접수 시간이 아니면 order-hours-closed, 가격이 상하한가를 벗어나면 price-out-of-range가 돌아온다. 같은 멱등키로 다른 내용을 보내면 idempotency-key-conflict가 뜬다. 문의할 일이 생기면 응답의 requestId를 함께 남기면 된다.
에이전트에게 스크립트를 맡길 때는 이 에러 처리를 처음부터 요구하는 게 좋다. 그냥 만들라고 하면 성공 경로만 짜 놓는 경우가 많고, 그 상태로 자동 실행에 걸면 조용히 실패한다.
정리하면, 이 순서로 시작하면 된다
첫째, 토스증권 WTS 설정에서 Open API 키를 발급받고 허용 IP를 등록한다. 둘째, 터미널에서 curl로 토큰을 받아 종목 정보 한 건을 조회해 본다. 여기까지가 연결 확인이다.
셋째, Claude Code나 Codex를 설치하고 키를 .env에 넣은 뒤 보유 주식 조회 스크립트를 만들게 한다. 앱 화면과 숫자를 대조한다. 넷째, 주문 스크립트를 만들되 연습 모드를 기본값으로 두고 실주문 게이트를 먼저 넣는다. 다섯째, 아주 작은 수량으로 실주문을 한 번 내 보고 정정과 취소까지 확인한다. 여섯째, 손절·익절 같은 방어선을 조건주문으로 옮긴다.
마지막으로 당연하지만 짚어 둔다. 자동매매는 규칙이 틀리면 그 틀린 규칙을 빠르고 성실하게 반복한다. 처음에는 반드시 소액으로, 연습 모드로 충분히 돌려 본 뒤에 실행하고, 결과에 대한 책임은 전적으로 본인에게 있다.
규칙 자체가 실제로 돈을 벌었을지 검증하는 방법, 즉 과거 데이터로 매매 규칙을 시험하는 백테스트는 다음 편에서 다룬다.
