# 종목·시세

시세·종목 API는 전부 **공개**라서 토큰 없이도 호출돼요. 토큰을 실어 보내도 괜찮아요.

| 메서드 | 경로                              | 설명                                                |
| ------ | --------------------------------- | --------------------------------------------------- |
| GET    | `/v1/stocks`                      | 종목 목록(최대 1000개) / `q`로 검색(최대 50개)      |
| GET    | `/v1/stocks?symbol=…`             | 여러 종목 한 번에(최대 100개)                       |
| GET    | `/v1/stocks/{symbol}`             | 종목 상세                                           |
| GET    | `/v1/stocks/{symbol}/disclosures` | 거래소 공시(거래정지·재개, 관리종목, 종목명 변경)   |
| GET    | `/v1/market/price/{symbol}`       | 현재가 스냅샷 + 호가                                |
| GET    | `/v1/market/prices?symbol=…`      | 여러 종목 현재가 스냅샷 한 번에(최대 100개)         |
| GET    | `/v1/market/orderbook/{symbol}`   | 호가                                                |
| GET    | `/v1/market/candles/{symbol}`     | 캔들(분·일·주·월·년봉)                              |
| GET    | `/v1/market/trades/{symbol}`      | 최근 체결                                           |
| GET    | `/v1/market/popular?limit=`       | 인기 종목(직전 세션 거래대금 순, 세션 마감 때 갱신) |
| GET    | `/v1/market/rankings`             | 실시간 순위(홈 화면의 인기·거래량·급상승·급하락)    |

## 종목 목록

`GET /v1/stocks`

| 쿼리    | 설명              |
| ------- | ----------------- |
| `limit` | 1~1000. 기본 1000 |

전체 상장 종목을 이름순으로 돌려줘요. **한 번에 최대 1000개**이고, 그 이상은 검색으로 찾아야 해요. 관리종목(`hidden: true`)도 포함되니 "발견"용 목록을 만들 땐 걸러내세요.

**응답 200** `Stock[]`

```json
[
  {
    "symbol": "FOXX",
    "name": "FOXX",
    "species": "여우",
    "status": "listed",
    "tags": ["여우", "수인"],
    "lastPrice": 1234,
    "changeRate": 0.0523,
    "volume": 812,
    "characterId": "5b0c7a3e-...",
    "coverImageUrl": "https://images.furstock.trade/p/...",
    "listedAt": "2026-09-12T08:00:00.000Z",
    "tradingHalted": false,
    "haltReason": null,
    "hidden": false,
    "hideReason": null,
    "hideLocked": false,
    "bio": "여우 수인 캐릭터..."
  }
]
```

| 필드            | 설명                                                                    |
| --------------- | ----------------------------------------------------------------------- |
| `lastPrice`     | 현재가(원)                                                              |
| `changeRate`    | 세션 시작가 대비 등락률. `0.0523` = +5.23%                              |
| `volume`        | 현재 세션 누적 거래량(주)                                               |
| `coverImageUrl` | 캐릭터 대표 이미지. 종목을 화면에 표시할 땐 이 이미지를 함께 보여주세요 |
| `tradingHalted` | `true`면 관리자 거래정지 — 주문이 거부돼요                              |
| `hidden`        | `true`면 숨겨진 종목 — 검색·순위에서 빠지지만 거래는 돼요               |
| `hideLocked`    | `hidden`일 때 `true`면 관리자 지정 관리종목, `false`면 상장주가 숨긴 것 |

## 종목 검색

`GET /v1/stocks?q=여우`

| 쿼리    | 설명                                        |
| ------- | ------------------------------------------- |
| `q`     | 검색어. 종목명·태그 부분일치, 대소문자 무시 |
| `limit` | 1~50. 기본 50                               |

홈 화면 검색창과 같은 규칙이에요. 관리종목은 결과에서 빠져요. 응답 모양은 종목 목록과 같아요.

## 여러 종목 조회

`GET /v1/stocks?symbol=FOXX&symbol=WOLF`

화면에 보이는 몇 종목의 정보만 필요할 땐 전체 목록을 받지 말고 이걸 쓰세요. `symbol`을 1~100번 반복해서 넘기고, 응답 모양은 종목 목록과 같아요. 관리종목도 포함되고, 없는 종목은 빠지며, 순서는 요청 순서를 따라요. `symbol`이 있으면 `q`·`limit`은 무시돼요.

## 종목 상세

`GET /v1/stocks/{symbol}` → `Stock` 하나. 없으면 `404`.

## 공시

`GET /v1/stocks/{symbol}/disclosures` → 최신순 최대 50개

```json
[{ "kind": "trading_halted", "message": "관리자에 의해 거래가 정지되었습니다: ...", "createdAt": "..." }]
```

`kind`: `trading_halted` · `trading_resumed` · `hidden` · `unhidden` · `symbol_changed`

상장주 소유자가 쓰는 뉴스는 [커뮤니티·소셜](/developers/community)의 저널 API에 있어요.

## 현재가

`GET /v1/market/price/{symbol}`

