Skip to main content

VPN Locations

KapeLocationService fetches available VPN server locations from the Low Level SDK and exposes them as observable StateFlow collections.

Setup​

The list is scoped to a VPN protocol, so the service needs to know which one. KapeVpnManager supplies the user's persisted selection:

val vpnManager = KapeVpnManager(
handle,
protocols = listOf(KapeWireGuardSupport, KapeLightwaySupport, KapeOpenVpnSupport),
)
val locationService = vpnManager.createLocationService()

A consumer that depends on KapeVPN-Discovery alone — no tunnel, so no persisted selection — passes the protocol itself:

import com.kape.platformsdk.vpn.discovery.KapeLocationService
import com.kape.platformsdk.vpn.discovery.models.KapeVPNProtocol

val locationService = KapeLocationService(handle) { KapeVPNProtocol.OpenVPN }

There is no default on purpose: one would hand every caller the union of all three protocols, and a location that serves only Lightway cannot connect over OpenVPN.

Fetching locations​

fetchLocations() is a suspend function that calls the Low Level SDK, maps the results into KapeServerLocation models, and updates the allLocations and locationsByContinent state flows. It returns a FetchLocationsResult — no exception is thrown on failure.

Only locations serving the selected protocol come back. The protocol is read once per call and nothing observes it, so call fetchLocations() again after setSelectedProtocol(...).

import com.kape.platformsdk.vpn.discovery.FetchLocationsResult

when (val result = locationService.fetchLocations()) {
is FetchLocationsResult.Success -> {
// allLocations and locationsByContinent are now populated
}
is FetchLocationsResult.SdkError -> {
val error = result.error // KapeError with domain and message
}
}

Observing locations​

Both state flows are empty until the first successful fetchLocations() call.

// Flat list
locationService.allLocations.collect { locations: List<KapeServerLocation> ->
// update your server list UI
}

// Grouped by continent (localized continent name → list of locations)
locationService.locationsByContinent.collect { byContinent: Map<Continent, List<KapeServerLocation>> ->
// render a section per continent
}

KapeServerLocation model​

PropertyTypeDescription
idStringUnique location identifier used by the Low Level SDK
nameStringHuman-readable location name (e.g. "New York")
countryStringISO 3166-1 alpha-2 country code (e.g. "US")
continentStringLocalized continent name resolved from country (e.g. "Americas")
latitudeDoubleGeographic latitude
longitudeDoubleGeographic longitude
ratingKapeLocationRatingSmart location rating; Unknown until smart locations are fetched

KapeLocationRating​

enum class KapeLocationRating { Excellent, Good, Ok, Degraded, Poor, Unknown }

Rating is populated by a future fetchSmartLocations() call. All locations returned by fetchLocations() have rating Unknown until then.

Fetching endpoints​

fetchEndpoints(forLocation:) returns the VPN endpoints the SDK would attempt for a location, in the same order the tunnel tries them — useful for diagnostics (e.g. pre-blocking specific hosts to simulate network failures). Requires a prior successful login; the call waits for the handle's subscription pick to settle.

Pass protocol to narrow the answer to one protocol. It defaults to KapeVPNProtocol.Automatic, which asks for every protocol the SDK would attempt.

import com.kape.platformsdk.vpn.discovery.FetchEndpointsResult
import com.kape.platformsdk.vpn.discovery.models.KapeVPNProtocol

when (val result = locationService.fetchEndpoints(forLocation = "59")) {
is FetchEndpointsResult.Success -> {
result.endpoints.forEach { endpoint ->
println("${endpoint.host}:${endpoint.port} (${endpoint.protocolName})")
}
}
is FetchEndpointsResult.SdkError -> {
val error = result.error // KapeError with domain and message
}
}

// Only the OpenVPN endpoints
locationService.fetchEndpoints(forLocation = "59", protocol = KapeVPNProtocol.OpenVPN)

A location the backend serves no matching endpoints for yields Success with an empty list, not an error.

KapeVPNEndpointInfo model​

PropertyTypeDescription
hostStringEndpoint address — an IP literal, or a hostname for an HTTP proxy
portIntEndpoint port
protocolNameString"wireguard", "openvpn", "lightway" or "httpproxy"

This model describes an endpoint well enough to list, filter or pick one; it is deliberately not enough to connect with or to build a config file from. For the full OpenVPN payload — the server-supplied .ovpn contents, MTU, cert DN and XOR value — use KapeVPNDiscoveryService.