토스증권 OpenAPI 실전 — 공식 문서에 없는 함정 4개

토스증권이 개인에게 OpenAPI를 열었습니다. 잔고·주문내역을 코드로 받아올 수 있다는 건, 매매일지를 손으로 쓰던 사람에겐 해방 선언이죠.

저도 바로 붙였습니다. 그리고 몇 주에 걸쳐, 공식 문서만 믿으면 안 되는 지점들을 온몸으로 확인했는데요.

이 글은 그 실측 기록입니다. 같은 길을 가실 분들이 제 시행착오를 건너뛰시길 바라며 씁니다.

[30초 요약] 토스증권 API의 함정 넷 — ①주문내역 페이징의 커서가 작동하지 않아 날짜를 당겨가는 수동 커서가 필요하고 ②상태값 CLOSED에는 취소·거부도 포함되며 ③원화 거래는 수수료·세금이 0으로 내려와 직접 보정해야 하고 ④호출이 잦으면 에러 대신 빈 응답으로 조용히 제한됩니다.

기본 연결은 쉽습니다

인증은 OAuth2 client_credentials 방식입니다. 발급받은 키로 토큰을 받으면 약 24시간 유효하고요.

“`python import requests

token = requests.post( “https://apis.tossinvest.com/oauth2/token”, data={“grant_type”: “client_credentials”, “client_id”: CLIENT_ID, “client_secret”: CLIENT_SECRET}, ).json()[“access_token”]

accounts = requests.get( “https://apis.tossinvest.com/api/v1/accounts”, headers={“Authorization”: f”Bearer {token}”}, ).json() “`

계좌 목록에서 계좌 식별자(accountSeq)를 얻고, 이후 보유·예수금 조회에는 `X-Tossinvest-Account` 헤더로 이 값을 실어 보냅니다. 여기까지는 문서대로 됩니다. 문제는 지금부터입니다.

함정 1 — 페이징 커서가 작동하지 않습니다

주문내역(/orders)에 기간을 주고 조회하면, 최신순으로 최대 100건만 옵니다. 응답에 nextCursor 필드가 있어서 “아, 커서 페이징이구나” 했는데 — 항상 비어 있습니다. hasNext는 true인데 커서가 없어요.

해법은 수동 커서입니다. 받은 100건 중 가장 오래된 체결 시각을 다음 요청의 종료일(to)로 당겨서 다시 조회하고, 시작일에 닿을 때까지 반복합니다. 중복은 주문 ID로 걸러내고요. 우아하진 않지만 확실하게 전체 이력을 받아옵니다.

함정 2 — CLOSED는 “체결완료”가 아닙니다

주문 상태 필터에 CLOSED를 주면 끝난 주문들이 옵니다. 저는 이걸 “체결된 주문”으로 읽었습니다. 아니었습니다. CLOSED는 ‘종결’이라는 뜻이고, 취소된 주문과 거부된 주문도 포함됩니다.

이걸 모르고 매매 기록을 쌓으면 어떻게 되냐면 — 취소한 주문이 매매로 집계돼 수익률 계산이 통째로 오염됩니다. 저는 수백 건을 쌓은 뒤에야 숫자가 앱과 다른 걸 발견했고, 원인을 찾는 데 한참 걸렸습니다.

실제 체결만 원하면 execution.filledQuantity가 0보다 큰 것만 걸러야 합니다. 한 줄짜리 필터인데, 이 한 줄이 데이터 전체의 신뢰를 결정합니다.

함정 3 — 원화 거래의 수수료·세금이 0으로 옵니다

응답에 commission과 tax 필드가 있습니다. 달러 거래는 값이 제대로 들어옵니다. 그런데 원화(국내 주식) 거래는 둘 다 0으로 내려옵니다.

실현손익을 계산해서 토스 앱의 숫자와 맞춰보면 계속 어긋나는 이유가 이거였습니다. 해법은 직접 보정 — 매도 금액에 증권거래세(2026년 기준 코스닥 0.20% 등, 시장별 상이)를 계산해서 차감하면 앱 숫자와 맞아떨어집니다.

“API가 필드를 준다 ≠ 값이 채워져 있다”는 교훈을 여기서 배웠습니다.

함정 4 — 조용한 호출 제한

과거 이력을 한 번에 백필하려고 연속 호출을 돌리다 발견했습니다. 8회쯤 연속 호출하면 제한에 걸리는데, 429 에러가 아니라 정상 응답 모양의 빈 데이터가 옵니다.

에러가 나면 코드가 멈추기라도 하죠. 빈 응답은 “이 구간엔 거래가 없었나 보다”로 조용히 넘어가게 만듭니다. 데이터 누락을 며칠 뒤에야 알아챘습니다. 대량 조회에는 호출 사이 쿨다운을 넣으시고, “빈 응답 = 거래 없음”이라고 단정하는 코드는 피하세요.

숨은 보너스 엔드포인트

문서에서 찾기 어려운데 존재하는 것들 — buying-power(통화별 예수금)와 exchange-rate(환율)입니다. 예수금까지 합쳐야 진짜 계좌 상태가 보이고, 원화·달러가 섞인 계좌의 수익률 계산엔 환율 엔드포인트가 유용합니다.

자주 묻는 질문

토스증권 API는 누구나 쓸 수 있나요? 개발자 포털에서 신청하면 개인도 발급받을 수 있습니다. 조회 중심으로 시작하시길 권합니다 — 주문 API는 실계좌 리스크가 다른 차원입니다.

API 키는 어디에 보관하나요? 코드에 하드코딩하지 말고 환경변수나 별도 파일(버전 관리 제외)에 두세요. 키가 유출되면 계좌 조회 권한이 통째로 넘어갑니다.

과거 거래 전체를 받을 수 있나요? 수동 커서(함정 1)로 연초까지 받는 데 성공했습니다. 다만 함정 4의 호출 제한 때문에 백필은 천천히 나눠서 돌리세요.

앱 실현손익과 API 계산이 안 맞아요. 십중팔구 함정 2(취소 주문 포함)나 함정 3(원화 세금 미반영)입니다. 이 둘을 잡으니 저는 앱 숫자와 원 단위 수준까지 일치했습니다.

함께 읽으면 좋은 글

증권사 API의 함정은 회사마다 다릅니다 — 한국투자증권 쪽은 KIS API 함정 모음에 정리했습니다. 받아온 데이터로 알림을 쏘는 단계는 텔레그램 봇 10분 구축이 이어집니다. 예수금을 어디 두는 게 유리한지는 증권사 예수금 이자 비교 참고.

API 문서는 지도이고 실측은 지형입니다 — 돈이 걸린 데이터라면, 지형을 믿으세요.

※ 본 글은 2026년 7월 실측 기준이며, API 사양은 예고 없이 변경될 수 있습니다. 투자 권유가 아닙니다.

Leave a Comment