```json
{
  "symbol": "FOXX",
  "sessionId": "0f6c...",
  "seq": 1790226600668,
  "lastPrice": 1234,
  "openPrice": 1173,
  "high": 1260,
  "low": 1150,
  "bandLow": 821,
  "bandHigh": 1524,
  "volume": 812,
  "orderbook": {
    "bids": [
      [1233, 10],
      [1232, 20]
    ],
    "asks": [
      [1235, 10],
      [1236, 20]
    ]
  },
  "ts": 1790226600668
}
```

| 필드                   | 설명                                                      |
| ---------------------- | --------------------------------------------------------- |
| `openPrice`            | 이번 세션 시작가                                          |
| `bandLow` / `bandHigh` | 하한가 / 상한가(시작가 ±30%). 이 밖으로는 체결되지 않아요 |
| `orderbook`            | 호가(아래 참고)                                           |
| `ts`                   | 스냅샷 시각(epoch ms)                                     |

여러 종목을 볼 때는 종목마다 따로 부르지 말고 `GET /v1/market/prices`로 한 번에 받으세요. `symbol`을 1~100번 반복해서 넘기면(`?symbol=FOXX&symbol=WOLF`) 위와 같은 스냅샷의 배열이 요청 순서대로 와요. 없는 종목은 빠져요. 시세 REST는 최대 1초 캐시되니, 1초보다 자주 부를 필요는 없어요. 실시간 변동은 [웹소켓](/developers/realtime)으로 받는 게 가장 좋아요.

## 호가

`GET /v1/market/orderbook/{symbol}` → `{ bids, asks }`

각 단계는 `[가격, 그 가격까지의 누적 수량]`이에요. 퍼스톡은 실제 주문장 대신 **가격 곡선**으로 체결하기 때문에, 호가는 "지금 이만큼 사면(팔면) 가격이 어디까지 움직이는지"를 곡선에서 계산해 보여주는 **합성 호가**예요. 다른 참가자가 주문을 내면 곡선이 움직이므로, 실제 체결가는 주문 시점의 곡선으로 정해져요.

## 캔들

`GET /v1/market/candles/{symbol}?unit=10m&before=1790226000`

| 쿼리     | 설명                                                                                                                           |
| -------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `unit`   | `1m`(기본), `3m`, `5m`, `10m` … N분봉(N=1~1440, 차트 화면은 1·3·5·10·15·30·60·120·240분), `1d`, `1w`, `1M`, `1y` 일·주·월·년봉 |
| `before` | (선택) 봉 시작 시각(epoch **초**). 이 시각보다 앞선 봉만 줘요 — 과거를 이어 받을 때                                            |

```json
[{ "time": 1790226000, "open": 1200, "high": 1260, "low": 1190, "close": 1234, "volume": 55 }]
```

**빈틈없는 봉 최대 500개**를 오래된 순서로 줘요. `time`은 봉 시작 시각(epoch **초**)이에요. 진행 중인 봉(지금 분봉, 오늘 일봉 등)도 지금까지의 체결로 들어 있어요.

**거래가 없던 구간은 거래정지처럼 표시해요.** 체결이 없던 봉은 직전 종가 하나로 시가·고가·저가·종가가 모두 같은 1자 봉이 되고, `volume`은 0이에요. 그래서 봉 사이에 빈 시간이 없어요. 상장(첫 체결) 이전은 채우지 않아요.

**과거를 끝까지 받으려면** 받은 봉 중 가장 오래된 `time`을 `before`로 넘겨 다시 부르세요. 500개보다 적게 오면 그 종목의 첫 봉까지 다 받은 거예요.

봉은 **한국 시간(KST)** 기준으로 끊어요. 120·240분봉과 일봉은 KST 00시, 주봉은 월요일, 월봉은 1일, 년봉은 1월 1일에 시작해요.

응답 헤더 `x-last-trade-seq`는 이 응답에 이미 반영된 가장 최근 체결의 `seq`예요(`before` 없이 부른 최신 페이지에서만 의미가 있어요). 아래 최근 체결(`/v1/market/trades`)을 폴링해 봉을 실시간으로 갱신한다면, `seq`가 이 값 이하인 체결은 건너뛰세요(두 번 세지 않도록).

## 최근 체결

`GET /v1/market/trades/{symbol}?limit=50` (최대 200, 최신순)

```json
[{ "symbol": "FOXX", "seq": 918273, "price": 1234, "quantity": 3, "side": "buy", "ts": 1790226600668 }]
```

`seq`는 체결마다 고유하고 계속 커져요. 폴링하면서 이미 본 체결을 거를 때 쓰세요. `side`는 그 체결을 일으킨 주문의 방향이에요.

## 실시간 순위

`GET /v1/market/rankings?type=value&limit=20`

| `type`        | 정렬                                   | 홈 화면  |
| ------------- | -------------------------------------- | -------- |
| `value`(기본) | 거래대금(`lastPrice × volume`) 높은 순 | 인기     |
| `volume`      | 거래량 많은 순                         | 거래량순 |
| `gainers`     | 등락률 높은 순                         | 급상승   |
| `losers`      | 등락률 낮은 순                         | 급하락   |

`limit` 1~50(기본 20). 관리종목은 빠져요.

```json
[
  {
    "symbol": "FOXX",
    "name": "FOXX",
    "species": "여우",
    "lastPrice": 1234,
    "changeRate": 0.0523,
    "volume": 812,
    "tradingValue": 1002008
  }
]
```
