Bitvoya Edition
다음 여정을 정리하고 있습니다
페이지가 열리기 전에 이미지, 목적지, 디테일을 차분하게 구성하고 있습니다.
Bitvoya Edition
페이지가 열리기 전에 이미지, 목적지, 디테일을 차분하게 구성하고 있습니다.
Bitvoya B2B API · v1
엄선된 호텔 검색, 실시간 견적, 선결제 예약을 귀사 플랫폼에서 바로. 요금마다 가격은 하나뿐이며, 위안화 기준으로 세금과 서비스 수수료가 모두 포함됩니다.
빠른 시작
여섯 번의 호출로 예약이 끝납니다. 단계마다 요청과 응답을 함께 보여 드립니다.
모든 요청에 API 키를 Bearer 토큰으로 보냅니다. GET /me는 키가 속한 테넌트, 스코프, 분당 요청 한도를 알려 줍니다.
curl https://app.bitvoya.com/api/b2b/v1/me \
-H "Authorization: Bearer $BITVOYA_API_KEY"{
"data": {
"tenant": { "code": "acme-travel", "name": "Acme Travel" },
"api_key": {
"name": "Production server",
"prefix": "bvk_live_AbCd1234",
"scopes": [
"catalog:read",
"rates:read",
"bookings:read",
"bookings:write"
],
"expires_at": null
},
"pricing": {
"currency": "CNY",
"price_basis": "tax_inclusive_total_with_service_fee"
},
"rate_limit": { "requests_per_minute": 120 }
}
}목적지나 브랜드로 필터링하고 커서로 페이지를 넘기며 호텔을 가져옵니다. 호텔 정보에는 ETag가 있어, 바뀌지 않았다면 304가 돌아와 다시 받을 필요가 없습니다.
curl "https://app.bitvoya.com/api/b2b/v1/hotels?destination_id=5736&limit=1" \
-H "Authorization: Bearer $BITVOYA_API_KEY"{
"data": [
{
"id": "644",
"name": "Sofitel Hangzhou Westlake",
"address": "333 Xihu Avenue, Shangcheng District",
"destination": { "id": "5736", "name": "Hangzhou" },
"brand": { "id": "1862", "name": "Sofitel Hotels" },
"location": { "latitude": 30.2537, "longitude": 120.1652 },
"image_url": "https://images.example/hotels/644/cover.jpg"
}
],
"next_cursor": "eyJrIjoiaG90ZWwiLCJhIjoiNjQ0In0"
}숙박 날짜와 성인 수(객실 1개, 1–4명)를 지정합니다. 요금마다 가격 하나, 식사 조건, 호텔 현지 시간 기준의 취소 규정이 붙습니다.
curl "https://app.bitvoya.com/api/b2b/v1/hotels/644/rates?checkin=2026-12-05&checkout=2026-12-07&adults=2" \
-H "Authorization: Bearer $BITVOYA_API_KEY"{
"data": {
"hotel_id": "644",
"checkin": "2026-12-05",
"checkout": "2026-12-07",
"nights": 2,
"adults": 2,
"rooms": [
{
"room_id": "38211",
"name": "Luxury Room, Lake View",
"image_url": "https://images.example/hotels/644/rooms/38211.jpg",
"rates": [
{
"rate_key": "eyJoIjoiNjQ0IiwiZCI6IjkwMTc3NDAyIiwiY2kiOiIyMDI2LTEyLTA1IiwiY28iOiIyMDI2LTEyLTA3IiwiYSI6Mn0",
"name": "Breakfast for two, free cancellation",
"meal_plan": "breakfast",
"executive_benefit": false,
"price": { "amount": "1709.65", "currency": "CNY" },
"cancellation": {
"type": "free_cancellation",
"deadline": "2026-12-04T18:00:00+08:00",
"confirmed": true
},
"pay_at_hotel": null
}
]
}
]
}
}고른 rate_key를 보내면 공급사에 실시간으로 확인하고 가격을 15분간 유지합니다.
curl -X POST https://app.bitvoya.com/api/b2b/v1/quotes \
-H "Authorization: Bearer $BITVOYA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"rate_key": "eyJoIjoiNjQ0IiwiZCI6IjkwMTc3NDAyIiwiY2kiOiIyMDI2LTEyLTA1IiwiY28iOiIyMDI2LTEyLTA3IiwiYSI6Mn0"
}'{
"data": {
"quote_id": "qt_7Hk2Qx9PmW4rT8vN3bLc",
"expires_at": "2026-11-20T09:15:00Z",
"hotel_id": "644",
"room": { "room_id": "38211", "name": "Luxury Room, Lake View" },
"rate": {
"name": "Breakfast for two, free cancellation",
"meal_plan": "breakfast",
"executive_benefit": false
},
"checkin": "2026-12-05",
"checkout": "2026-12-07",
"nights": 2,
"adults": 2,
"price": { "amount": "1709.65", "currency": "CNY" },
"cancellation": {
"type": "free_cancellation",
"deadline": "2026-12-04T18:00:00+08:00",
"confirmed": true
},
"pay_at_hotel": null
}
}견적과 투숙객 이름으로 예약을 만듭니다. Idempotency-Key를 보내면 재시도해도 중복 예약이 생기지 않습니다. 전액 결제용 Stripe 결제 페이지를 받습니다.
curl -X POST https://app.bitvoya.com/api/b2b/v1/bookings \
-H "Authorization: Bearer $BITVOYA_API_KEY" \
-H "Idempotency-Key: 6f1c2a9e-4b7d-4c1e-9a53-2d8e0f7b1c44" \
-H "Content-Type: application/json" \
-d '{
"quote_id": "qt_7Hk2Qx9PmW4rT8vN3bLc",
"client_reference": "ACME-10293",
"guests": [
{ "first_name": "Mei", "last_name": "Lin" },
{ "first_name": "James", "last_name": "Lin" }
],
"contact": { "email": "ops@acme.example", "phone": "+86 21 5555 0100" },
"arrival_time": "18:00",
"special_requests": ["king_bed"],
"success_url": "https://acme.example/trips/ACME-10293/paid",
"cancel_url": "https://acme.example/trips/ACME-10293"
}'{
"data": {
"booking_id": "BV20261120090112",
"client_reference": "ACME-10293",
"status": "awaiting_payment",
"hotel": { "hotel_id": "644", "name": "Sofitel Hangzhou Westlake" },
"room": { "room_id": "38211", "name": "Luxury Room, Lake View" },
"rate": {
"name": "Breakfast for two, free cancellation",
"meal_plan": "breakfast",
"executive_benefit": false
},
"checkin": "2026-12-05",
"checkout": "2026-12-07",
"nights": 2,
"adults": 2,
"guests": [
{ "first_name": "Mei", "last_name": "Lin" },
{ "first_name": "James", "last_name": "Lin" }
],
"price": { "amount": "1709.65", "currency": "CNY" },
"cancellation": {
"type": "free_cancellation",
"deadline": "2026-12-04T18:00:00+08:00",
"confirmed": true
},
"pay_at_hotel": null,
"payment": {
"status": "pending",
"url": "https://checkout.stripe.com/c/pay/cs_live_a1B2c3D4e5F6g7H8",
"expires_at": "2026-11-20T09:31:12Z",
"paid_at": null
},
"hotel_confirmation_number": null,
"created_at": "2026-11-20T09:01:12Z",
"updated_at": "2026-11-20T09:01:12Z"
}
}결제 후 호텔에 확정을 요청하며, 몇 시간이 걸릴 수 있습니다. 상태가 confirmed가 되고 호텔 확인 번호가 붙을 때까지 예약을 조회하세요.
curl https://app.bitvoya.com/api/b2b/v1/bookings/BV20261120090112 \
-H "Authorization: Bearer $BITVOYA_API_KEY"{
"data": {
"booking_id": "BV20261120090112",
"client_reference": "ACME-10293",
"status": "confirmed",
"hotel": { "hotel_id": "644", "name": "Sofitel Hangzhou Westlake" },
"room": { "room_id": "38211", "name": "Luxury Room, Lake View" },
"rate": {
"name": "Breakfast for two, free cancellation",
"meal_plan": "breakfast",
"executive_benefit": false
},
"checkin": "2026-12-05",
"checkout": "2026-12-07",
"nights": 2,
"adults": 2,
"guests": [
{ "first_name": "Mei", "last_name": "Lin" },
{ "first_name": "James", "last_name": "Lin" }
],
"price": { "amount": "1709.65", "currency": "CNY" },
"cancellation": {
"type": "free_cancellation",
"deadline": "2026-12-04T18:00:00+08:00",
"confirmed": true
},
"pay_at_hotel": null,
"payment": {
"status": "paid",
"url": null,
"expires_at": null,
"paid_at": "2026-11-20T09:04:51Z"
},
"hotel_confirmation_number": "48213977",
"created_at": "2026-11-20T09:01:12Z",
"updated_at": "2026-11-20T11:42:05Z"
}
}요금
요금마다 가격은 하나뿐입니다. 전체 숙박의 세금 포함 총액이며, Bitvoya 서비스 수수료도 이미 들어 있습니다. 공급사 가격이나 수수료를 직접 더할 필요가 없습니다.
요금 예시 · 2박 · 성인 2명
rate.priceprice
Stripe로 선결제하는 금액
¥1,709.65
"price": { "amount": "1709.65", "currency": "CNY" }pay_at_hotel · 호텔에서 현장 결제, price에 미포함
예약 상태
예약은 하나의 주요 흐름을 따라 진행됩니다. 나머지 상태는 무슨 일이 있었고 다음에 무엇을 해야 하는지 알려 줍니다.
주요 흐름
payment.url에서 결제 대기 중. 결제 페이지는 30분간 유효합니다.
결제 완료. 호텔에 확정을 요청 중이며 몇 시간이 걸릴 수 있습니다.
호텔이 확정했습니다. hotel_confirmation_number가 채워집니다.
기타 결과
결제 페이지가 만료되었거나 결제에 실패했습니다. 다시 예약하세요.
이전 상태awaiting_payment
취소됨. 환불 상태는 payment.status에서 확인하세요.
이전 상태awaiting_paymentpending_confirmationconfirmed
결제에 문제가 있어 당사가 직접 확인 중입니다.
API 레퍼런스
경로는 기본 URL 기준입니다. 엔드포인트를 펼치면 파라미터와 예시를 볼 수 있습니다.
이 요청의 테넌트, 키, 스코프와 요청 한도.
파라미터
파라미터가 없습니다.
예시
호텔이 있는 도시. 어떤 언어의 이름이나 도시 코드로 검색하거나, 전체를 페이지로 조회.
파라미터
queryquerystring · 1–100
cursorquerystring · next_cursor
limitqueryinteger · 1–100 · 기본값 50
예시
ID 순 호텔 목록. 목적지나 브랜드로 필터링할 수 있고, 필터 없이 호출하면 전체 동기화.
파라미터
destination_idquerystring · digits
brand_idquerystring · digits
cursorquerystring · next_cursor
limitqueryinteger · 1–100 · 기본값 50
예시
호텔 한 곳의 상세: 주소, 위치, 등급, 체크인·체크아웃 시간, 설명, 시설, 이미지.
파라미터
hotel_idpath필수string · digits
예시
호텔 브랜드와 브랜드별 호텔 수.
파라미터
파라미터가 없습니다.
예시
한 번의 숙박에 대한 객실 유형과 예약 가능한 요금, 낮은 가격순.
파라미터
hotel_idpath필수string · digits
checkinquery필수date · YYYY-MM-DD
checkoutquery필수date · YYYY-MM-DD
adultsqueryinteger · 1–4 · 기본값 2
예시
요금을 실시간으로 확인하고 가격을 15분간 유지.
파라미터
rate_keybody필수string
예시
견적으로 예약. 예약 정보와 Stripe 결제 페이지를 반환.
파라미터
Idempotency-Keyheader필수string · ≤255
quote_idbody필수string · qt_…
guests[]body필수1–2 × { first_name, last_name }
contact.emailbody필수contact.phonebodystring · +86 …
client_referencebodystring · ≤64
arrival_timebodyHH:MM
special_requests[]bodyking_bed | twin_beds | baby_cot | extra_bed | birthday
remarksbodystring · ≤200
success_urlbodyhttps URL
cancel_urlbodyhttps URL
예시
귀사의 예약, 최신순. client_reference로 찾을 수 있음.
파라미터
client_referencequerystring · ≤64
cursorquerystring · next_cursor
limitqueryinteger · 1–100 · 기본값 50
예시
예약 한 건: 상태, 결제, 호텔 확인 번호.
파라미터
booking_idpath필수string · BV + 14 digits
예시
예약 취소. 기한 전이면 결제된 예약도 전액 환불.
파라미터
booking_idpath필수string · BV + 14 digits
reasonbodystring · ≤200
예시
success_url을 보내지 않았을 때 결제 후 돌아오는 기본 페이지.
파라미터
파라미터가 없습니다.
예시
이 API의 OpenAPI 3.1 명세.
파라미터
파라미터가 없습니다.
예시
공통 규칙
익숙한 HTTP 관례 그대로이며, 전용 SDK가 필요 없습니다.
키는 Authorization: Bearer로 보냅니다. 키마다 스코프를 지정하며, 테넌트당 최대 10개의 유효한 키로 교체할 수 있습니다. 당사는 해시만 저장하며 키는 발급 시 한 번만 표시됩니다.
Authorization: Bearer bvk_live_…오류는 RFC 9457 problem details 형식입니다. 프로그램에서는 안정적인 code로 판단하세요. detail은 사람을 위한 설명이며, 문의 시 request_id를 알려 주세요.
Content-Type: application/problem+json테넌트마다 분당 요청 한도가 있으며 모든 키가 함께 씁니다. 남은 양은 IETF RateLimit 헤더로 알 수 있고, 429에는 Retry-After가 붙습니다.
RateLimit: "tenant";r=118;t=41POST /bookings에는 Idempotency-Key가 필요합니다. 같은 키와 같은 본문이면 원래 예약을 돌려주고, 같은 키에 다른 본문이면 거부합니다.
Idempotency-Key: 6f1c2a9e-4b7d…목록은 페이지 번호 대신 커서를 씁니다. next_cursor를 cursor로 넘기고 null이 될 때까지 반복하세요. limit는 최대 100입니다.
?limit=100&cursor=eyJrIjoiaG90ZWwi…Accept-Language에 en, zh-CN, zh-TW, ja, ko를 지정합니다. 번역이 없으면 적절히 대체하며, Content-Language로 실제 언어를 알 수 있습니다.
Accept-Language: ja호텔 정보는 5분간 캐시할 수 있고 약한 ETag가 붙습니다. 요금, 견적, 예약은 캐시하지 않습니다.
If-None-Match: W/"5c1-9f3a7e21"메이저 버전은 경로에 있습니다. v1에서는 추가만 하며, 호환되지 않는 변경은 v2로 내고 Deprecation과 Sunset 헤더로 미리 알립니다.
/api/b2b/v1오류 코드
모든 오류에는 HTTP 상태와 안정적인 code가 있습니다.
{
"type": "about:blank",
"title": "Conflict",
"status": 409,
"code": "quote_changed",
"detail": "The price or the cancellation terms changed. Check current_quote and book with its quote_id.",
"request_id": "req-3k9x1",
"current_quote": {
"quote_id": "qt_Vb8nR2kL5tY7wQ3mZ9xP",
"price": { "amount": "1788.40", "currency": "CNY" }
}
}| HTTP | code | 의미 |
|---|---|---|
| 400 | invalid_request파라미터나 필드가 올바르지 않습니다. errors를 확인하세요. | 파라미터나 필드가 올바르지 않습니다. errors를 확인하세요. |
| 400 | invalid_cursor커서가 잘못되었거나 다른 목록의 커서입니다. | 커서가 잘못되었거나 다른 목록의 커서입니다. |
| 400 | invalid_rate_keyrate_key를 읽을 수 없습니다. 요금을 다시 조회하세요. | rate_key를 읽을 수 없습니다. 요금을 다시 조회하세요. |
| 400 | idempotency_key_requiredPOST /bookings에는 Idempotency-Key 헤더가 필요합니다. | POST /bookings에는 Idempotency-Key 헤더가 필요합니다. |
| 401 | missing_api_keyAPI 키를 보내지 않았습니다. | API 키를 보내지 않았습니다. |
| 401 | invalid_api_key키를 인식할 수 없습니다. | 키를 인식할 수 없습니다. |
| 401 | api_key_revoked키가 폐기되었습니다. 다른 키를 사용하세요. | 키가 폐기되었습니다. 다른 키를 사용하세요. |
| 401 | api_key_expired키가 만료되었습니다. | 키가 만료되었습니다. |
| 403 | tenant_suspended테넌트가 정지되었습니다. 당사에 문의하세요. | 테넌트가 정지되었습니다. 당사에 문의하세요. |
| 403 | insufficient_scope키에 필요한 스코프가 없습니다. required_scopes를 확인하세요. | 키에 필요한 스코프가 없습니다. required_scopes를 확인하세요. |
| 404 | hotel_not_found해당 호텔이 없거나 더 이상 제공되지 않습니다. | 해당 호텔이 없거나 더 이상 제공되지 않습니다. |
| 404 | quote_not_found귀사 테넌트에 이 견적이 없습니다. | 귀사 테넌트에 이 견적이 없습니다. |
| 404 | booking_not_found귀사 테넌트에 이 예약이 없습니다. | 귀사 테넌트에 이 예약이 없습니다. |
| 409 | rate_unavailable이 요금은 더 이상 예약할 수 없습니다. | 이 요금은 더 이상 예약할 수 없습니다. |
| 409 | quote_expired견적 후 15분이 지났습니다. 다시 견적을 받으세요. | 견적 후 15분이 지났습니다. 다시 견적을 받으세요. |
| 409 | quote_changed가격이나 조건이 바뀌었습니다. current_quote로 예약하세요. | 가격이나 조건이 바뀌었습니다. current_quote로 예약하세요. |
| 409 | already_cancelled이미 취소된 예약입니다. | 이미 취소된 예약입니다. |
| 409 | not_cancellable무료 취소 기한이 지났거나, 환불 불가 요금이거나, 확인 중인 예약입니다. | 무료 취소 기한이 지났거나, 환불 불가 요금이거나, 확인 중인 예약입니다. |
| 409 | conflict다른 요청이 이 예약을 변경했습니다. 다시 조회한 뒤 재시도하세요. | 다른 요청이 이 예약을 변경했습니다. 다시 조회한 뒤 재시도하세요. |
| 422 | idempotency_key_reused이 Idempotency-Key는 다른 본문에 이미 쓰였습니다. | 이 Idempotency-Key는 다른 본문에 이미 쓰였습니다. |
| 429 | rate_limited분당 한도를 넘었습니다. Retry-After 후 다시 시도하세요. | 분당 한도를 넘었습니다. Retry-After 후 다시 시도하세요. |
| 500 | internal_error당사 쪽 오류입니다. 문의 시 request_id를 알려 주세요. | 당사 쪽 오류입니다. 문의 시 request_id를 알려 주세요. |
| 502 | payment_unavailable예약은 생성됐지만 결제 페이지를 열지 못했습니다. 같은 Idempotency-Key로 재시도하세요. | 예약은 생성됐지만 결제 페이지를 열지 못했습니다. 같은 Idempotency-Key로 재시도하세요. |
| 502 | supplier_error공급사가 오류를 반환했습니다. | 공급사가 오류를 반환했습니다. |
| 503 | supplier_unavailable공급사가 응답하지 않았습니다. 잠시 후 다시 시도하세요. | 공급사가 응답하지 않았습니다. 잠시 후 다시 시도하세요. |
연동하기
먼저 귀사의 비즈니스를 알려 주세요. 테넌트를 개설하고 서비스 수수료를 정한 뒤, 당사 관리 화면에서 API 키를 발급해 드립니다.