English | 한국어
v1 API는 RESTful 경로 기반으로 변경되었습니다. 기존 v0 API도 계속 지원되며, 서버 설정에서 선택적으로 활성화/비활성화할 수 있습니다.
v0 API의 사용 여부는 서버 설정에서 제어합니다:
| 설정 | 동작 |
|---|---|
| 레거시 API 활성화 (v0) 체크 | v0, v1 엔드포인트 모두 사용 가능 (기본값) |
| 레거시 API 활성화 (v0) 해제 | v0 엔드포인트 비활성화, v1만 사용 가능 |
설정 위치: 웹 관리자 → 서버 설정 → API 탭
| 기능 | v0 | v1 |
|---|---|---|
| 인증: 세션 쿠키 | ✅ | ✅ |
| 인증: JWT Bearer Token | ❌ | ✅ |
| 인증: API Key | ❌ | ✅ |
| 응답 URL 형식 | 절대 URL (http://{host}/...) |
상대 URL (/...) |
| 채널 목록 | GET /api/enum?what=channel |
GET /api/v1/channel |
| 시스템 정보 | GET /api/system?info |
GET /api/v1/system/info |
| PTZ 제어 | GET /api/channel/ptz?ch=1&home |
GET /api/v1/channel/1/ptz?home |
| 시스템 재시작 | GET /api/system?restart |
POST /api/v1/system/restart |
| 문서 | — | API 가이드 |
| 예제 | — | 9개 언어 |
| v0 | v1 |
|---|---|
GET /api/auth?login=... |
POST /api/v1/auth/login (JSON body) |
GET /api/auth?logout |
POST /api/v1/auth/logout (JSON body) |
참고:
GET /api/v1/auth?login=...은 보안상의 이유로 v1에서 차단되었습니다. 크레덴셜을 쿼리 스트링으로 전달해서는 안 됩니다. 대신POST /api/v1/auth/login을 사용하여 JSON 요청 본문으로 크레덴셜을 전송하십시오.
| v0 | v1 |
|---|---|
GET /api/info?all |
GET /api/v1/info?all |
| v0 | v1 |
|---|---|
GET /api/system?info |
GET /api/v1/system/info |
GET /api/system?info=os |
GET /api/v1/system/info?item=os |
GET /api/system?health |
GET /api/v1/system/health |
GET /api/system?health=cpu |
GET /api/v1/system/health?item=cpu |
GET /api/system?hddsmart |
GET /api/v1/system/hddsmart |
GET /api/system?hddsmart=1 |
GET /api/v1/system/hddsmart?disk=1 |
GET /api/system?restart |
POST /api/v1/system/restart |
GET /api/system?reboot |
POST /api/v1/system/reboot |
| v0 | v1 |
|---|---|
GET /api/status |
GET /api/v1/channel/status |
GET /api/status?ch=1,2,3 |
GET /api/v1/channel/status?ch=1,2,3 |
| v0 | v1 |
|---|---|
GET /api/enum?what=channel |
GET /api/v1/channel |
GET /api/enum?what=channel&staticSrc |
GET /api/v1/channel?staticSrc |
GET /api/enum?what=channel&caps |
GET /api/v1/channel?caps |
| v0 | v1 |
|---|---|
GET /api/channel/info |
GET /api/v1/channel/info |
GET /api/channel/info?caps&ch=1 |
GET /api/v1/channel/1/info?caps |
GET /api/channel/ptz?ch=1&home |
GET /api/v1/channel/1/ptz?home |
GET /api/channel/ptz?ch=1&move=0.5,0.5 |
GET /api/v1/channel/1/ptz?move=0.5,0.5 |
GET /api/channel/preset?ch=1&list |
GET /api/v1/channel/1/preset |
GET /api/channel/preset?ch=1&add&name=door |
POST /api/v1/channel/1/preset?name=door |
GET /api/channel/preset?ch=1&set=preset1 |
PUT /api/v1/channel/1/preset/preset1 |
GET /api/channel/preset?ch=1&rm=1 |
DELETE /api/v1/channel/1/preset/1 |
GET /api/channel/preset?ch=1&go=1 |
GET /api/v1/channel/1/preset/1/go |
GET /api/channel/relay?ch=1&list |
GET /api/v1/channel/1/relay |
GET /api/channel/relay?ch=1&on=uuid |
PUT /api/v1/channel/1/relay/uuid?state=on |
GET /api/channel/relay?ch=1&off=uuid |
PUT /api/v1/channel/1/relay/uuid?state=off |
GET /api/channel/aux?ch=1&on=0 |
PUT /api/v1/channel/1/aux/0?state=on |
GET /api/channel/reboot?ch=1 |
POST /api/v1/channel/1/reboot |
POST /api/channel |
POST /api/v1/channel |
DELETE /api/channel/1 |
DELETE /api/v1/channel/1 |
| v0 | v1 |
|---|---|
GET /api/find?what=recDays |
GET /api/v1/recording/days |
GET /api/find?what=recDays&ch=1 |
GET /api/v1/recording/days?ch=1 |
GET /api/find?what=recMinutes&... |
GET /api/v1/recording/minutes?... |
| v0 | v1 |
|---|---|
GET /api/enum?what=eventType |
GET /api/v1/event/type |
GET /api/enum?what=realtimeEvent |
GET /api/v1/event/realtime |
GET /api/find?what=eventLog |
GET /api/v1/event/log |
PUT /api/event/trigger |
PUT /api/v1/event/trigger |
| v0 | v1 |
|---|---|
GET /api/enum?what=lprSrc |
GET /api/v1/lpr/source |
GET /api/find?what=carNo |
GET /api/v1/lpr/log |
GET /api/find?what=carNo&keyword=12 |
GET /api/v1/lpr/log?keyword=12 |
GET /api/find?what=similarCarNo&keyword=1234 |
GET /api/v1/lpr/similar?keyword=1234 |
| v0 | v1 |
|---|---|
GET /api/enum?what=objectType |
GET /api/v1/object/type |
GET /api/enum?what=objectAttr&type=face |
GET /api/v1/object/attr?type=face |
GET /api/find?what=object |
GET /api/v1/object/log |
| v0 | v1 |
|---|---|
POST /api/searchFace |
POST /api/v1/face/search |
GET /api/searchFace?... |
GET /api/v1/face/search?... |
| v0 | v1 |
|---|---|
GET /api/vod |
GET /api/v1/vod |
GET /api/vod?ch=1&when=... |
GET /api/v1/vod?ch=1&when=... |
| v0 | v1 |
|---|---|
GET /api/enum?what=emergencyCall |
GET /api/v1/emergency |
| v0 | v1 |
|---|---|
POST /api/push |
POST /api/v1/push |
| v0 | v1 |
|---|---|
ws:///wsapi/subscribeEvents?topics=... |
ws:///wsapi/v1/events?topics=... |
| v0 | v1 |
|---|---|
ws:///wsapi/dataExport?ch=1&timeBegin=...&timeEnd=... |
ws:///wsapi/v1/export?ch=1&timeBegin=...&timeEnd=... |
인증 변경: v0는
auth=base64(user:pass)쿼리 파라미터를 사용하지만, v1은token={JWT}또는apikey={key}쿼리 파라미터를 사용합니다.
변경 전 (v0):
// Get channels
fetch('/api/enum?what=channel')
// PTZ control
fetch('/api/channel/ptz?ch=1&home')
// System restart
fetch('/api/system?restart')변경 후 (v1):
// Get channels
fetch('/api/v1/channel')
// PTZ control
fetch('/api/v1/channel/1/ptz?home')
// System restart
fetch('/api/v1/system/restart', {method: 'POST'})변경 전 (v0):
# Get channels
requests.get(f'{base}/api/enum', params={'what': 'channel'})
# PTZ control
requests.get(f'{base}/api/channel/ptz', params={'ch': 1, 'home': ''})
# System restart
requests.get(f'{base}/api/system', params={'restart': ''})변경 후 (v1):
# Get channels
requests.get(f'{base}/api/v1/channel')
# PTZ control
requests.get(f'{base}/api/v1/channel/1/ptz', params={'home': ''})
# System restart
requests.post(f'{base}/api/v1/system/restart')-
경로 기반 리소스: 채널 ID가 URL 경로에 포함됨
- v0:
/api/channel/ptz?ch=1 - v1:
/api/v1/channel/1/ptz
- v0:
-
RESTful HTTP 메서드: 상태 변경 작업에 적절한 HTTP 메서드 사용
- v0:
GET /api/system?restart - v1:
POST /api/v1/system/restart
- v0:
-
리소스 지향 URL: 리소스 중심의 URL 구조
- v0:
/api/enum?what=channel - v1:
/api/v1/channel
- v0:
-
일관된 파라미터 이름:
- v0:
info=os,health=cpu - v1:
item=os,item=cpu
- v0:
-
응답 URL 형식: v0는 절대 URL, v1은 상대 URL
- v0 (레거시):
"image": "http://nvr.example.com/storage/...","videoSrc": "http://nvr.example.com/watch?ch=1&when=..." - v1:
"image": "/storage/...","videoSrc": "/watch?ch=1&when=..." - v0 절대 URL의 host는 Canonical Host 설정(웹 관리자 → 서버 설정 → API)이 지정되어 있으면 그 값을 사용하고, 없으면 요청의
X-Host헤더로 fallback 합니다. - v1은 상대 URL을 반환하므로 클라이언트가 자신의 base URL을 prepend 합니다 — 리버스 프록시나 cross-origin 환경에서 유용합니다.
- v0 (레거시):
-
응답 필드명 참고사항 (v0/v1 동일):
- 채널 목록:
title(채널명),displayName(표시명,"CH{N}. {title}"형식) - VOD 응답: 스트림 URL은
src필드 (예:src.rtmp,src.flv) - 이벤트 유형:
id(유형 ID),code(하위 코드 배열) - 시스템 정보:
item=storage요청 시 응답 필드명은disk
- 채널 목록:
v1 API는 모든 엔드포인트에서 JWT Bearer Token 및 API Key 인증을 지원합니다. v1 엔드포인트에서는 세션 쿠키를 지원하지 않습니다.
| 기존 v0 인증 | v1 권장 방식 |
|---|---|
| 세션 쿠키 | JWT 로그인 (POST /api/v1/auth/login) - 크레덴셜은 JSON body로 전송 |
| 외부 시스템 연동 | API Key (X-API-Key 헤더) - 로그인 불필요 |
v0 API는 deprecated 되었으며, 보안 강화를 위해 설정에서 비활성화할 수 있습니다. v0 API는 쿼리 스트링을 통한 인증 정보 전달 등 보안에 취약한 방식을 사용하므로, v1 마이그레이션이 완료된 환경에서는 비활성화를 권장합니다.
비활성화 방법:
웹 서버 설정에서 "레거시 API 활성화 (v0)" 체크박스를 해제합니다.
비활성화 시 동작:
v0 API 호출 시 404 에러가 반환됩니다:
{
"code": -1,
"message": "Legacy API (v0) is disabled. Please use /api/v1/ endpoints."
}영향받는 엔드포인트:
| 구분 | 엔드포인트 |
|---|---|
| REST API | /api/auth, /api/info, /api/system, /api/enum, /api/find, /api/vod, /api/status, /api/channel/*, /api/push, /api/searchFace |
| WebSocket API | /wsapi/subscribeEvents, /wsapi/dataExport |