{
  "openapi": "3.0.3",
  "info": {
    "title": "NH투자증권 Open API — 공통 (Common: 인증·계좌)",
    "version": "v1",
    "description": "자산군과 무관한 **플랫폼 공통 API** 문서입니다.\n\n- 접근 토큰 발급(`/oauth2/token`)과 계좌 목록 조회(`/n2/acctinfo`)를 포함합니다.\n- 이 두 API 는 모든 자산군 조회·주문의 선행 단계입니다: 토큰 발급 → 계좌목록 조회 → 각 계좌번호로 자산군 API 호출.\n- `/oauth2/token` 은 쿼리 파라미터 + form-urlencoded 방식, `/n2/acctinfo` 는 다른 REST API 와 동일하게 `Input_0`/`Output_0` 봉투를 사용합니다.\n\n**환경 제공 범위**: 대부분 API 는 모의투자·운영 모두 제공. **예외: 접근토큰발급(`/oauth2/token`) 은 운영(api) 전용**(모의투자 미제공)."
  },
  "servers": [
    {
      "url": "https://api.nhplug.com:8443",
      "description": "🔴 운영 (Live) — 실제 주문 체결 [기본]"
    },
    {
      "url": "https://moapi.nhplug.com:8443",
      "description": "🟢 모의투자 (Mock) — 교육이수·개발·검증"
    }
  ],
  "tags": [
    {
      "name": "인증 (Auth)"
    },
    {
      "name": "계좌 (Account)"
    }
  ],
  "paths": {
    "/oauth2/token": {
      "post": {
        "operationId": "commonAuthIssueToken",
        "summary": "접근 토큰 발급",
        "tags": [
          "인증 (Auth)"
        ],
        "description": "⚠️ **모의투자 미제공 — 운영(api.nhplug.com:8443) 에서만 발급 가능합니다.** 발급받은 access token 은 모의투자·운영 호출 모두에 사용합니다.\n\n🔑 **토큰은 24시간(expires_in=86400) 유효합니다. 반드시 캐시해서 재사용하세요.**\n- 매 API 호출마다 재발급하지 마세요. 재발급은 보안 알림을 유발하며, 알림이 쌓이면 실제 이상 발급을 구분할 수 없게 됩니다.\n- 프로세스 메모리 캐시만으로는 부족합니다(스크립트는 실행마다 새 프로세스). 파일 등 프로세스 간 공유 캐시에 저장하세요.\n- 재발급 조건은 401(토큰 무효)뿐입니다. 429(유량 초과) 재시도에는 기존 토큰을 그대로 사용하세요.\n\n앱키/앱시크릿으로 access token 발급. 쿼리 파라미터 + Content-Type application/x-www-form-urlencoded. 발급 토큰은 만료 전까지 재사용(매 호출 재발급 금지).",
        "parameters": [
          {
            "name": "appkey",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "발급받은 앱키"
          },
          {
            "name": "appsecretkey",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "발급받은 앱시크릿"
          },
          {
            "name": "grant_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "default": "client_credentials"
            },
            "description": "고정값 client_credentials"
          },
          {
            "name": "scope",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "default": "oob"
            },
            "description": "고정값 oob"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "토큰 발급 성공",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": {
                      "type": "string",
                      "description": "접근 토큰"
                    },
                    "token_type": {
                      "type": "string",
                      "description": "토큰 유형 (예: Bearer)"
                    },
                    "expires_in": {
                      "type": "integer",
                      "description": "만료까지 남은 초 (24시간 = 86400). 이 시간까지 토큰을 캐시해 재사용할 것",
                      "example": 86400
                    },
                    "scope": {
                      "type": "string",
                      "description": "scope"
                    }
                  },
                  "required": [
                    "access_token"
                  ]
                }
              }
            }
          }
        },
        "servers": [
          {
            "url": "https://api.nhplug.com:8443",
            "description": "🔴 운영 (Live) — 접근토큰발급은 운영에서만 제공"
          }
        ],
        "x-available-env": [
          "live"
        ]
      }
    },
    "/n2/acctinfo": {
      "post": {
        "operationId": "commonAccountList",
        "summary": "계좌 목록 조회",
        "tags": [
          "계좌 (Account)"
        ],
        "description": "자격증명(앱키/시크릿)에 연결된 보유 계좌 목록 조회. 입력 없음. 응답 acct_no 를 이후 잔고·주문 API 의 act_no 로 사용.\n\n응답 블록은 **데이터가 있을 때만 내려옵니다.** 블록이 없을 수 있으니 존재 여부를 먼저 확인하세요.\n\n**계좌구분(acct_type)에 따라 사용 도메인이 다릅니다.** 01=운영(api.nhplug.com:8443, 일반) · 02=운영(api.nhplug.com:8443, 주문대리인) · 03=모의투자(moapi.nhplug.com:8443). 대상 환경에 맞는 계좌를 선택하세요.",
        "security": [
          {
            "bearerAuth": [],
            "clientId": [],
            "clientSecret": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "Input_0": {
                    "type": "object",
                    "properties": {},
                    "description": "입력 파라미터 없음"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "계좌 목록 조회 성공",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "Output_0": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "acct_no": {
                            "type": "string",
                            "description": "계좌번호 (잔고·주문 API 의 act_no 로 사용). 이 계좌를 쓸 수 있는 도메인은 같은 항목의 acct_type 을 확인하세요(01·02=운영, 03=모의투자)."
                          },
                          "acct_type": {
                            "type": "string",
                            "description": "계좌구분코드 — 이 계좌를 사용할 수 있는 도메인이 결정됩니다. 01 = 운영(Live) 일반 계좌 → https://api.nhplug.com:8443. 02 = 운영(Live) 주문대리인 계좌 → https://api.nhplug.com:8443. 03 = 모의투자(Mock) 전용 계좌 → https://moapi.nhplug.com:8443. 계좌구분과 다른 도메인으로 호출하지 마세요."
                          }
                        }
                      }
                    },
                    "rsp_cd": {
                      "type": "string",
                      "description": "응답코드 (00000=정상)"
                    },
                    "rsp_msg": {
                      "type": "string",
                      "description": "응답메시지"
                    },
                    "cust_no": {
                      "type": "string",
                      "description": "고객번호"
                    }
                  }
                },
                "example": {
                  "rsp_cd": "00000",
                  "rsp_msg": "조회가 완료되었습니다.",
                  "cust_no": "100805701",
                  "Output_0": [
                    {
                      "acct_no": "20101036881",
                      "acct_type": "01"
                    },
                    {
                      "acct_no": "50051036881",
                      "acct_type": "03"
                    }
                  ]
                }
              }
            }
          }
        },
        "x-available-env": [
          "mock",
          "live"
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Authorization: Bearer {access_token}"
      },
      "clientId": {
        "type": "apiKey",
        "in": "header",
        "name": "x-client-id",
        "description": "앱키"
      },
      "clientSecret": {
        "type": "apiKey",
        "in": "header",
        "name": "x-client-secret",
        "description": "앱시크릿"
      }
    }
  },
  "x-instruments": {
    "note": "전 종목의 코드·종목명·업종·지수편입 여부 등 정적 종목정보는 REST API 가 아니라 종목마스터 파일(.mst)로 제공됩니다. 전 종목 목록을 조회하는 REST API 는 없습니다.",
    "download_url_pattern": "https://www.nhplug.com/instruments/<파일명>.mst",
    "auth_required": false,
    "auth_note": "토큰·헤더 없이 공개 다운로드",
    "file_count": 28,
    "categories": [
      "국내주식",
      "해외주식",
      "국내선물옵션",
      "해외파생",
      "장내채권"
    ],
    "format": [
      "인코딩 CP949 (UTF-8 아님)",
      "고정 길이 레코드. 파일 헤더 없음(0번 오프셋부터 첫 레코드)",
      "좌측정렬 + 공백(0x20) 우측 패딩. NUL 종료 문자열 아님 → 길이 기반 슬라이싱 후 우측 공백 제거",
      "레코드 끝 1바이트 LF(0x0A). CRLF 아님",
      "반드시 바이너리 모드(\"rb\")로 열 것 — 텍스트 모드는 CRLF 축약·0x1A EOF 처리로 레코드가 어긋남",
      "파일크기 % 레코드크기 == 0 을 먼저 검증할 것. 0 이 아니면 파일 손상 또는 구조체 불일치"
    ],
    "parsing_gotchas": [
      "지수옵션(m_optksp·m_moption·m_soption·m_woption·m_qoption)의 sPrice 는 실제 행사가 × 100 → 반드시 /100. 단 주식옵션(m_optstp)의 sValue 는 스케일 없음",
      "위클리옵션(m_woption·m_qoption)의 sMonth 는 YYMMWW(주차) — 날짜로 파싱 금지",
      "콜/풋 구분은 CP949 한글 2바이트(\"콜\"/\"풋\") — ASCII C/P 아님",
      "지수 편입 플래그는 == \"Y\" 로만 판정 (공백을 N 으로 오해하면 누락 발생)",
      "국내주식 한글종목명 선두 1바이트는 지수 마커(* KOSPI200 / # 코스닥150) — 정렬·검색 시 제거"
    ],
    "main_files": {
      "국내주식": "m_new_stock.mst",
      "해외주식": "m_gtsstock.mst",
      "지수옵션": "m_optksp.mst",
      "주식선물": "m_stkfut.mst",
      "장내채권": "bond_hts.mst"
    },
    "exception": "금현물은 마스터 파일이 없고 전문(IVOGLDREQ01)으로 조회합니다.",
    "struct_definition_url_pattern": "https://www.nhplug.com/instruments/<파일명>.h",
    "struct_definition_note": "마스터 파일(.mst)과 1:1 대응하는 .h 파일에 오프셋·길이·코드값·레코드크기가 정의되어 있습니다. 인증 불필요.",
    "main_struct_definitions": {
      "국내주식": "m_new_stock.h",
      "해외주식": "m_gtsstock.h",
      "지수옵션": "m_optksp.h",
      "주식선물": "m_stkfut.h",
      "장내채권": "bond_hts.h"
    }
  }
}
