Channel API v2 가이드
HATEOAS 토큰 기반의 v2 API를 사용하여 숙소 검색부터 예약까지 완전한 흐름을 구현합니다.
Channel API v2 가이드
v2 API는 HATEOAS(Hypermedia as the Engine of Application State) 패턴을 채택한 새로운 Channel API입니다. 각 단계에서 발급된 토큰이 다음 단계로 연결되므로, 파라미터를 직접 조합하지 않고 응답에 포함된 링크를 따라가는 방식으로 예약 흐름을 구성합니다.
v1과의 주요 차이점
| 항목 | v1 | v2 |
|---|---|---|
| 인증 방식 | X-Api-Key 헤더 | X-Api-Key 헤더 (동일) |
| 예약 흐름 | 독립적인 API 호출 조합 | 토큰으로 연결된 4단계 흐름 |
| 가격 검증 | 별도 검증 없음 | Price Check 단계에서 가격 재확인 후 book 토큰 발급 |
| ID 형식 | 숫자형 property_id | property_id는 문자열, room/rate는 해시 ID |
| 인원 형식 | adults, children 별도 파라미터 | EPS 호환 occupancy 파라미터 ("2", "2-3,5") |
| 숙소 목록 | 없음 | 페이지 토큰 기반 페이지네이션 |
| 콘텐츠 API | 없음 | 숙소 상세, 객실 타입 조회 추가 |
v2 API의 기본 경로는 /api/channel/v2/ 입니다. v1과 동일한 API 키를 사용하며, 기존 v1 엔드포인트는 계속 지원됩니다.
전체 엔드포인트 목록
| HTTP 메서드 | 경로 | 설명 |
|---|---|---|
GET | /api/channel/v2/properties | 숙소 목록 조회 (페이지네이션) |
GET | /api/channel/v2/properties/{id} | 숙소 상세 조회 |
GET | /api/channel/v2/properties/{id}/roomtypes | 객실 타입 목록 조회 |
GET | /api/channel/v2/properties/availability | 가용성 검색 (Step 1) |
GET | /api/channel/v2/properties/{propertyId}/rooms/{roomId}/rates/{rateId} | 가격 확인 (Step 2) |
POST | /api/channel/v2/bookings | 예약 생성 (Step 3) |
GET | /api/channel/v2/bookings/retrieve | 예약 조회 (Step 4a) |
PUT | /api/channel/v2/bookings/cancel | 예약 취소 (Step 4b) |
예약 4단계 흐름
v2의 예약 흐름은 토큰으로 연결된 4단계로 구성됩니다.
Step 1: Availability Search
날짜/인원으로 가용 객실을 검색합니다. 응답의 각 요금에 price_check 링크(토큰 포함)가 포함됩니다.
Step 2: Price Check
price_check 링크를 호출하여 가격을 재확인합니다. 성공 시 book 토큰이 발급됩니다.
Step 3: Booking
book 토큰과 투숙객 정보로 예약을 생성합니다. 응답에 retrieve와 cancel 링크가 포함됩니다.
Step 4: Retrieve / Cancel
retrieve 링크로 예약 상세를 조회하거나, cancel 링크로 예약을 취소합니다.
Step 1: 가용성 검색
GET /api/channel/v2/properties/availability
날짜, 인원, 숙소 ID를 지정하여 가용 객실과 요금을 조회합니다.
쿼리 파라미터
| 파라미터 | 필수 | 설명 | 예시 |
|---|---|---|---|
checkin | ✅ | 체크인 날짜 | 2026-04-01 |
checkout | ✅ | 체크아웃 날짜 | 2026-04-03 |
occupancy | ✅ | 인원 (반복 가능) | 2 또는 2-3,5 |
property_id | ✅ | 숙소 ID (반복 가능) | 12345 |
currency | - | 통화 코드 (기본값: KRW) | KRW |
language | - | 언어 코드 (기본값: ko-KR) | ko-KR |
occupancy 형식: EPS 호환 포맷을 사용합니다.
"2"— 성인 2명"2-3,5"— 성인 2명, 어린이 3세·5세
Step 1: 가용성 검색
응답 구조
[
{
"property_id": "12345",
"status": "available",
"rooms": [
{
"id": "a1b2c3d4",
"room_name": "디럭스 더블룸",
"rates": [
{
"id": "e5f6g7h8",
"status": "available",
"available_rooms": 5,
"refundable": true,
"occupancy_pricing": {
"2": {
"nightly": [
[
{ "type": "base_rate", "currency": "KRW", "value": 150000 },
{ "type": "tax_and_service_fee", "currency": "KRW", "value": 15000 }
],
[
{ "type": "base_rate", "currency": "KRW", "value": 150000 },
{ "type": "tax_and_service_fee", "currency": "KRW", "value": 15000 }
]
],
"totals": {
"inclusive": {
"request_currency": { "currency": "KRW", "value": 330000 }
}
}
}
},
"bed_groups": {
"37321": {
"id": "37321",
"description": "1 King Bed",
"links": {
"price_check": {
"method": "GET",
"href": "/api/channel/v2/properties/12345/rooms/a1b2c3d4/rates/e5f6g7h8?token=eyJ...",
"expires": "2026-04-01T10:30:00.000Z"
}
}
}
},
"cancel_penalties": [],
"amenities": {},
"promotions": null,
"deposits": []
}
]
}
]
}
]
price_check 토큰에는 유효 기간이 있습니다. expires 필드를 확인하고, 만료 전에 Step 2를 호출하세요. 만료된 토큰으로 요청하면 410 Gone이 반환됩니다.
Step 2: 가격 확인 (Price Check)
GET /api/channel/v2/properties/{propertyId}/rooms/{roomId}/rates/{rateId}?token=
Step 1 응답의 price_check 링크를 그대로 호출합니다. URL을 직접 조합하지 말고 응답에 포함된 href를 사용하세요.
경로 파라미터
| 파라미터 | 설명 |
|---|---|
propertyId | 숙소 ID (Step 1 property_id) |
roomId | 객실 해시 ID (Step 1 rooms[].id) |
rateId | 요금 해시 ID (Step 1 rooms[].rates[].id) |
쿼리 파라미터
| 파라미터 | 필수 | 설명 |
|---|---|---|
token | ✅ | Step 1에서 발급된 price_check 토큰 |
Step 2: 가격 확인
응답 구조
{
"status": "matched",
"occupancy_pricing": {
"2": {
"nightly": [...],
"totals": {
"inclusive": {
"request_currency": { "currency": "KRW", "value": 330000 }
}
}
}
},
"links": {
"book": {
"method": "POST",
"href": "/api/channel/v2/bookings?token=eyJ...",
"expires": "2026-04-01T11:00:00.000Z"
}
}
}
status 필드:
"matched"— 가격이 Step 1과 동일합니다."price_changed"— 가격이 변경되었습니다.occupancy_pricing에 최신 가격이 반영됩니다. 변경된 가격을 고객에게 안내한 후 계속 진행하세요.
book 토큰은 단일 사용(single-use) 입니다. 한 번 사용하면 재사용할 수 없으므로, 예약 실패 시 Step 1부터 다시 시작해야 합니다.
Step 3: 예약 생성
POST /api/channel/v2/bookings?token=
Step 2에서 발급된 book 토큰과 투숙객 정보로 예약을 생성합니다.
쿼리 파라미터
| 파라미터 | 설명 |
|---|---|
token | Step 2에서 발급된 book 토큰 (단일 객실 예약 시) |
요청 바디
| 필드 | 필수 | 설명 |
|---|---|---|
rooms | ✅ | 투숙객 정보 배열 |
rooms[].given_name | ✅ | 투숙객 이름 |
rooms[].family_name | ✅ | 투숙객 성 |
affiliate_reference_id | - | 채널 자체 예약 참조 ID |
book_tokens | - | 복수 객실 예약 시 book 토큰 배열 (query의 token 대신 사용) |
Step 3: 예약 생성
응답 (201 Created)
{
"itinerary_id": "ONDA1743500000000",
"links": {
"retrieve": {
"method": "GET",
"href": "/api/channel/v2/bookings/retrieve?token=eyJ...",
"expires": "2027-04-01T10:00:00.000Z"
},
"cancel": {
"method": "PUT",
"href": "/api/channel/v2/bookings/cancel?token=eyJ...",
"expires": "2027-04-01T10:00:00.000Z"
}
}
}
itinerary_id와 retrieve/cancel 링크를 안전하게 저장하세요. 예약 조회와 취소에 사용됩니다.
Step 4a: 예약 조회
GET /api/channel/v2/bookings/retrieve?token=
예약 생성 응답의 retrieve 링크를 호출하여 예약 상세를 조회합니다.
Step 4a: 예약 조회
응답 구조
{
"itinerary_id": "ONDA1743500000000",
"status": "confirmed",
"property_id": "12345",
"checkin": "2026-04-01",
"checkout": "2026-04-03",
"request_currency": "KRW",
"billable_currency": "KRW",
"rooms": [
{
"room_id": "a1b2c3d4",
"rate_id": "e5f6g7h8",
"bed_group_id": "37321",
"bed_group_description": "1 King Bed",
"status": "confirmed",
"refundable": true,
"guest": {
"given_name": "길동",
"family_name": "홍"
},
"occupancy_pricing": { ... },
"cancel_penalties": [],
"cancel_refund": {
"refundable": true,
"refund_amount": 330000,
"penalty_amount": 0,
"currency": "KRW"
}
}
],
"links": {
"cancel": {
"method": "PUT",
"href": "/api/channel/v2/bookings/cancel?token=eyJ...",
"expires": "2027-04-01T10:00:00.000Z"
}
}
}
Step 4b: 예약 취소
PUT /api/channel/v2/bookings/cancel?token=
예약 생성(또는 조회) 응답의 cancel 링크를 호출하여 예약을 취소합니다.
cancel 토큰은 단일 사용(single-use) 입니다. 취소 요청이 성공하면 토큰이 소진됩니다. 취소 후 조회가 필요하면 retrieve 토큰을 별도로 저장해두세요.
Step 4b: 예약 취소
응답 구조
{
"itinerary_id": "ONDA1743500000000",
"status": "cancelled",
"cancel_refund": {
"refundable": true,
"refund_amount": 330000,
"penalty_amount": 0,
"currency": "KRW"
}
}
콘텐츠 API
숙소 목록 조회
GET /api/channel/v2/properties
연동된 숙소 목록을 페이지 토큰 기반으로 조회합니다.
쿼리 파라미터
| 파라미터 | 설명 |
|---|---|
page_token | 다음 페이지 토큰 (첫 페이지는 생략) |
per_page | 페이지당 결과 수 |
updated_since | 해당 시각 이후 변경된 숙소만 조회 (ISO 8601) |
curl -X GET "https://developers.tport.dev/api/channel/v2/properties?per_page=20" \
-H "X-Api-Key: {your_api_key}"
숙소 상세 조회
GET /api/channel/v2/properties/{id}
특정 숙소의 상세 정보를 조회합니다. property_id는 문자열로 반환됩니다.
curl -X GET "https://developers.tport.dev/api/channel/v2/properties/12345" \
-H "X-Api-Key: {your_api_key}"
객실 타입 목록 조회
GET /api/channel/v2/properties/{id}/roomtypes
특정 숙소의 객실 타입 목록을 조회합니다.
curl -X GET "https://developers.tport.dev/api/channel/v2/properties/12345/roomtypes" \
-H "X-Api-Key: {your_api_key}"
토큰 오류 처리
v2 API는 단계 간 연결에 토큰을 사용합니다. 토큰 관련 오류 시나리오와 대응 방법입니다.
| HTTP 상태 | 오류 코드 | 원인 | 대응 |
|---|---|---|---|
400 | INVALID_TOKEN | 토큰 형식 오류 또는 타입 불일치 | Step 1부터 재시작 |
409 | TOKEN_ALREADY_USED | 단일 사용 토큰을 재사용 시도 | Step 1부터 재시작 |
410 | TOKEN_EXPIRED | 토큰 유효 기간 초과 | Step 1부터 재시작 |
403 | FORBIDDEN | 경로 파라미터가 토큰 컨텍스트와 불일치 | href를 그대로 사용 |
토큰 오류(4xx)가 발생하면 항상 Step 1(가용성 검색)부터 다시 시작하세요. 중간 단계부터 재시도하는 것은 지원하지 않습니다.
v1에서 v2로 마이그레이션
1. 예약 흐름 재구성
v1은 직접 파라미터를 조합하여 예약 API를 호출하는 방식이었습니다. v2는 응답의 링크(href)를 따라가는 방식입니다.
v1: GET /search/availability → GET /search/price-check → POST /bookings
v2: GET /properties/availability (price_check 링크 수령)
→ GET /properties/{pId}/rooms/{rId}/rates/{rateId}?token= (book 링크 수령)
→ POST /bookings?token= (retrieve/cancel 링크 수령)
2. property_id 형식 변경
v2에서 property_id는 항상 문자열로 반환됩니다. 숫자로 비교하거나 저장하지 마세요.
// v1 (숫자)
property.property_id === 12345
// v2 (문자열)
property.property_id === "12345"
3. 인원 파라미터 변경
v1의 adults/children 파라미터 대신 EPS 호환 occupancy 파라미터를 사용합니다.
v1: ?adults=2&children=1
v2: ?occupancy=2-5 (성인 2명, 어린이 5세 1명)
4. room/rate ID 변경
v2의 room ID와 rate ID는 내부 ID를 해싱한 값입니다. 직접 생성하거나 저장하지 말고 가용성 검색 응답에서 가져오세요.