가격 스트림 레퍼런스
하나의 WebSocket 연결로 상품 현물 가격과 FX 환율을 제공하며, 구독 항목별 초기 가격과 가격 변경 시 업데이트를 전송
접근 권한 및 제한
가격 스트림은 Basic 및 Pro 요금제에서 사용할 수 있습니다. Free 요금제 키에는 plan_upgrade_required가 반환되고 연결이 종료됩니다.
가격, 이벤트, 예측 스트림에는 공통 동시 연결 제한이 적용됩니다. Free는 1개, Basic은 2개, Pro는 10개입니다. 각 연결은 월간 할당량에서 호출 1회를 사용합니다.
연결
API 키를 Authorization: Bearer 헤더에 넣고 wss://api.narwhalapi.com/v1/prices/stream에 연결합니다.
브라우저는 WebSocket 연결에 해당 헤더를 설정할 수 없습니다. 서버에서 POST /v1/prices/stream-ticket을 보낸 다음, 반환된 티켓을 ?ticket=에 넣어 연결합니다. 티켓은 한 번만 사용할 수 있고 30초 후 만료되며, 허용된 오리진이 필요합니다. 예측 스트림에도 동일한 티켓 규칙이 적용됩니다.
구독
서버가 {"type":"ready"}를 보냅니다. 5초 이내에 구독 메시지 하나를 보내세요:
{
"action": "subscribe",
"commodities": [
{
"commodity": "XAU",
"currency": "USD"
}
],
"fx": [
{
"base": "USD",
"currencies": [
"EUR",
"JPY"
]
}
]
}commodities:GET /v1/commodities/spot/{commodity}/{currency}에서 지원하는 상품 및 통화 쌍을 최대 20개 지정할 수 있습니다.fx: 기준 통화를 최대 5개 지정할 수 있습니다.currencies는 선택 사항입니다. 생략하면 해당 기준 통화에 제공되는 모든 통화를 받으며, 지정할 경우 최대 64개 통화를 나열할 수 있습니다.
서버가 {"type":"subscribed"}로 응답하고 구독한 각 가격을 한 번씩 보냅니다. 이후에는 가격이 변경될 때만 보냅니다. 가격은 약 1초마다 확인합니다.
구독을 변경하려면 다시 연결하세요. 두 번째 구독 메시지를 보내면 resubscribe_required와 함께 연결이 종료됩니다.
메시지
가격 메시지의 본문은 REST 엔드포인트의 응답 본문과 같으며, 소수 자릿수, 대체 값, 오래된 데이터 표시 플래그도 동일합니다.
| 메시지 | 내용 또는 전송 주기 |
|---|---|
ready | 연결이 열릴 때 전송됩니다. 5초 이내에 구독하세요. |
subscribed | 구독이 수락되었습니다. |
commodity | spot에는 GET /v1/commodities/spot/{commodity}/{currency}의 응답 본문이 들어 있습니다. |
fx | rate에는 GET /v1/fx/rates/{base}의 rates 항목 하나와 base, market_session이 들어 있습니다. |
heartbeat | as_of와 함께 30초마다 전송됩니다. |
pong | {"action":"ping"}에 대한 응답입니다. |
error | 오류 code가 포함되며, 이후 연결이 종료됩니다. |
{
"type": "commodity",
"spot": {
"symbol": "XAU-USD",
"price": "4195.86",
"currency": "USD",
"unit": "troy_ounce",
"timestamp": "2026-10-11T06:25:00Z",
"stale": false
}
}{
"type": "fx",
"base": "USD",
"market_session": "open",
"rate": {
"currency": "EUR",
"rate": "0.8924",
"timestamp": "2026-10-09T00:00:00Z",
"stale": false
}
}연결 유지
{"action":"ping"}을 보내면 {"type":"pong"}을 받습니다. 서버는 30초마다 heartbeat도 보냅니다. 메시지를 바로 읽으세요. 5초 동안 읽지 않는 클라이언트는 slow_consumer와 함께 연결이 종료됩니다.
연결당 최대 30프레임을 보낼 수 있습니다. 다시 연결하면 구독한 각 가격이 다시 전송되지만, 놓친 변경 사항은 재전송되지 않습니다.
오류
오류는 {"type":"error","code":"..."} 형식으로 전달된 후 연결이 종료됩니다.
| 코드 | 의미 |
|---|---|
unauthorized | API 키 또는 티켓이 없거나 유효하지 않습니다. |
plan_upgrade_required | 이 스트림을 사용하려면 Basic 또는 Pro 요금제가 필요합니다. |
stream_limit | 요금제의 스트림 동시 연결 제한에 도달했습니다. |
quota_unavailable | 월간 할당량을 모두 사용했거나 할당량을 확인할 수 없습니다. |
subscribe_required | 준비 메시지 이후 5초 이내에 구독 메시지를 받지 못했습니다. |
resubscribe_required | 두 번째 구독 메시지가 전송되었습니다. 구독을 변경하려면 다시 연결하세요. |
invalid_command | 메시지가 구독 또는 ping 동작이 아닙니다. |
invalid_frame | 메시지가 유효한 JSON이 아니거나 구독 제한을 초과합니다. |
commodity_not_supported | 구독 메시지에 포함된 상품이 제공되지 않습니다. |
currency_not_supported | 구독 메시지에 포함된 통화가 제공되지 않습니다. |
revoked | API 키가 폐기되었거나 연결 임대가 해제되었습니다. |
slow_consumer | 클라이언트가 5초 동안 메시지를 읽지 않았습니다. |
command_limit | 클라이언트가 하나의 연결에서 30프레임을 초과하여 보냈습니다. |
unavailable | 스트림을 일시적으로 사용할 수 없습니다. 나중에 다시 연결하세요. |
문서