Skip to main content

Java SDK

The Bundleport Java SDK provides a type-safe client for the Connect Hotels REST API with support for both reactive (Spring WebFlux) and blocking operations.

Install

Gradle

dependencies {
implementation("com.bundleport:connect-hotels-sdk:<version>")
}

Maven

<dependency>
<groupId>com.bundleport</groupId>
<artifactId>connect-hotels-sdk</artifactId>
<version>${bundleport.version}</version>
</dependency>

Initialize the Client

Blocking Client

import com.bundleport.client.BundleportClient;
import com.bundleport.client.ClientConfig;
import java.time.Duration;

ClientConfig config = ClientConfig.builder()
.apiKey("YOUR_API_KEY_HERE")
.baseUrl("https://api.bundleport.com") // Optional
.timeout(Duration.ofSeconds(30)) // Optional
.build();

BundleportClient client = new BundleportClient(config);

Reactive Client (Spring WebFlux)

import com.bundleport.client.reactive.ReactiveBundleportClient;
import org.springframework.web.reactive.function.client.WebClient;

WebClient webClient = WebClient.builder()
.baseUrl("https://api.bundleport.com")
.build();

ReactiveBundleportClient client = new ReactiveBundleportClient(
webClient,
"YOUR_API_KEY_HERE"
);

Booking Operations

Search for Hotels

SearchRequest request = SearchRequest.builder()
.stay(Stay.builder()
.checkIn("2025-06-15")
.checkOut("2025-06-17")
.build())
.destination(Destination.builder()
.code("BCN")
.build())
.occupancies(List.of(
Occupancy.builder()
.adults(2)
.children(1)
.childrenAges(List.of(8))
.build()
))
.filters(SearchFilters.builder()
.currency("EUR")
.minPrice(100)
.maxPrice(300)
.build())
.settings(Settings.builder()
.accessIds(List.of("ACCESS_1"))
.build())
.build();

SearchResponse result = client.hotels().search(request);
System.out.println("Found " + result.getOptions().size() + " options");

Quote an Option

QuoteRequest quoteRequest = QuoteRequest.builder()
.optionRefId(result.getOptions().get(0).getOptionRefId())
.settings(Settings.builder()
.accessIds(List.of("ACCESS_1"))
.build())
.build();

QuoteResponse quoteResult = client.hotels().quote(quoteRequest);

// Check for price changes
boolean priceChanged = quoteResult.getWarnings().stream()
.anyMatch(w -> "PRICE_CHANGED".equals(w.getCode()));
if (priceChanged) {
System.out.println("Price has changed: " + quoteResult.getPrice());
}

Create a Booking

BookRequest bookRequest = BookRequest.builder()
.optionRefId(quoteResult.getOptionQuote().getOptionRefId())
.holder(Holder.builder()
.name("John")
.surname("Doe")
.email("john.doe@example.com")
.phone("+34600123456")
.build())
.rooms(List.of(
BookRoom.builder()
.occupancyRefId(1)
.paxes(List.of(
Pax.builder().name("John").surname("Doe").age(35).build(),
Pax.builder().name("Jane").surname("Doe").age(33).build()
))
.build()
))
.paymentCard(PaymentCard.builder()
.type("VI")
.number("4111111111111111")
.expire(CardExpire.builder().month(12).year(2027).build())
.holder(CardHolder.builder().name("John").surname("Doe").build())
.build())
.clientReference("BOOKING-2025-001")
.build();

BookResponse booking = client.hotels().book(bookRequest);
System.out.println("Booking confirmed: " + booking.getBooking().getId());

Reactive Usage

import reactor.core.publisher.Mono;

Mono<SearchResponse> searchMono = reactiveClient.hotels().search(request);

Mono<QuoteResponse> quoteMono = searchMono.flatMap(result ->
reactiveClient.hotels().quote(QuoteRequest.builder()
.optionRefId(result.getOptions().get(0).getOptionRefId())
.build())
);

quoteMono.subscribe(
quote -> System.out.println("Quote received: " + quote.getPrice()),
error -> System.err.println("Error: " + error.getMessage())
);

Content Operations

Get Hotels

HotelsRequest hotelsRequest = HotelsRequest.builder()
.query(HotelListQuery.builder()
.destinationCodes(List.of("BCN"))
.maxSize(100)
.build())
.build();

HotelsResponse hotels = client.content().getHotels(hotelsRequest);
System.out.println("Found " + hotels.getHotels().getHotels().size() + " hotels");

Error Handling

import com.bundleport.exceptions.BundleportException;
import com.bundleport.exceptions.UnauthorizedException;
import com.bundleport.exceptions.RateLimitException;

try {
SearchResponse result = client.hotels().search(request);
} catch (UnauthorizedException e) {
System.err.println("Invalid API key");
} catch (RateLimitException e) {
System.err.println("Rate limit exceeded, retry after: " + e.getRetryAfter() + " seconds");
} catch (BundleportException e) {
System.err.println("API error: " + e.getMessage());
}

Next Steps