The Kotlin SDK provides convenient access to the Dodo Payments REST API from applications written in Kotlin. It features nullable values, Sequence, suspend functions, and other Kotlin-specific features for ergonomic use.
Installation
Gradle (Kotlin DSL)
Add the dependency to your build.gradle.kts:
implementation ( "com.dodopayments.api:dodo-payments-kotlin:1.53.4" )
Maven
Add the dependency to your pom.xml:
< dependency >
< groupId > com.dodopayments.api </ groupId >
< artifactId > dodo-payments-kotlin </ artifactId >
< version > 1.53.4 </ version >
</ dependency >
The SDK requires Kotlin 1.6 or higher and is compatible with both JVM and Android platforms.
Quick Start
Initialize the client and create a checkout session:
import com.dodopayments.api.client.DodoPaymentsClient
import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient
import com.dodopayments.api.models.checkoutsessions.CheckoutSessionRequest
import com.dodopayments.api.models.checkoutsessions.CheckoutSessionResponse
// Configure using environment variables (DODO_PAYMENTS_API_KEY, DODO_PAYMENTS_BASE_URL)
// Or system properties (dodopayments.apiKey, dodopayments.baseUrl)
val client: DodoPaymentsClient = DodoPaymentsOkHttpClient. fromEnv ()
val params: CheckoutSessionRequest = CheckoutSessionRequest. builder ()
. addProductCart (CheckoutSessionRequest.ProductCart. builder ()
. productId ( "product_id" )
. quantity ( 1 )
. build ())
. build ()
val checkoutSessionResponse: CheckoutSessionResponse = client. checkoutSessions (). create (params)
println (checkoutSessionResponse. sessionId ())
Always store your API keys securely using environment variables or encrypted configuration. Never commit them to version control.
Core Features
Coroutines Full support for Kotlin coroutines for asynchronous operations
Null Safety Leverage Kotlin’s null safety for robust error handling
Extension Functions Idiomatic Kotlin extensions for enhanced functionality
Data Classes Type-safe data classes with copy and destructuring support
Configuration
From Environment Variables
Initialize from environment variables or system properties:
val client: DodoPaymentsClient = DodoPaymentsOkHttpClient. fromEnv ()
Manual Configuration
Configure manually with all options:
import java.time.Duration
val client = DodoPaymentsOkHttpClient. builder ()
. bearerToken ( "your_api_key_here" )
. baseUrl ( "https://live.dodopayments.com" )
. maxRetries ( 3 )
. timeout (Duration. ofSeconds ( 30 ))
. build ()
Test Mode
Configure for test/sandbox environment:
val testClient = DodoPaymentsOkHttpClient. builder ()
. fromEnv ()
. testMode ()
. build ()
Timeouts and Retries
Configure globally or per-request:
import com.dodopayments.api.core.RequestOptions
// Global configuration
val client = DodoPaymentsOkHttpClient. builder ()
. fromEnv ()
. timeout (Duration. ofSeconds ( 45 ))
. maxRetries ( 3 )
. build ()
// Per-request timeout override
val product = client. products (). retrieve (
"prod_123" ,
RequestOptions. builder ()
. timeout (Duration. ofSeconds ( 10 ))
. build ()
)
Common Operations
Create a Checkout Session
Generate a checkout session:
val params = CheckoutSessionRequest. builder ()
. addProductCart (CheckoutSessionRequest.ProductCart. builder ()
. productId ( "prod_123" )
. quantity ( 1 )
. build ())
. returnUrl ( "https://yourdomain.com/return" )
. build ()
val session = client. checkoutSessions (). create (params)
println ( "Checkout URL: ${ session. url () } " )
Create a Product
Create products with detailed configuration:
import com.dodopayments.api.models.products.Product
import com.dodopayments.api.models.products.ProductCreateParams
import com.dodopayments.api.models.misc.Currency
import com.dodopayments.api.models.misc.TaxCategory
val createParams = ProductCreateParams. builder ()
. name ( "Premium Subscription" )
. description ( "Monthly subscription with all features" )
. price (
ProductCreateParams.RecurringPrice. builder ()
. currency (Currency.USD)
. preTaxAmount ( 2999 ) // $29.99 in cents
. paymentFrequencyInterval (ProductCreateParams.RecurringPrice.TimeInterval.MONTH)
. paymentFrequencyCount ( 1 )
. build ()
)
. taxCategory (TaxCategory.DIGITAL_GOODS)
. build ()
val product: Product = client. products (). create (createParams)
println ( "Created product ID: ${ product. productId () } " )
Activate License Key
Activate license keys for customers:
import com.dodopayments.api.models.licenses.LicenseActivateParams
import com.dodopayments.api.models.licenses.LicenseActivateResponse
val activateParams = LicenseActivateParams. builder ()
. licenseKey ( "XXXX-XXXX-XXXX-XXXX" )
. instanceName ( "user-laptop-01" )
. build ()
try {
val activationResult: LicenseActivateResponse = client. licenses ()
. activate (activateParams)
println ( "License activated successfully" )
println ( "Instance ID: ${ activationResult. instanceId () } " )
println ( "Expires at: ${ activationResult. expiresAt () } " )
} catch (e: UnprocessableEntityException ) {
println ( "License activation failed: ${ e.message } " )
}
Usage-Based Billing
Record Usage Events
Track usage for meters:
import com.dodopayments.api.models.usageevents.UsageEventCreateParams
import java.time.OffsetDateTime
val usageParams = UsageEventCreateParams. builder ()
. meterId ( "meter_123" )
. customerId ( "cust_456" )
. value ( 150 )
. timestamp (OffsetDateTime. now ())
. build ()
client. usageEvents (). create (usageParams)
println ( "Usage event recorded" )
Async Operations
Async Client
Use the async client for coroutine-based operations:
import com.dodopayments.api.client.DodoPaymentsClientAsync
import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClientAsync
import kotlinx.coroutines.runBlocking
val asyncClient: DodoPaymentsClientAsync = DodoPaymentsOkHttpClientAsync. fromEnv ()
runBlocking {
val customer = asyncClient. customers (). retrieve ( "cust_123" )
println ( "Customer email: ${ customer. email () } " )
}
Error Handling
Handle errors with Kotlin’s exception handling:
import com.dodopayments.api.errors. *
try {
val payment = client. payments (). create (params)
println ( "Success: ${ payment. id () } " )
} catch (e: AuthenticationException ) {
println ( "Authentication failed: ${ e.message } " )
} catch (e: InvalidRequestException ) {
println ( "Invalid request: ${ e.message } " )
e.parameter?. let { println ( "Parameter: $it " ) }
} catch (e: RateLimitException ) {
println ( "Rate limit exceeded, retry after: ${ e.retryAfter } " )
} catch (e: DodoPaymentsServiceException ) {
println ( "API error: ${ e. statusCode () } - ${ e.message } " )
}
Functional Error Handling
Use Result for functional error handling:
fun safeCreatePayment (client: DodoPaymentsClient ): Result < Payment > = runCatching {
client. payments (). create (params)
}
// Usage
safe CreatePayment (client)
. onSuccess { payment -> println ( "Created: ${ payment. id () } " ) }
. onFailure { error -> println ( "Error: ${ error.message } " ) }
Use Kotlin’s runCatching for a more functional approach to error handling with Result types.
Android Integration
Use with Android applications:
import android.app.Application
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.dodopayments.api.client.DodoPaymentsClient
import kotlinx.coroutines.launch
class PaymentViewModel (application: Application ) : ViewModel () {
private val client = DodoPaymentsOkHttpClient. builder ()
. bearerToken (BuildConfig.DODO_API_KEY)
. build ()
fun createCheckout (productId: String ) {
viewModelScope. launch {
try {
val session = client. async (). checkoutSessions (). create (params)
// Open checkout URL in browser or WebView
openUrl (session. url ())
} catch (e: Exception ) {
handleError (e)
}
}
}
}
Response Validation
Enable response validation:
import com.dodopayments.api.core.RequestOptions
// Per-request validation
val product = client. products (). retrieve (
"prod_123" ,
RequestOptions. builder ()
. responseValidation ( true )
. build ()
)
// Or validate explicitly
val validatedProduct = product. validate ()
Advanced Features
Proxy Configuration
Configure proxy settings:
import java.net.InetSocketAddress
import java.net.Proxy
val client = DodoPaymentsOkHttpClient. builder ()
. fromEnv ()
. proxy (
Proxy (
Proxy.Type.HTTP,
InetSocketAddress ( "proxy.example.com" , 8080 )
)
)
. build ()
Temporary Configuration
Modify client configuration temporarily:
val customClient = client. withOptions {
it. baseUrl ( "https://example.com" )
it. maxRetries ( 5 )
}
Ktor Integration
Integrate with Ktor server applications:
import io.ktor.server.application. *
import io.ktor.server.request. *
import io.ktor.server.response. *
import io.ktor.server.routing. *
fun Application . configureRouting () {
val client = DodoPaymentsOkHttpClient. builder ()
. bearerToken (environment.config. property ( "dodo.apiKey" ). getString ())
. build ()
routing {
post ( "/create-checkout" ) {
try {
val request = call. receive < CheckoutRequest >()
val session = client. checkoutSessions (). create (params)
call. respond ( mapOf ( "checkout_url" to session. url ()))
} catch (e: DodoPaymentsServiceException ) {
call. respond (HttpStatusCode.BadRequest, mapOf ( "error" to e.message))
}
}
}
}
Resources
Support
Need help with the Kotlin SDK?
Contributing
We welcome contributions! Check the contributing guidelines to get started.