Skip to content

Kotlin SDK

Idiomatic Kotlin client for PulseRoute. Zero dependencies, data classes, named parameters. Requires Java 11+.

Installation

Gradle (Kotlin DSL)

implementation("dev.pulseroute:pulseroute-sdk-kotlin:0.1.0")

Gradle (Groovy)

implementation 'dev.pulseroute:pulseroute-sdk-kotlin:0.1.0'

Quick Start

val pulse = PulseRoute(
    apiKey = System.getenv("PULSEROUTE_KEY"),
    baseUrl = "https://api.pulseroute.dev"
)

// Pre-transaction: get routing decision
val route = pulse.getRoute(RouteRequest(country = "US", currency = "USD", cardType = "visa"))

// Process payment with route.processorId...

// Post-transaction: report outcome (fire-and-forget)
pulse.reportOutcome(OutcomeRequest(
    ruleId = route?.ruleId ?: "",
    processorId = route?.processorId ?: "",
    success = true,
    latencyMs = 145.0
))

// On shutdown
pulse.shutdown()

Stripe + Adyen Integration

val pulse = PulseRoute(apiKey = System.getenv("PULSEROUTE_KEY"))

fun processPayment(country: String, currency: String, cardType: String, amount: Long): PaymentResult {
    val route = pulse.getRoute(RouteRequest(country, currency, cardType = cardType))
    val start = System.currentTimeMillis()

    return try {
        val result = when (route?.processorId) {
            "stripe" -> stripe.charges.create(amount, currency)
            "adyen" -> adyen.payments.create(amount, currency)
            else -> stripe.charges.create(amount, currency) // default
        }

        pulse.reportOutcome(OutcomeRequest(
            ruleId = route?.ruleId ?: "",
            processorId = route?.processorId ?: "",
            success = true,
            latencyMs = (System.currentTimeMillis() - start).toDouble()
        ))
        result

    } catch (e: PaymentException) {
        pulse.reportOutcome(OutcomeRequest(
            ruleId = route?.ruleId ?: "",
            processorId = route?.processorId ?: "",
            success = false,
            latencyMs = (System.currentTimeMillis() - start).toDouble(),
            errorCode = e.code
        ))

        // Try fallback
        route?.fallbackProcessorId?.let { fallback ->
            processWithFallback(fallback, amount, currency)
        } ?: throw e
    }
}

Spring Boot

@Configuration
class PulseRouteConfig {

    @Bean
    fun pulseRouteClient(
        @Value("\${pulseroute.api-key}") apiKey: String,
        @Value("\${pulseroute.base-url:http://localhost:8080}") baseUrl: String,
    ) = PulseRoute(apiKey = apiKey, baseUrl = baseUrl)

    @PreDestroy
    fun shutdown(@Autowired client: PulseRoute) = client.shutdown()
}

Ktor

fun Application.configurePulseRoute() {
    val pulse = PulseRoute(
        apiKey = environment.config.property("pulseroute.apiKey").getString()
    )

    environment.monitor.subscribe(ApplicationStopped) {
        pulse.shutdown()
    }

    routing {
        post("/pay") {
            val route = pulse.getRoute(RouteRequest("US", "USD"))
            // ... process payment ...
        }
    }
}

Configuration

Option Default Description
apiKey null API key for authentication
baseUrl http://localhost:8080 PulseRoute API URL
timeoutMs 5000 HTTP request timeout
flushIntervalMs 5000 Outcome flush interval
batchSize 50 Max outcomes per flush

Features

  • Zero dependencies — Java 11+ HttpClient under the hood
  • Idiomatic Kotlin — data classes, named parameters, null safety
  • Local decision cache — falls back to cached decision if API unreachable
  • Fire-and-forget outcomes — buffered and flushed async in batches
  • Thread-safe — daemon flush thread, concurrent collections
  • AutoCloseable — works with use {} blocks