Skip to main content

C# SDK

The Bundleport C# SDK provides a type-safe client for the Connect Hotels REST API with full .NET support and dependency injection.

Install

dotnet add package Bundleport.ConnectHotels.Sdk

Initialize the Client

Direct Instantiation

using Bundleport.ConnectHotels;

var client = new BundleportClient(new ClientOptions
{
ApiKey = "YOUR_API_KEY_HERE",
BaseUrl = "https://api.bundleport.com", // Optional
Timeout = TimeSpan.FromSeconds(30), // Optional
});

Dependency Injection (ASP.NET Core)

using Bundleport.ConnectHotels;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddBundleportClient(options =>
{
options.ApiKey = builder.Configuration["Bundleport:ApiKey"];
options.BaseUrl = "https://api.bundleport.com";
options.Timeout = TimeSpan.FromSeconds(30);
});

Inject IBundleportClient in your controllers:

public class HotelsController : ControllerBase
{
private readonly IBundleportClient _client;

public HotelsController(IBundleportClient client) => _client = client;

[HttpPost("/search")]
public async Task<IActionResult> Search([FromBody] SearchRequest request)
{
var response = await _client.Hotels.SearchAsync(request);
return Ok(response);
}
}

Booking Operations

Search for Hotels (Availability)

var searchRequest = new SearchRequest
{
Criteria = new SearchCriteria
{
CheckIn = "2025-06-15T00:00:00Z",
CheckOut = "2025-06-17T00:00:00Z",
Occupancies = new List<Occupancy>
{
new Occupancy
{
Paxes = new List<Pax>
{
new Pax { Name = "John", Surname = "Doe", Age = 35 },
new Pax { Name = "Jane", Surname = "Doe", Age = 33 },
new Pax { Name = "Child", Surname = "Doe", Age = 8 }
}
}
},
Hotels = new List<string> { "12345", "67890" }, // Optional
Currency = "EUR",
Language = "en",
Nationality = "US"
},
Settings = new Settings
{
ConnectionCodes = new List<string> { "testb-hbds-1876" },
Timeout = 30000
}
};

var searchResult = await client.Hotels.SearchAvailabilityAsync(searchRequest);
Console.WriteLine($"Found {searchResult.Options.Count} options");

Get Prebooking Quote

var quoteRequest = new QuoteRequest
{
Criteria = new QuoteCriteria
{
OptionRefId = searchResult.Options[0].OptionRefId
},
Settings = new Settings
{
ConnectionCodes = new List<string> { "testb-hbds-1876" }
}
};

var quoteResult = await client.Hotels.GetPrebookingAsync(quoteRequest);

// Check for price changes
if (quoteResult.Warnings?.Any(w => w.Code == "PRICE_CHANGED") == true)
{
Console.WriteLine($"Price has changed: {quoteResult.OptionQuote.Price.Net}");
}

Create a Booking

var bookRequest = new BookRequest
{
Input = new BookInput
{
OptionRefId = quoteResult.OptionQuote.OptionRefId,
Holder = new Holder
{
Name = "John",
Surname = "Doe",
Title = "MR"
},
Rooms = new List<BookRoom>
{
new BookRoom
{
OccupancyRefId = 1,
Paxes = new List<Pax>
{
new Pax { Name = "John", Surname = "Doe", Age = 35 },
new Pax { Name = "Jane", Surname = "Doe", Age = 33 }
}
}
},
PaymentCard = new PaymentCard
{
Type = "VI",
Number = "4111111111111111",
Expire = new CardExpire { Month = 12, Year = 2027 },
Holder = new CardHolder
{
Name = "John",
Surname = "Doe",
ContactInfo = new ContactInfo
{
Email = "john.doe@example.com",
Phone = new Phone
{
CountryCode = "+34",
Number = "600123456"
}
}
}
},
ClientReference = "BOOKING-2025-001"
},
Settings = new Settings
{
ConnectionCodes = new List<string> { "testb-hbds-1876" }
}
};

var booking = await client.Hotels.CreateBookingAsync(bookRequest);
Console.WriteLine($"Booking confirmed: {booking.Booking.BookingID}");

Retrieve Booking Details

var detailRequest = new BookingDetailRequest
{
Criteria = new BookingDetailCriteria
{
BookingID = "BK-987654321"
},
Settings = new Settings
{
ConnectionCodes = new List<string> { "testb-hbds-1876" }
}
};

var bookingDetails = await client.Hotels.GetBookingDetailAsync(detailRequest);
Console.WriteLine($"Booking status: {bookingDetails.Booking.Status}");

List Bookings

var listRequest = new BookingListRequest
{
Criteria = new BookingListCriteria
{
TypeSearch = "BOOKING_LIST_CRITERIA_TYPE_DATES",
Dates = new BookingListDates
{
DateType = "BOOKING_LIST_CRITERIA_DATE_TYPE_ARRIVAL",
Start = "2025-06-01T00:00:00Z",
End = "2025-06-30T00:00:00Z"
}
// Or search by booking ID:
// TypeSearch = "BOOKING_LIST_CRITERIA_TYPE_BOOKING_ID",
// BookingID = "BK-987654321"
},
Settings = new Settings
{
ConnectionCodes = new List<string> { "testb-hbds-1876" }
}
};

var bookings = await client.Hotels.ListBookingsAsync(listRequest);
Console.WriteLine($"Found {bookings.Bookings.Count} bookings");

Cancel Booking

var cancelRequest = new CancelRequest
{
Input = new CancelInput
{
BookingID = "BK-987654321"
},
Settings = new Settings
{
ConnectionCodes = new List<string> { "testb-hbds-1876" }
}
};

var cancelResult = await client.Hotels.CancelAsync(cancelRequest);
Console.WriteLine($"Cancellation status: {cancelResult.Cancel.Status}");
if (cancelResult.Cancel.CancelPenalties?.Count > 0)
{
foreach (var penalty in cancelResult.Cancel.CancelPenalties)
{
Console.WriteLine($"Cancellation penalty: {penalty.Value} {penalty.Currency}");
}
}

Content Operations

Get Hotels

var hotelsRequest = new HotelsRequest
{
Query = new HotelListQuery
{
DestinationCodes = new List<string> { "BCN" },
MaxSize = 100
}
};

var hotels = await client.Content.GetHotelsAsync(hotelsRequest);
Console.WriteLine($"Found {hotels.Hotels.Hotels.Count} hotels");

Error Handling

using Bundleport.Exceptions;

try
{
var result = await client.Hotels.SearchAvailabilityAsync(request);
}
catch (UnauthorizedException)
{
Console.Error.WriteLine("Invalid API key");
}
catch (RateLimitException ex)
{
Console.Error.WriteLine($"Rate limit exceeded, retry after: {ex.RetryAfter} seconds");
}
catch (BundleportException ex)
{
Console.Error.WriteLine($"API error: {ex.Message}");
}

Next Steps