Repository: Adyen/adyen-android
Pull request #2110: v6: AdyenCheckout - Initialize Sessions 
Author: login: ozgur00
Labels: name: Chore
description: [PRs only] Indicates any task that does not need to be mentioned in the public release notes
Created: 2025-05-01T10:06:40Z | Merged: 2025-05-26T14:06:30Z

## Description
[//]: # (Include a short summary of your changes)
[//]: # (If this is a new feature: attach screenshots or a video if applicable)
[//]: # (If this is a bug fix: include a reproduction path)
In the initialization block of AdyenCheckout we're initializing sessions with the changes in this PR. I have copied a lot of classes from several core modules (`sessions-core`, `components-core`, `checkout-core`). A lot of the size of the change comes from that.

COSDK-441



Diff:
diff --git a/core/api/core.api b/core/api/core.api
index bd6f7801d1..9777744680 100644
--- a/core/api/core.api
+++ b/core/api/core.api
@@ -1,6 +1,45 @@
 public final class com/adyen/checkout/core/AdyenCheckout {
 	public static final field $stable I
-	public fun <init> ()V
+	public static final field Companion Lcom/adyen/checkout/core/AdyenCheckout$Companion;
+	public fun <init> (Lcom/adyen/checkout/core/sessions/CheckoutSession;)V
+	public final fun component1 ()Lcom/adyen/checkout/core/sessions/CheckoutSession;
+	public final fun copy (Lcom/adyen/checkout/core/sessions/CheckoutSession;)Lcom/adyen/checkout/core/AdyenCheckout;
+	public static synthetic fun copy$default (Lcom/adyen/checkout/core/AdyenCheckout;Lcom/adyen/checkout/core/sessions/CheckoutSession;ILjava/lang/Object;)Lcom/adyen/checkout/core/AdyenCheckout;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getCheckoutSession ()Lcom/adyen/checkout/core/sessions/CheckoutSession;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class com/adyen/checkout/core/AdyenCheckout$Companion {
+	public final fun initialize (Lcom/adyen/checkout/core/sessions/SessionModel;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+}
+
+public abstract interface class com/adyen/checkout/core/AdyenCheckout$Result {
+}
+
+public final class com/adyen/checkout/core/AdyenCheckout$Result$Error : com/adyen/checkout/core/AdyenCheckout$Result {
+	public static final field $stable I
+	public fun <init> (Ljava/lang/String;)V
+	public final fun component1 ()Ljava/lang/String;
+	public final fun copy (Ljava/lang/String;)Lcom/adyen/checkout/core/AdyenCheckout$Result$Error;
+	public static synthetic fun copy$default (Lcom/adyen/checkout/core/AdyenCheckout$Result$Error;Ljava/lang/String;ILjava/lang/Object;)Lcom/adyen/checkout/core/AdyenCheckout$Result$Error;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getErrorReason ()Ljava/lang/String;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public final class com/adyen/checkout/core/AdyenCheckout$Result$Success : com/adyen/checkout/core/AdyenCheckout$Result {
+	public static final field $stable I
+	public fun <init> (Lcom/adyen/checkout/core/AdyenCheckout;)V
+	public final fun component1 ()Lcom/adyen/checkout/core/AdyenCheckout;
+	public final fun copy (Lcom/adyen/checkout/core/AdyenCheckout;)Lcom/adyen/checkout/core/AdyenCheckout$Result$Success;
+	public static synthetic fun copy$default (Lcom/adyen/checkout/core/AdyenCheckout$Result$Success;Lcom/adyen/checkout/core/AdyenCheckout;ILjava/lang/Object;)Lcom/adyen/checkout/core/AdyenCheckout$Result$Success;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getAdyenCheckout ()Lcom/adyen/checkout/core/AdyenCheckout;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
 }
 
 public final class com/adyen/checkout/core/AdyenPaymentFlowKt {
@@ -15,6 +54,164 @@ public final class com/adyen/checkout/core/BuildConfig {
 	public fun <init> ()V
 }
 
+public final class com/adyen/checkout/core/Environment : android/os/Parcelable {
+	public static final field $stable I
+	public static final field APSE Lcom/adyen/checkout/core/Environment;
+	public static final field AUSTRALIA Lcom/adyen/checkout/core/Environment;
+	public static final field CREATOR Landroid/os/Parcelable$Creator;
+	public static final field Companion Lcom/adyen/checkout/core/Environment$Companion;
+	public static final field EUROPE Lcom/adyen/checkout/core/Environment;
+	public static final field INDIA Lcom/adyen/checkout/core/Environment;
+	public static final field TEST Lcom/adyen/checkout/core/Environment;
+	public static final field UNITED_STATES Lcom/adyen/checkout/core/Environment;
+	public final fun component1 ()Ljava/net/URL;
+	public final fun component2 ()Ljava/net/URL;
+	public final fun copy (Ljava/net/URL;Ljava/net/URL;)Lcom/adyen/checkout/core/Environment;
+	public static synthetic fun copy$default (Lcom/adyen/checkout/core/Environment;Ljava/net/URL;Ljava/net/URL;ILjava/lang/Object;)Lcom/adyen/checkout/core/Environment;
+	public final fun describeContents ()I
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getCheckoutAnalyticsBaseUrl ()Ljava/net/URL;
+	public final fun getCheckoutShopperBaseUrl ()Ljava/net/URL;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+	public final fun writeToParcel (Landroid/os/Parcel;I)V
+}
+
+public final class com/adyen/checkout/core/Environment$Companion {
+}
+
+public final class com/adyen/checkout/core/Environment$Creator : android/os/Parcelable$Creator {
+	public fun <init> ()V
+	public final fun createFromParcel (Landroid/os/Parcel;)Lcom/adyen/checkout/core/Environment;
+	public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
+	public final fun newArray (I)[Lcom/adyen/checkout/core/Environment;
+	public synthetic fun newArray (I)[Ljava/lang/Object;
+}
+
+public final class com/adyen/checkout/core/data/model/Amount : com/adyen/checkout/core/internal/data/model/ModelObject {
+	public static final field $stable I
+	public static final field CREATOR Landroid/os/Parcelable$Creator;
+	public static final field Companion Lcom/adyen/checkout/core/data/model/Amount$Companion;
+	public static final field SERIALIZER Lcom/adyen/checkout/core/internal/data/model/ModelObject$Serializer;
+	public fun <init> ()V
+	public fun <init> (Ljava/lang/String;J)V
+	public synthetic fun <init> (Ljava/lang/String;JILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun component1 ()Ljava/lang/String;
+	public final fun component2 ()J
+	public final fun copy (Ljava/lang/String;J)Lcom/adyen/checkout/core/data/model/Amount;
+	public static synthetic fun copy$default (Lcom/adyen/checkout/core/data/model/Amount;Ljava/lang/String;JILjava/lang/Object;)Lcom/adyen/checkout/core/data/model/Amount;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getCurrency ()Ljava/lang/String;
+	public final fun getValue ()J
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+	public final fun writeToParcel (Landroid/os/Parcel;I)V
+}
+
+public final class com/adyen/checkout/core/data/model/Amount$Companion {
+}
+
+public final class com/adyen/checkout/core/data/model/Amount$Creator : android/os/Parcelable$Creator {
+	public fun <init> ()V
+	public final fun createFromParcel (Landroid/os/Parcel;)Lcom/adyen/checkout/core/data/model/Amount;
+	public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
+	public final fun newArray (I)[Lcom/adyen/checkout/core/data/model/Amount;
+	public synthetic fun newArray (I)[Ljava/lang/Object;
+}
+
+public final class com/adyen/checkout/core/data/model/PaymentMethod : com/adyen/checkout/core/internal/data/model/ModelObject {
+	public static final field $stable I
+	public static final field CREATOR Landroid/os/Parcelable$Creator;
+	public static final field Companion Lcom/adyen/checkout/core/data/model/PaymentMethod$Companion;
+	public static final field SERIALIZER Lcom/adyen/checkout/core/internal/data/model/ModelObject$Serializer;
+	public fun <init> ()V
+	public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
+	public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun component1 ()Ljava/lang/String;
+	public final fun component2 ()Ljava/lang/String;
+	public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lcom/adyen/checkout/core/data/model/PaymentMethod;
+	public static synthetic fun copy$default (Lcom/adyen/checkout/core/data/model/PaymentMethod;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/adyen/checkout/core/data/model/PaymentMethod;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getName ()Ljava/lang/String;
+	public final fun getType ()Ljava/lang/String;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+	public final fun writeToParcel (Landroid/os/Parcel;I)V
+}
+
+public final class com/adyen/checkout/core/data/model/PaymentMethod$Companion {
+}
+
+public final class com/adyen/checkout/core/data/model/PaymentMethod$Creator : android/os/Parcelable$Creator {
+	public fun <init> ()V
+	public final fun createFromParcel (Landroid/os/Parcel;)Lcom/adyen/checkout/core/data/model/PaymentMethod;
+	public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
+	public final fun newArray (I)[Lcom/adyen/checkout/core/data/model/PaymentMethod;
+	public synthetic fun newArray (I)[Ljava/lang/Object;
+}
+
+public final class com/adyen/checkout/core/data/model/PaymentMethodsApiResponse : com/adyen/checkout/core/internal/data/model/ModelObject {
+	public static final field $stable I
+	public static final field CREATOR Landroid/os/Parcelable$Creator;
+	public static final field Companion Lcom/adyen/checkout/core/data/model/PaymentMethodsApiResponse$Companion;
+	public static final field SERIALIZER Lcom/adyen/checkout/core/internal/data/model/ModelObject$Serializer;
+	public fun <init> ()V
+	public fun <init> (Ljava/util/List;)V
+	public synthetic fun <init> (Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun component1 ()Ljava/util/List;
+	public final fun copy (Ljava/util/List;)Lcom/adyen/checkout/core/data/model/PaymentMethodsApiResponse;
+	public static synthetic fun copy$default (Lcom/adyen/checkout/core/data/model/PaymentMethodsApiResponse;Ljava/util/List;ILjava/lang/Object;)Lcom/adyen/checkout/core/data/model/PaymentMethodsApiResponse;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getPaymentMethods ()Ljava/util/List;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+	public final fun writeToParcel (Landroid/os/Parcel;I)V
+}
+
+public final class com/adyen/checkout/core/data/model/PaymentMethodsApiResponse$Companion {
+}
+
+public final class com/adyen/checkout/core/data/model/PaymentMethodsApiResponse$Creator : android/os/Parcelable$Creator {
+	public fun <init> ()V
+	public final fun createFromParcel (Landroid/os/Parcel;)Lcom/adyen/checkout/core/data/model/PaymentMethodsApiResponse;
+	public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
+	public final fun newArray (I)[Lcom/adyen/checkout/core/data/model/PaymentMethodsApiResponse;
+	public synthetic fun newArray (I)[Ljava/lang/Object;
+}
+
+public final class com/adyen/checkout/core/exception/HttpException : java/lang/RuntimeException {
+	public static final field $stable I
+	public fun <init> (ILjava/lang/String;Lcom/adyen/checkout/core/internal/data/model/ErrorResponseBody;)V
+	public final fun getCode ()I
+	public final fun getErrorBody ()Lcom/adyen/checkout/core/internal/data/model/ErrorResponseBody;
+}
+
+public final class com/adyen/checkout/core/exception/ModelSerializationException : java/lang/RuntimeException {
+	public static final field $stable I
+	public fun <init> (Ljava/lang/Class;Lorg/json/JSONException;)V
+}
+
+public final class com/adyen/checkout/core/internal/data/model/ErrorResponseBody$Companion {
+}
+
+public final class com/adyen/checkout/core/internal/data/model/ErrorResponseBody$Creator : android/os/Parcelable$Creator {
+	public fun <init> ()V
+	public final fun createFromParcel (Landroid/os/Parcel;)Lcom/adyen/checkout/core/internal/data/model/ErrorResponseBody;
+	public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
+	public final fun newArray (I)[Lcom/adyen/checkout/core/internal/data/model/ErrorResponseBody;
+	public synthetic fun newArray (I)[Ljava/lang/Object;
+}
+
+public abstract class com/adyen/checkout/core/internal/data/model/ModelObject : android/os/Parcelable {
+	public static final field $stable I
+	public fun describeContents ()I
+}
+
+public abstract interface class com/adyen/checkout/core/internal/data/model/ModelObject$Serializer {
+	public abstract fun deserialize (Lorg/json/JSONObject;)Lcom/adyen/checkout/core/internal/data/model/ModelObject;
+	public abstract fun serialize (Lcom/adyen/checkout/core/internal/data/model/ModelObject;)Lorg/json/JSONObject;
+}
+
 public final class com/adyen/checkout/core/internal/ui/view/ComposableSingletons$PayButtonKt {
 	public static final field INSTANCE Lcom/adyen/checkout/core/internal/ui/view/ComposableSingletons$PayButtonKt;
 	public fun <init> ()V
@@ -32,3 +229,166 @@ public final class com/adyen/checkout/core/mbway/internal/ui/view/ComposableSing
 	public final fun getLambda-2$core_release ()Lkotlin/jvm/functions/Function2;
 }
 
+public final class com/adyen/checkout/core/sessions/CheckoutSession {
+	public static final field $stable I
+	public fun <init> (Lcom/adyen/checkout/core/sessions/data/SessionSetupResponse;Lcom/adyen/checkout/core/Environment;Ljava/lang/String;)V
+	public final fun component1 ()Lcom/adyen/checkout/core/sessions/data/SessionSetupResponse;
+	public final fun component2 ()Lcom/adyen/checkout/core/Environment;
+	public final fun component3 ()Ljava/lang/String;
+	public final fun copy (Lcom/adyen/checkout/core/sessions/data/SessionSetupResponse;Lcom/adyen/checkout/core/Environment;Ljava/lang/String;)Lcom/adyen/checkout/core/sessions/CheckoutSession;
+	public static synthetic fun copy$default (Lcom/adyen/checkout/core/sessions/CheckoutSession;Lcom/adyen/checkout/core/sessions/data/SessionSetupResponse;Lcom/adyen/checkout/core/Environment;Ljava/lang/String;ILjava/lang/Object;)Lcom/adyen/checkout/core/sessions/CheckoutSession;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getClientKey ()Ljava/lang/String;
+	public final fun getEnvironment ()Lcom/adyen/checkout/core/Environment;
+	public final fun getPaymentMethod (Ljava/lang/String;)Lcom/adyen/checkout/core/data/model/PaymentMethod;
+	public final fun getSessionSetupResponse ()Lcom/adyen/checkout/core/sessions/data/SessionSetupResponse;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+}
+
+public abstract class com/adyen/checkout/core/sessions/CheckoutSessionResult {
+	public static final field $stable I
+}
+
+public final class com/adyen/checkout/core/sessions/CheckoutSessionResult$Error : com/adyen/checkout/core/sessions/CheckoutSessionResult {
+	public static final field $stable I
+	public fun <init> (Ljava/lang/Exception;)V
+	public final fun getException ()Ljava/lang/Exception;
+}
+
+public final class com/adyen/checkout/core/sessions/CheckoutSessionResult$Success : com/adyen/checkout/core/sessions/CheckoutSessionResult {
+	public static final field $stable I
+	public fun <init> (Lcom/adyen/checkout/core/sessions/CheckoutSession;)V
+	public final fun getCheckoutSession ()Lcom/adyen/checkout/core/sessions/CheckoutSession;
+}
+
+public final class com/adyen/checkout/core/sessions/SessionModel : com/adyen/checkout/core/internal/data/model/ModelObject {
+	public static final field $stable I
+	public static final field CREATOR Landroid/os/Parcelable$Creator;
+	public static final field Companion Lcom/adyen/checkout/core/sessions/SessionModel$Companion;
+	public static final field SERIALIZER Lcom/adyen/checkout/core/internal/data/model/ModelObject$Serializer;
+	public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
+	public final fun component1 ()Ljava/lang/String;
+	public final fun component2 ()Ljava/lang/String;
+	public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lcom/adyen/checkout/core/sessions/SessionModel;
+	public static synthetic fun copy$default (Lcom/adyen/checkout/core/sessions/SessionModel;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/adyen/checkout/core/sessions/SessionModel;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getId ()Ljava/lang/String;
+	public final fun getSessionData ()Ljava/lang/String;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+	public final fun writeToParcel (Landroid/os/Parcel;I)V
+}
+
+public final class com/adyen/checkout/core/sessions/SessionModel$Companion {
+}
+
+public final class com/adyen/checkout/core/sessions/SessionModel$Creator : android/os/Parcelable$Creator {
+	public fun <init> ()V
+	public final fun createFromParcel (Landroid/os/Parcel;)Lcom/adyen/checkout/core/sessions/SessionModel;
+	public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
+	public final fun newArray (I)[Lcom/adyen/checkout/core/sessions/SessionModel;
+	public synthetic fun newArray (I)[Ljava/lang/Object;
+}
+
+public final class com/adyen/checkout/core/sessions/data/SessionSetupConfiguration : com/adyen/checkout/core/internal/data/model/ModelObject {
+	public static final field $stable I
+	public static final field CREATOR Landroid/os/Parcelable$Creator;
+	public static final field Companion Lcom/adyen/checkout/core/sessions/data/SessionSetupConfiguration$Companion;
+	public static final field SERIALIZER Lcom/adyen/checkout/core/internal/data/model/ModelObject$Serializer;
+	public fun <init> ()V
+	public fun <init> (Ljava/lang/Boolean;ZLjava/lang/Boolean;)V
+	public synthetic fun <init> (Ljava/lang/Boolean;ZLjava/lang/Boolean;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+	public final fun component1 ()Ljava/lang/Boolean;
+	public final fun component2 ()Z
+	public final fun component3 ()Ljava/lang/Boolean;
+	public final fun copy (Ljava/lang/Boolean;ZLjava/lang/Boolean;)Lcom/adyen/checkout/core/sessions/data/SessionSetupConfiguration;
+	public static synthetic fun copy$default (Lcom/adyen/checkout/core/sessions/data/SessionSetupConfiguration;Ljava/lang/Boolean;ZLjava/lang/Boolean;ILjava/lang/Object;)Lcom/adyen/checkout/core/sessions/data/SessionSetupConfiguration;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getEnableStoreDetails ()Ljava/lang/Boolean;
+	public final fun getShowInstallmentAmount ()Z
+	public final fun getShowRemovePaymentMethodButton ()Ljava/lang/Boolean;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+	public final fun writeToParcel (Landroid/os/Parcel;I)V
+}
+
+public final class com/adyen/checkout/core/sessions/data/SessionSetupConfiguration$Companion {
+}
+
+public final class com/adyen/checkout/core/sessions/data/SessionSetupConfiguration$Creator : android/os/Parcelable$Creator {
+	public fun <init> ()V
+	public final fun createFromParcel (Landroid/os/Parcel;)Lcom/adyen/checkout/core/sessions/data/SessionSetupConfiguration;
+	public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
+	public final fun newArray (I)[Lcom/adyen/checkout/core/sessions/data/SessionSetupConfiguration;
+	public synthetic fun newArray (I)[Ljava/lang/Object;
+}
+
+public final class com/adyen/checkout/core/sessions/data/SessionSetupRequest : com/adyen/checkout/core/internal/data/model/ModelObject {
+	public static final field $stable I
+	public static final field CREATOR Landroid/os/Parcelable$Creator;
+	public static final field Companion Lcom/adyen/checkout/core/sessions/data/SessionSetupRequest$Companion;
+	public static final field SERIALIZER Lcom/adyen/checkout/core/internal/data/model/ModelObject$Serializer;
+	public fun <init> (Ljava/lang/String;)V
+	public final fun component1 ()Ljava/lang/String;
+	public final fun copy (Ljava/lang/String;)Lcom/adyen/checkout/core/sessions/data/SessionSetupRequest;
+	public static synthetic fun copy$default (Lcom/adyen/checkout/core/sessions/data/SessionSetupRequest;Ljava/lang/String;ILjava/lang/Object;)Lcom/adyen/checkout/core/sessions/data/SessionSetupRequest;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getSessionData ()Ljava/lang/String;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+	public final fun writeToParcel (Landroid/os/Parcel;I)V
+}
+
+public final class com/adyen/checkout/core/sessions/data/SessionSetupRequest$Companion {
+}
+
+public final class com/adyen/checkout/core/sessions/data/SessionSetupRequest$Creator : android/os/Parcelable$Creator {
+	public fun <init> ()V
+	public final fun createFromParcel (Landroid/os/Parcel;)Lcom/adyen/checkout/core/sessions/data/SessionSetupRequest;
+	public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
+	public final fun newArray (I)[Lcom/adyen/checkout/core/sessions/data/SessionSetupRequest;
+	public synthetic fun newArray (I)[Ljava/lang/Object;
+}
+
+public final class com/adyen/checkout/core/sessions/data/SessionSetupResponse : com/adyen/checkout/core/internal/data/model/ModelObject {
+	public static final field $stable I
+	public static final field CREATOR Landroid/os/Parcelable$Creator;
+	public static final field Companion Lcom/adyen/checkout/core/sessions/data/SessionSetupResponse$Companion;
+	public static final field SERIALIZER Lcom/adyen/checkout/core/internal/data/model/ModelObject$Serializer;
+	public fun <init> (Ljava/lang/String;Ljava/lang/String;Lcom/adyen/checkout/core/data/model/Amount;Ljava/lang/String;Lcom/adyen/checkout/core/data/model/PaymentMethodsApiResponse;Ljava/lang/String;Lcom/adyen/checkout/core/sessions/data/SessionSetupConfiguration;Ljava/lang/String;)V
+	public final fun component1 ()Ljava/lang/String;
+	public final fun component2 ()Ljava/lang/String;
+	public final fun component3 ()Lcom/adyen/checkout/core/data/model/Amount;
+	public final fun component4 ()Ljava/lang/String;
+	public final fun component5 ()Lcom/adyen/checkout/core/data/model/PaymentMethodsApiResponse;
+	public final fun component6 ()Ljava/lang/String;
+	public final fun component7 ()Lcom/adyen/checkout/core/sessions/data/SessionSetupConfiguration;
+	public final fun component8 ()Ljava/lang/String;
+	public final fun copy (Ljava/lang/String;Ljava/lang/String;Lcom/adyen/checkout/core/data/model/Amount;Ljava/lang/String;Lcom/adyen/checkout/core/data/model/PaymentMethodsApiResponse;Ljava/lang/String;Lcom/adyen/checkout/core/sessions/data/SessionSetupConfiguration;Ljava/lang/String;)Lcom/adyen/checkout/core/sessions/data/SessionSetupResponse;
+	public static synthetic fun copy$default (Lcom/adyen/checkout/core/sessions/data/SessionSetupResponse;Ljava/lang/String;Ljava/lang/String;Lcom/adyen/checkout/core/data/model/Amount;Ljava/lang/String;Lcom/adyen/checkout/core/data/model/PaymentMethodsApiResponse;Ljava/lang/String;Lcom/adyen/checkout/core/sessions/data/SessionSetupConfiguration;Ljava/lang/String;ILjava/lang/Object;)Lcom/adyen/checkout/core/sessions/data/SessionSetupResponse;
+	public fun equals (Ljava/lang/Object;)Z
+	public final fun getAmount ()Lcom/adyen/checkout/core/data/model/Amount;
+	public final fun getConfiguration ()Lcom/adyen/checkout/core/sessions/data/SessionSetupConfiguration;
+	public final fun getExpiresAt ()Ljava/lang/String;
+	public final fun getId ()Ljava/lang/String;
+	public final fun getPaymentMethodsApiResponse ()Lcom/adyen/checkout/core/data/model/PaymentMethodsApiResponse;
+	public final fun getReturnUrl ()Ljava/lang/String;
+	public final fun getSessionData ()Ljava/lang/String;
+	public final fun getShopperLocale ()Ljava/lang/String;
+	public fun hashCode ()I
+	public fun toString ()Ljava/lang/String;
+	public final fun writeToParcel (Landroid/os/Parcel;I)V
+}
+
+public final class com/adyen/checkout/core/sessions/data/SessionSetupResponse$Companion {
+}
+
+public final class com/adyen/checkout/core/sessions/data/SessionSetupResponse$Creator : android/os/Parcelable$Creator {
+	public fun <init> ()V
+	public final fun createFromParcel (Landroid/os/Parcel;)Lcom/adyen/checkout/core/sessions/data/SessionSetupResponse;
+	public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
+	public final fun newArray (I)[Lcom/adyen/checkout/core/sessions/data/SessionSetupResponse;
+	public synthetic fun newArray (I)[Ljava/lang/Object;
+}
+
diff --git a/core/build.gradle b/core/build.gradle
index ddb21e1d37..3b4c2efdc2 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -50,6 +50,7 @@ dependencies {
     implementation libs.bundles.compose.ui
     implementation libs.compose.hilt
     implementation libs.compose.viewmodel
+    implementation libs.okhttp
 
     testImplementation libs.bundles.junit
     testImplementation libs.bundles.mockito
diff --git a/core/src/main/java/com/adyen/checkout/core/AdyenCheckout.kt b/core/src/main/java/com/adyen/checkout/core/AdyenCheckout.kt
index 4429cc8bf8..e156c2d381 100644
--- a/core/src/main/java/com/adyen/checkout/core/AdyenCheckout.kt
+++ b/core/src/main/java/com/adyen/checkout/core/AdyenCheckout.kt
@@ -8,4 +8,50 @@
 
 package com.adyen.checkout.core
 
-class AdyenCheckout
+import com.adyen.checkout.core.sessions.CheckoutSession
+import com.adyen.checkout.core.sessions.CheckoutSessionProvider
+import com.adyen.checkout.core.sessions.CheckoutSessionResult
+import com.adyen.checkout.core.sessions.SessionModel
+
+data class AdyenCheckout(
+    val checkoutSession: CheckoutSession?,
+) {
+
+    companion object {
+        suspend fun initialize(
+            sessionModel: SessionModel,
+            // TODO - Configuration
+            clientKey: String,
+        ): AdyenCheckout.Result {
+            val checkoutSession = getCheckoutSession(sessionModel, clientKey)
+            return when {
+                checkoutSession != null -> Result.Success(
+                    adyenCheckout = AdyenCheckout(checkoutSession),
+                )
+
+                else -> Result.Error("Session initialization failed.")
+            }
+        }
+
+        private suspend fun getCheckoutSession(
+            sessionModel: SessionModel,
+            clientKey: String,
+            // TODO - Configuration
+//        checkoutConfiguration: CheckoutConfiguration
+        ): CheckoutSession? {
+            return when (
+                val result = CheckoutSessionProvider.createSession(sessionModel, Environment.TEST, clientKey)
+            ) {
+                is CheckoutSessionResult.Success -> result.checkoutSession
+                is CheckoutSessionResult.Error -> {
+                    null
+                }
+            }
+        }
+    }
+
+    sealed interface Result {
+        data class Success(val adyenCheckout: AdyenCheckout) : Result
+        data class Error(val errorReason: String) : Result
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/DispatcherProvider.kt b/core/src/main/java/com/adyen/checkout/core/DispatcherProvider.kt
new file mode 100644
index 0000000000..a07a046705
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/DispatcherProvider.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core
+
+import androidx.annotation.RestrictTo
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.MainCoroutineDispatcher
+
+@Suppress("NotDispatcherProvider")
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+object DispatcherProvider {
+
+    private var mainFactory = { Dispatchers.Main }
+    val Main: MainCoroutineDispatcher get() = mainFactory()
+
+    private var defaultFactory = { Dispatchers.Default }
+    val Default: CoroutineDispatcher get() = defaultFactory()
+
+    private var ioFactory = { Dispatchers.IO }
+    val IO: CoroutineDispatcher get() = ioFactory()
+
+    fun overrideMain(dispatcher: MainCoroutineDispatcher) {
+        mainFactory = { dispatcher }
+    }
+
+    fun overrideIO(dispatcher: CoroutineDispatcher) {
+        ioFactory = { dispatcher }
+    }
+
+    fun overrideDefault(dispatcher: CoroutineDispatcher) {
+        defaultFactory = { dispatcher }
+    }
+
+    fun resetMain() {
+        mainFactory = { Dispatchers.Main }
+    }
+
+    fun resetIO() {
+        ioFactory = { Dispatchers.IO }
+    }
+
+    fun resetDefault() {
+        defaultFactory = { Dispatchers.Default }
+    }
+
+    fun resetAll() {
+        resetMain()
+        resetIO()
+        resetDefault()
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/Environment.kt b/core/src/main/java/com/adyen/checkout/core/Environment.kt
new file mode 100644
index 0000000000..be0d2dee63
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/Environment.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+import java.net.URL
+
+/**
+ * Identifies which host URL to be used for internal network calls.
+ */
+@Parcelize
+data class Environment internal constructor(
+    val checkoutShopperBaseUrl: URL,
+    val checkoutAnalyticsBaseUrl: URL
+) : Parcelable {
+
+    companion object {
+
+        @JvmField
+        val TEST: Environment = Environment(
+            checkoutShopperBaseUrl = URL("https://checkoutshopper-test.adyen.com/checkoutshopper/"),
+            checkoutAnalyticsBaseUrl = URL("https://checkoutanalytics-test.adyen.com/checkoutanalytics/")
+        )
+
+        @JvmField
+        val EUROPE: Environment = Environment(
+            checkoutShopperBaseUrl = URL("https://checkoutshopper-live.adyen.com/checkoutshopper/"),
+            checkoutAnalyticsBaseUrl = URL("https://checkoutanalytics-live.adyen.com/checkoutanalytics/")
+        )
+
+        @JvmField
+        val UNITED_STATES: Environment = Environment(
+            checkoutShopperBaseUrl = URL("https://checkoutshopper-live-us.adyen.com/checkoutshopper/"),
+            checkoutAnalyticsBaseUrl = URL("https://checkoutanalytics-live-us.adyen.com/checkoutanalytics/")
+        )
+
+        @JvmField
+        val AUSTRALIA: Environment = Environment(
+            checkoutShopperBaseUrl = URL("https://checkoutshopper-live-au.adyen.com/checkoutshopper/"),
+            checkoutAnalyticsBaseUrl = URL("https://checkoutanalytics-live-au.adyen.com/checkoutanalytics/")
+        )
+
+        @JvmField
+        val INDIA: Environment = Environment(
+            checkoutShopperBaseUrl = URL("https://checkoutshopper-live-in.adyen.com/checkoutshopper/"),
+            checkoutAnalyticsBaseUrl = URL("https://checkoutanalytics-live-in.adyen.com/checkoutanalytics/")
+        )
+
+        @JvmField
+        val APSE: Environment = Environment(
+            checkoutShopperBaseUrl = URL("https://checkoutshopper-live-apse.adyen.com/checkoutshopper/"),
+            checkoutAnalyticsBaseUrl = URL("https://checkoutanalytics-live-apse.adyen.com/checkoutanalytics/")
+        )
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/data/model/Amount.kt b/core/src/main/java/com/adyen/checkout/core/data/model/Amount.kt
new file mode 100644
index 0000000000..8426aa86eb
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/data/model/Amount.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 1/5/2025.
+ */
+
+package com.adyen.checkout.core.data.model
+
+import com.adyen.checkout.core.exception.ModelSerializationException
+import com.adyen.checkout.core.internal.data.model.ModelObject
+import com.adyen.checkout.core.internal.data.model.getLongOrNull
+import com.adyen.checkout.core.internal.data.model.getStringOrNull
+import kotlinx.parcelize.Parcelize
+import org.json.JSONException
+import org.json.JSONObject
+
+@Parcelize
+data class Amount(
+    val currency: String? = null,
+    val value: Long = 0L,
+) : ModelObject() {
+
+    companion object {
+        private const val CURRENCY = "currency"
+        private const val VALUE = "value"
+
+        @JvmField
+        val SERIALIZER: Serializer<Amount> = object : Serializer<Amount> {
+            override fun serialize(modelObject: Amount): JSONObject {
+                return try {
+                    JSONObject().apply {
+                        putOpt(CURRENCY, modelObject.currency)
+                        putOpt(VALUE, modelObject.value)
+                    }
+                } catch (e: JSONException) {
+                    throw ModelSerializationException(Amount::class.java, e)
+                }
+            }
+
+            override fun deserialize(jsonObject: JSONObject): Amount {
+                return Amount(
+                    currency = jsonObject.getStringOrNull(CURRENCY),
+                    value = jsonObject.getLongOrNull(VALUE) ?: EMPTY_VALUE,
+                )
+            }
+        }
+    }
+}
+
+// TODO - Originally in AmountExt
+private const val EMPTY_VALUE = -1L
diff --git a/core/src/main/java/com/adyen/checkout/core/data/model/PaymentMethod.kt b/core/src/main/java/com/adyen/checkout/core/data/model/PaymentMethod.kt
new file mode 100644
index 0000000000..b183f12584
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/data/model/PaymentMethod.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 1/5/2025.
+ */
+
+package com.adyen.checkout.core.data.model
+
+import com.adyen.checkout.core.exception.ModelSerializationException
+import com.adyen.checkout.core.internal.data.model.ModelObject
+import com.adyen.checkout.core.internal.data.model.getStringOrNull
+import kotlinx.parcelize.Parcelize
+import org.json.JSONException
+import org.json.JSONObject
+
+@Parcelize
+data class PaymentMethod(
+    val type: String? = null,
+    val name: String? = null,
+//    var brands: List<String>? = null,
+//    var brand: String? = null,
+//    var fundingSource: String? = null,
+//    var issuers: List<Issuer>? = null,
+//    var configuration: Configuration? = null,
+//    var details: List<InputDetail>? = null,
+//    var apps: List<AppData>? = null,
+) : ModelObject() {
+
+    companion object {
+        private const val TYPE = "type"
+        private const val NAME = "name"
+
+//        // Brands is only used for type = scheme
+//        private const val BRANDS = "brands"
+//
+//        // Brand is only used for type = giftcard
+//        private const val BRAND = "brand"
+//        private const val FUNDING_SOURCE = "fundingSource"
+//        private const val ISSUERS = "issuers"
+//        private const val APPS = "apps"
+//        private const val CONFIGURATION = "configuration"
+//
+//        // This field is returned in older API versions, only used to retrieve the issuers list
+//        private const val DETAILS = "details"
+
+        @JvmField
+        val SERIALIZER: Serializer<PaymentMethod> = object : Serializer<PaymentMethod> {
+            override fun serialize(modelObject: PaymentMethod): JSONObject {
+                return try {
+                    JSONObject().apply {
+                        putOpt(TYPE, modelObject.type)
+                        putOpt(NAME, modelObject.name)
+//                        putOpt(BRANDS, serializeOptStringList(modelObject.brands))
+//                        putOpt(BRAND, modelObject.brand)
+//                        putOpt(FUNDING_SOURCE, modelObject.fundingSource)
+//                        putOpt(ISSUERS, serializeOptList(modelObject.issuers, Issuer.SERIALIZER))
+//                        putOpt(CONFIGURATION, serializeOpt(modelObject.configuration, Configuration.SERIALIZER))
+//                        putOpt(DETAILS, serializeOptList(modelObject.details, InputDetail.SERIALIZER))
+//                        putOpt(APPS, serializeOptList(modelObject.apps, AppData.SERIALIZER))
+                    }
+                } catch (e: JSONException) {
+                    throw ModelSerializationException(PaymentMethod::class.java, e)
+                }
+            }
+
+            override fun deserialize(jsonObject: JSONObject): PaymentMethod {
+                return PaymentMethod(
+                    type = jsonObject.getStringOrNull(TYPE),
+                    name = jsonObject.getStringOrNull(NAME),
+//                    brands = parseOptStringList(jsonObject.optJSONArray(BRANDS)),
+//                    brand = jsonObject.getStringOrNull(BRAND),
+//                    fundingSource = jsonObject.getStringOrNull(FUNDING_SOURCE),
+//                    issuers = deserializeOptList(jsonObject.optJSONArray(ISSUERS), Issuer.SERIALIZER),
+//                    configuration = deserializeOpt(jsonObject.optJSONObject(CONFIGURATION), Configuration.SERIALIZER),
+//                    details = deserializeOptList(jsonObject.optJSONArray(DETAILS), InputDetail.SERIALIZER),
+//                    apps = deserializeOptList(jsonObject.optJSONArray(APPS), AppData.SERIALIZER),
+                )
+            }
+        }
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/data/model/PaymentMethodsApiResponse.kt b/core/src/main/java/com/adyen/checkout/core/data/model/PaymentMethodsApiResponse.kt
new file mode 100644
index 0000000000..00d4059d46
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/data/model/PaymentMethodsApiResponse.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 1/5/2025.
+ */
+
+package com.adyen.checkout.core.data.model
+
+import com.adyen.checkout.core.exception.ModelSerializationException
+import com.adyen.checkout.core.internal.data.model.ModelObject
+import com.adyen.checkout.core.internal.data.model.ModelUtils.deserializeOptList
+import com.adyen.checkout.core.internal.data.model.ModelUtils.serializeOptList
+import kotlinx.parcelize.Parcelize
+import org.json.JSONException
+import org.json.JSONObject
+
+/**
+ * Object that parses and holds the response data from the /paymentMethods endpoint.
+ * Use [PaymentMethodsApiResponse.SERIALIZER] to deserialize this class from your JSON response.
+ */
+@Parcelize
+data class PaymentMethodsApiResponse(
+    // TODO - Stored Payment Methods
+//    var storedPaymentMethods: List<StoredPaymentMethod>? = null,
+    val paymentMethods: List<PaymentMethod>? = null,
+) : ModelObject() {
+
+    companion object {
+        //        private const val STORED_PAYMENT_METHODS = "storedPaymentMethods"
+        private const val PAYMENT_METHODS = "paymentMethods"
+
+        @JvmField
+        val SERIALIZER: Serializer<PaymentMethodsApiResponse> = object : Serializer<PaymentMethodsApiResponse> {
+            override fun serialize(modelObject: PaymentMethodsApiResponse): JSONObject {
+                return try {
+                    JSONObject().apply {
+//                        putOpt(
+//                            STORED_PAYMENT_METHODS,
+//                            serializeOptList(modelObject.storedPaymentMethods, StoredPaymentMethod.SERIALIZER)
+//                        )
+                        putOpt(
+                            PAYMENT_METHODS,
+                            serializeOptList(
+                                modelObject.paymentMethods,
+                                PaymentMethod.SERIALIZER,
+                            ),
+                        )
+                    }
+                } catch (e: JSONException) {
+                    throw ModelSerializationException(PaymentMethodsApiResponse::class.java, e)
+                }
+            }
+
+            override fun deserialize(jsonObject: JSONObject): PaymentMethodsApiResponse {
+                return PaymentMethodsApiResponse(
+//                    storedPaymentMethods = deserializeOptList(
+//                        jsonObject.optJSONArray(STORED_PAYMENT_METHODS),
+//                        StoredPaymentMethod.SERIALIZER
+//                    ),
+                    paymentMethods = deserializeOptList(
+                        jsonObject.optJSONArray(PAYMENT_METHODS),
+                        PaymentMethod.SERIALIZER,
+                    ),
+                )
+            }
+        }
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/exception/HttpException.kt b/core/src/main/java/com/adyen/checkout/core/exception/HttpException.kt
new file mode 100644
index 0000000000..5b1df3a0aa
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/exception/HttpException.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.exception
+
+import com.adyen.checkout.core.internal.data.model.ErrorResponseBody
+
+/**
+ * Indicates that an internal API call has failed.
+ */
+class HttpException(
+    val code: Int,
+    message: String,
+    val errorBody: ErrorResponseBody?,
+    // TODO - Errors
+// ) : CheckoutException(message)
+) : RuntimeException(message)
diff --git a/core/src/main/java/com/adyen/checkout/core/exception/ModelSerializationException.kt b/core/src/main/java/com/adyen/checkout/core/exception/ModelSerializationException.kt
new file mode 100644
index 0000000000..b8d4704eee
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/exception/ModelSerializationException.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.exception
+
+import com.adyen.checkout.core.internal.data.model.ModelObject
+import org.json.JSONException
+
+/**
+ * Exception thrown when an issue occurs during serialization of a [ModelObject].
+ */
+class ModelSerializationException(modelClass: Class<*>, cause: JSONException?) :
+// TODO - Error Propagation
+//    CheckoutException("Unexpected exception while serializing ${modelClass.simpleName}.", cause)
+    RuntimeException("Unexpected exception while serializing ${modelClass.simpleName}.", cause)
diff --git a/core/src/main/java/com/adyen/checkout/core/internal/data/api/AdyenApiResponse.kt b/core/src/main/java/com/adyen/checkout/core/internal/data/api/AdyenApiResponse.kt
new file mode 100644
index 0000000000..179602dba4
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/internal/data/api/AdyenApiResponse.kt
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.internal.data.api
+
+import androidx.annotation.RestrictTo
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+data class AdyenApiResponse(
+    val path: String,
+    val statusCode: Int,
+    val headers: Map<String, String>,
+    val body: String,
+)
diff --git a/core/src/main/java/com/adyen/checkout/core/internal/data/api/HttpClient.kt b/core/src/main/java/com/adyen/checkout/core/internal/data/api/HttpClient.kt
new file mode 100644
index 0000000000..a3dec3df68
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/internal/data/api/HttpClient.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.internal.data.api
+
+import androidx.annotation.RestrictTo
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+interface HttpClient {
+
+    suspend fun get(
+        path: String,
+        queryParameters: Map<String, String> = emptyMap(),
+        headers: Map<String, String> = emptyMap()
+    ): AdyenApiResponse
+
+    suspend fun post(
+        path: String,
+        jsonBody: String,
+        queryParameters: Map<String, String> = emptyMap(),
+        headers: Map<String, String> = emptyMap()
+    ): AdyenApiResponse
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/internal/data/api/HttpClientExt.kt b/core/src/main/java/com/adyen/checkout/core/internal/data/api/HttpClientExt.kt
new file mode 100644
index 0000000000..a814f89928
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/internal/data/api/HttpClientExt.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.internal.data.api
+
+import androidx.annotation.RestrictTo
+import com.adyen.checkout.core.exception.HttpException
+import com.adyen.checkout.core.internal.data.model.ModelObject
+import org.json.JSONObject
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+suspend fun <T : ModelObject, R : ModelObject> HttpClient.post(
+    path: String,
+    body: T,
+    requestSerializer: ModelObject.Serializer<T>,
+    responseSerializer: ModelObject.Serializer<R>,
+    queryParameters: Map<String, String> = emptyMap(),
+): R {
+    // TODO - AdyenLogger
+//    adyenLog(AdyenLogLevel.DEBUG) { "POST - $path" }
+
+    val requestJson = requestSerializer.serialize(body)
+
+//    adyenLog(AdyenLogLevel.VERBOSE) { "request - ${requestJson.toStringPretty()}" }
+
+    val response = runAndLogHttpException { post(path, requestJson.toString(), queryParameters) }
+
+//    logResponse(response)
+
+    return responseSerializer.deserialize(response.body.toJSONObject())
+}
+
+@Suppress("RethrowCaughtException")
+private inline fun <T : Any, R> T.runAndLogHttpException(block: T.() -> R): R {
+    return try {
+        block()
+    } catch (httpException: HttpException) {
+//        adyenLog(AdyenLogLevel.ERROR) { "API error - ${httpException.getLogMessage()}" }
+        throw httpException
+    }
+}
+
+private fun String.toJSONObject(): JSONObject {
+    return if (isEmpty()) {
+        JSONObject()
+    } else {
+        JSONObject(this)
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/internal/data/api/HttpClientFactory.kt b/core/src/main/java/com/adyen/checkout/core/internal/data/api/HttpClientFactory.kt
new file mode 100644
index 0000000000..c6b9a0ab39
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/internal/data/api/HttpClientFactory.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.internal.data.api
+
+import androidx.annotation.RestrictTo
+import com.adyen.checkout.core.Environment
+import okhttp3.OkHttpClient
+import com.adyen.checkout.core.internal.data.api.OkHttpClient as InternalOkHttpClient
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+object HttpClientFactory {
+
+    private val defaultHeaders = mapOf(
+        "Content-Type" to "application/json"
+    )
+
+    private val okHttpClient: OkHttpClient by lazy { OkHttpClient() }
+
+    fun getHttpClient(environment: Environment): HttpClient {
+        return InternalOkHttpClient(
+            okHttpClient,
+            environment.checkoutShopperBaseUrl.toString(),
+            defaultHeaders
+        )
+    }
+
+    fun getAnalyticsHttpClient(environment: Environment): HttpClient {
+        return InternalOkHttpClient(
+            okHttpClient,
+            environment.checkoutAnalyticsBaseUrl.toString(),
+            defaultHeaders
+        )
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/internal/data/api/OkHttpClient.kt b/core/src/main/java/com/adyen/checkout/core/internal/data/api/OkHttpClient.kt
new file mode 100644
index 0000000000..518ea4adc0
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/internal/data/api/OkHttpClient.kt
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.internal.data.api
+
+import com.adyen.checkout.core.exception.HttpException
+import com.adyen.checkout.core.exception.ModelSerializationException
+import com.adyen.checkout.core.internal.data.model.ErrorResponseBody
+import okhttp3.Headers.Companion.toHeaders
+import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
+import okhttp3.MediaType.Companion.toMediaType
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import okhttp3.RequestBody.Companion.toRequestBody
+import okhttp3.Response
+import org.json.JSONException
+import org.json.JSONObject
+import java.io.IOException
+import kotlin.coroutines.cancellation.CancellationException
+
+internal class OkHttpClient(
+    private val client: OkHttpClient,
+    private val baseUrl: String,
+    private val defaultHeaders: Map<String, String> = emptyMap()
+) : HttpClient {
+
+    override suspend fun get(
+        path: String,
+        queryParameters: Map<String, String>,
+        headers: Map<String, String>
+    ): AdyenApiResponse {
+        val request = Request.Builder()
+            .headers(headers.combineToHeaders())
+            .url(buildURL(path, queryParameters))
+            .get()
+            .build()
+
+        return executeRequest(request, path)
+    }
+
+    override suspend fun post(
+        path: String,
+        jsonBody: String,
+        queryParameters: Map<String, String>,
+        headers: Map<String, String>
+    ): AdyenApiResponse {
+        val request = Request.Builder()
+            .headers(headers.combineToHeaders())
+            .url(buildURL(path, queryParameters))
+            .post(jsonBody.toRequestBody(MEDIA_TYPE_JSON))
+            .build()
+
+        return executeRequest(request, path)
+    }
+
+    @Suppress("TooGenericExceptionThrown")
+    private fun buildURL(path: String, queryParameters: Map<String, String>): String {
+        val builder = (baseUrl + path).toHttpUrlOrNull()?.newBuilder()
+            ?: throw Exception("Failed to parse URL.")
+        // TODO - Errors
+//            ?: throw CheckoutException("Failed to parse URL.")
+
+        queryParameters.forEach { entry ->
+            builder.addQueryParameter(entry.key, entry.value)
+        }
+
+        return builder.toString()
+    }
+
+    private fun executeRequest(request: Request, path: String): AdyenApiResponse {
+        val call = client.newCall(request)
+
+        try {
+            val response = call.execute()
+
+            if (response.isSuccessful) {
+                val bytes = response.body
+                    ?.bytes()
+                    ?: ByteArray(0)
+                response.body?.close()
+                return AdyenApiResponse(
+                    path = path,
+                    statusCode = response.code,
+                    headers = response.headers.toMap(),
+                    body = String(bytes, Charsets.UTF_8),
+                )
+            } else {
+                val exception = response.getHttpException()
+                response.body?.close()
+                throw exception
+            }
+        } catch (e: CancellationException) {
+            call.cancel()
+            throw e
+        }
+    }
+
+    private fun Map<String, String>.combineToHeaders() =
+        (defaultHeaders + this).toHeaders()
+
+    @Suppress("SwallowedException")
+    private fun Response.getHttpException(): HttpException {
+        val stringBody = try {
+            body?.string()
+        } catch (e: IOException) {
+            null
+        }
+
+        val parsedErrorResponseBody = try {
+            stringBody
+                ?.let { JSONObject(it) }
+                ?.let { ErrorResponseBody.SERIALIZER.deserialize(it) }
+        } catch (e: JSONException) {
+            null
+        } catch (e: ModelSerializationException) {
+            null
+        }
+
+        return HttpException(
+            code = parsedErrorResponseBody?.status ?: code,
+            message = parsedErrorResponseBody?.message ?: stringBody?.takeIf { it.isNotBlank() } ?: message,
+            errorBody = parsedErrorResponseBody,
+        )
+    }
+
+    companion object {
+        private val MEDIA_TYPE_JSON = "application/json; charset=utf-8".toMediaType()
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/internal/data/model/ErrorResponseBody.kt b/core/src/main/java/com/adyen/checkout/core/internal/data/model/ErrorResponseBody.kt
new file mode 100644
index 0000000000..2d7ec8baa9
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/internal/data/model/ErrorResponseBody.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.internal.data.model
+
+import androidx.annotation.RestrictTo
+import com.adyen.checkout.core.exception.ModelSerializationException
+import kotlinx.parcelize.Parcelize
+import org.json.JSONException
+import org.json.JSONObject
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@Parcelize
+data class ErrorResponseBody(
+    val status: Int?,
+    val errorCode: String?,
+    val message: String?,
+    val errorType: String?,
+    val pspReference: String?,
+) : ModelObject() {
+
+    companion object {
+
+        private const val STATUS = "status"
+        private const val ERROR_CODE = "errorCode"
+        private const val MESSAGE = "message"
+        private const val ERROR_TYPE = "errorType"
+        private const val PSP_REFERENCE = "pspReference"
+
+        @JvmField
+        val SERIALIZER: Serializer<ErrorResponseBody> = object : Serializer<ErrorResponseBody> {
+            override fun serialize(modelObject: ErrorResponseBody): JSONObject {
+                val jsonObject = JSONObject()
+                try {
+                    jsonObject.putOpt(STATUS, modelObject.status)
+                    jsonObject.putOpt(ERROR_CODE, modelObject.errorCode)
+                    jsonObject.putOpt(MESSAGE, modelObject.message)
+                    jsonObject.putOpt(ERROR_TYPE, modelObject.errorType)
+                    jsonObject.putOpt(PSP_REFERENCE, modelObject.pspReference)
+                } catch (e: JSONException) {
+                    throw ModelSerializationException(ErrorResponseBody::class.java, e)
+                }
+                return jsonObject
+            }
+
+            override fun deserialize(jsonObject: JSONObject): ErrorResponseBody {
+                return try {
+                    ErrorResponseBody(
+                        status = jsonObject.getIntOrNull(STATUS),
+                        errorCode = jsonObject.getStringOrNull(ERROR_CODE),
+                        message = jsonObject.getStringOrNull(MESSAGE),
+                        errorType = jsonObject.getStringOrNull(ERROR_TYPE),
+                        pspReference = jsonObject.getStringOrNull(PSP_REFERENCE),
+                    )
+                } catch (e: JSONException) {
+                    throw ModelSerializationException(ErrorResponseBody::class.java, e)
+                }
+            }
+        }
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/internal/data/model/JsonUtils.kt b/core/src/main/java/com/adyen/checkout/core/internal/data/model/JsonUtils.kt
new file mode 100644
index 0000000000..900aeb5540
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/internal/data/model/JsonUtils.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.internal.data.model
+
+import androidx.annotation.RestrictTo
+import org.json.JSONObject
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+fun JSONObject.getStringOrNull(key: String): String? {
+    return if (!isNull(key)) getString(key) else null
+}
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+fun JSONObject.getBooleanOrNull(key: String): Boolean? {
+    return if (!isNull(key)) getBoolean(key) else null
+}
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+fun JSONObject.getIntOrNull(key: String): Int? {
+    return if (!isNull(key)) getInt(key) else null
+}
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+fun JSONObject.getLongOrNull(key: String): Long? {
+    return if (!isNull(key)) getLong(key) else null
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/internal/data/model/ModelObject.kt b/core/src/main/java/com/adyen/checkout/core/internal/data/model/ModelObject.kt
new file mode 100644
index 0000000000..012a8aa0ab
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/internal/data/model/ModelObject.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.internal.data.model
+
+import android.os.Parcelable
+import androidx.annotation.RestrictTo
+import org.json.JSONObject
+
+/**
+ * Base class for a Model object. A model object is a representation of a JSON response or input from the Checkout API.
+ * All model objects can be serialized and deserialized to and from a JSONObject using the [Serializer] interface.
+ * All model object also implement Parcelable to be sent as part of Extras in an Intent Bundle.
+ *
+ * The classes extending [ModelObject] are data classes designed to work standalone or in association with JSON
+ * libraries like GSON and Moshi.
+ */
+abstract class ModelObject
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+constructor() : Parcelable {
+
+    override fun describeContents(): Int {
+        return Parcelable.CONTENTS_FILE_DESCRIPTOR
+    }
+
+    /**
+     * Interface that must be implemented and provided as a public SERIALIZER field that serializes the to and from a
+     * JSONObject.
+     * @param <T> The class that extends ModelObject to be serialized.
+     */
+    interface Serializer<T : ModelObject> {
+        /**
+         * Serialize the [ModelObject] to a [JSONObject].
+         * @param modelObject The Model class to be serialized.
+         * @return The result JSONObject
+         */
+        fun serialize(modelObject: T): JSONObject
+
+        /**
+         * Deserialize a [JSONObject] to a [ModelObject].
+         * @param jsonObject The base object to deserialize.
+         * @return The ModelObject parsed with the contents from the JSONObject.
+         */
+        fun deserialize(jsonObject: JSONObject): T
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/internal/data/model/ModelUtils.kt b/core/src/main/java/com/adyen/checkout/core/internal/data/model/ModelUtils.kt
new file mode 100644
index 0000000000..1a9ad813b7
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/internal/data/model/ModelUtils.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.internal.data.model
+
+import org.json.JSONArray
+import org.json.JSONObject
+import java.util.Collections
+
+internal object ModelUtils {
+
+    /**
+     * Parse a [JSONObject] to a class that extends [ModelObject] using its [ModelObject.Serializer].
+     * Result can also be null if the object is null.
+     *
+     * @param jsonObject The object to be parsed.
+     * @param serializer The serializer of the ModelObject class to be used.
+     * @param <T> The type o the ModelObject class to be parse to.
+     * @return The parsed object from JSON, null if doesn't exist.
+     */
+    @JvmStatic
+    fun <T : ModelObject> deserializeOpt(jsonObject: JSONObject?, serializer: ModelObject.Serializer<T>): T? {
+        return if (jsonObject == null) null else serializer.deserialize(jsonObject)
+    }
+
+    /**
+     * Parse a [JSONArray] to a [List] of objects that extend [ModelObject].
+     * Result can also be null if the object is null.
+     *
+     * @param jsonArray The JSONArray to be parsed.
+     * @param serializer The serializer of the ModelObject class to be used.
+     * @param <T> The type o the ModelObject class to be parse to.
+     * @return The List of objects from the JSONArray.
+     */
+    @JvmStatic
+    fun <T : ModelObject> deserializeOptList(jsonArray: JSONArray?, serializer: ModelObject.Serializer<T>): List<T>? {
+        if (jsonArray == null) {
+            return null
+        }
+        val list: MutableList<T> = ArrayList()
+        for (i in 0 until jsonArray.length()) {
+            val itemJson = jsonArray.optJSONObject(i)
+            if (itemJson != null) {
+                val item = serializer.deserialize(itemJson)
+                list.add(item)
+            }
+        }
+        return Collections.unmodifiableList(list)
+    }
+
+    /**
+     * Serializes a class extending [ModelObject] into a JSONObject.
+     *
+     * @param modelObject The object to be serialized.
+     * @param serializer The serializer of the ModelObject class to be used.
+     * @param <T> The type o the ModelObject class to be serialized from.
+     * @return The JSONObject representing the ModelObject.
+     */
+    @JvmStatic
+    fun <T : ModelObject> serializeOpt(modelObject: T?, serializer: ModelObject.Serializer<T>): JSONObject? {
+        return if (modelObject == null) null else serializer.serialize(modelObject)
+    }
+
+    /**
+     * Serializes a [List] containing objects that extend [ModelObject] into a [JSONArray].
+     *
+     * @param modelList The list to be serialized.
+     * @param serializer The serializer of the ModelObject class to be used.
+     * @param <T> The type o the ModelObject class to be serialized from.
+     * @return The JSONArray representing the list of ModelObjects.
+     */
+    @JvmStatic
+    fun <T : ModelObject> serializeOptList(modelList: List<T>?, serializer: ModelObject.Serializer<T>): JSONArray? {
+        if (modelList == null || modelList.isEmpty()) {
+            return null
+        }
+        val jsonArray = JSONArray()
+        for (model in modelList) {
+            jsonArray.put(serializer.serialize(model))
+        }
+        return jsonArray
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/internal/util/ResultExt.kt b/core/src/main/java/com/adyen/checkout/core/internal/util/ResultExt.kt
new file mode 100644
index 0000000000..e75d9b7e87
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/internal/util/ResultExt.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.internal.util
+
+import androidx.annotation.RestrictTo
+import kotlinx.coroutines.CancellationException
+
+@Suppress("TooGenericExceptionCaught")
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+inline fun <T, R> T.runSuspendCatching(block: T.() -> R): Result<R> {
+    return try {
+        Result.success(block())
+    } catch (e: CancellationException) {
+        throw e
+    } catch (e: Throwable) {
+        Result.failure(e)
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/sessions/CheckoutSession.kt b/core/src/main/java/com/adyen/checkout/core/sessions/CheckoutSession.kt
new file mode 100644
index 0000000000..ef7ff17c47
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/sessions/CheckoutSession.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.sessions
+
+import com.adyen.checkout.core.Environment
+import com.adyen.checkout.core.data.model.PaymentMethod
+import com.adyen.checkout.core.sessions.data.SessionSetupResponse
+
+/**
+ * A class holding the data required to launch Drop-in or a component with the sessions flow.
+ * Use [CheckoutSessionProvider.createSession] to create this class.
+ */
+data class CheckoutSession(
+    val sessionSetupResponse: SessionSetupResponse,
+    // TODO - Partial Payment Flow Support
+//    val order: Order?,
+    val environment: Environment,
+    val clientKey: String,
+) {
+    fun getPaymentMethod(paymentMethodType: String): PaymentMethod? {
+        return sessionSetupResponse.paymentMethodsApiResponse?.paymentMethods.orEmpty()
+            .firstOrNull {
+                it.type == paymentMethodType
+            }
+    }
+
+    // TODO - Configuration
+//    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+//    fun getConfiguration(): CheckoutConfiguration {
+//        return CheckoutConfiguration(
+//            environment = environment,
+//            clientKey = clientKey,
+//        )
+//    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/sessions/CheckoutSessionInitializer.kt b/core/src/main/java/com/adyen/checkout/core/sessions/CheckoutSessionInitializer.kt
new file mode 100644
index 0000000000..419004c6d9
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/sessions/CheckoutSessionInitializer.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.sessions
+
+import com.adyen.checkout.core.DispatcherProvider
+import com.adyen.checkout.core.Environment
+import com.adyen.checkout.core.data.model.Amount
+import com.adyen.checkout.core.internal.data.api.HttpClientFactory
+import com.adyen.checkout.core.sessions.data.api.SessionRepository
+import com.adyen.checkout.core.sessions.data.api.SessionService
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.withContext
+
+internal class CheckoutSessionInitializer(
+    private val sessionModel: SessionModel,
+    private val environment: Environment,
+    private val clientKey: String,
+    // TODO - Partial Payment Flow
+//    private val order: Order?,
+    private val coroutineDispatcher: CoroutineDispatcher = DispatcherProvider.IO,
+) {
+
+    private val httpClient = HttpClientFactory.getHttpClient(environment)
+    private val sessionService = SessionService(httpClient)
+    private val sessionRepository = SessionRepository(sessionService, clientKey)
+
+    // TODO Once Backend provides the correct amount in the SessionSetupResponse use that in SessionDetails instead of
+    //  override Amount
+    suspend fun setupSession(overrideAmount: Amount?): CheckoutSessionResult = withContext(coroutineDispatcher) {
+        sessionRepository.setupSession(
+            sessionModel = sessionModel,
+//            order = order,
+        ).fold(
+            onSuccess = { sessionSetupResponse ->
+                return@withContext CheckoutSessionResult.Success(
+                    CheckoutSession(
+                        sessionSetupResponse.copy(amount = overrideAmount ?: sessionSetupResponse.amount),
+//                        order,
+                        environment,
+                        clientKey,
+                    ),
+                )
+            },
+            onFailure = {
+                // TODO - Error propagation
+//                return@withContext CheckoutSessionResult.Error(CheckoutException("Failed to fetch session", it))
+                return@withContext CheckoutSessionResult.Error(Exception("Failed to fetch session", it))
+            },
+        )
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/sessions/CheckoutSessionProvider.kt b/core/src/main/java/com/adyen/checkout/core/sessions/CheckoutSessionProvider.kt
new file mode 100644
index 0000000000..b37e711532
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/sessions/CheckoutSessionProvider.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.sessions
+
+import com.adyen.checkout.core.Environment
+
+internal object CheckoutSessionProvider {
+
+    /**
+     * Allows creating a [CheckoutSession] from the response of the /sessions endpoint.
+     * This is a suspend function that executes a network call on the IO thread.
+     *
+     * @param sessionModel The deserialized JSON response of the /sessions API call. You can use
+     * [SessionModel.SERIALIZER] to deserialize this JSON.
+     * @param environment The [Environment] to be used for internal network calls from the SDK to Adyen.
+     * @param clientKey Your Client Key used for internal network calls from the SDK to Adyen.
+     * @param order An [Order] in case of an ongoing partial payment flow.
+     *
+     * @return The result of the API call.
+     */
+    @Suppress("CommentWrapping")
+    suspend fun createSession(
+        sessionModel: SessionModel,
+        environment: Environment,
+        clientKey: String,
+        // TODO - Partial Payment Flow
+//        order: Order? = null,
+    ): CheckoutSessionResult {
+        return CheckoutSessionInitializer(sessionModel, environment, clientKey).setupSession(null)
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/sessions/CheckoutSessionResult.kt b/core/src/main/java/com/adyen/checkout/core/sessions/CheckoutSessionResult.kt
new file mode 100644
index 0000000000..0a9292e51f
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/sessions/CheckoutSessionResult.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.sessions
+
+/**
+ * The result of the API call to fetch a [CheckoutSession].
+ */
+sealed class CheckoutSessionResult {
+    class Success(val checkoutSession: CheckoutSession) : CheckoutSessionResult()
+
+    // TODO - Revisit while error propagation improvements
+//    class Error(val exception: CheckoutException) : CheckoutSessionResult()
+    class Error(val exception: Exception) : CheckoutSessionResult()
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/sessions/SessionModel.kt b/core/src/main/java/com/adyen/checkout/core/sessions/SessionModel.kt
new file mode 100644
index 0000000000..2da975573f
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/sessions/SessionModel.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.sessions
+
+import com.adyen.checkout.core.exception.ModelSerializationException
+import com.adyen.checkout.core.internal.data.model.ModelObject
+import com.adyen.checkout.core.internal.data.model.getStringOrNull
+import kotlinx.parcelize.Parcelize
+import org.json.JSONException
+import org.json.JSONObject
+
+/**
+ * Object that parses and holds the response data from the /sessions endpoint.
+ * Use [PaymentMethodsApiResponse.SERIALIZER] to deserialize this class from your JSON response.
+ */
+@Parcelize
+data class SessionModel(
+    val id: String,
+    val sessionData: String?
+) : ModelObject() {
+
+    companion object {
+        private const val ID = "id"
+        private const val SESSION_DATA = "sessionData"
+
+        @JvmField
+        val SERIALIZER: Serializer<SessionModel> = object : Serializer<SessionModel> {
+            override fun serialize(modelObject: SessionModel): JSONObject {
+                return JSONObject().apply {
+                    try {
+                        putOpt(ID, modelObject.id)
+                        putOpt(SESSION_DATA, modelObject.sessionData)
+                    } catch (e: JSONException) {
+                        throw ModelSerializationException(SessionModel::class.java, e)
+                    }
+                }
+            }
+
+            override fun deserialize(jsonObject: JSONObject): SessionModel {
+                return SessionModel(
+                    id = jsonObject.getStringOrNull(ID).orEmpty(),
+                    sessionData = jsonObject.getStringOrNull(SESSION_DATA)
+                )
+            }
+        }
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/sessions/data/SessionSetupConfiguration.kt b/core/src/main/java/com/adyen/checkout/core/sessions/data/SessionSetupConfiguration.kt
new file mode 100644
index 0000000000..0818699276
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/sessions/data/SessionSetupConfiguration.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.sessions.data
+
+import com.adyen.checkout.core.exception.ModelSerializationException
+import com.adyen.checkout.core.internal.data.model.ModelObject
+import com.adyen.checkout.core.internal.data.model.getBooleanOrNull
+import kotlinx.parcelize.Parcelize
+import org.json.JSONException
+import org.json.JSONObject
+
+@Parcelize
+data class SessionSetupConfiguration(
+    val enableStoreDetails: Boolean? = null,
+    val showInstallmentAmount: Boolean = false,
+    // TODO - Installments
+//    val installmentOptions: Map<String, SessionSetupInstallmentOptions?>? = null,
+    val showRemovePaymentMethodButton: Boolean? = null,
+) : ModelObject() {
+
+    companion object {
+        private const val ENABLE_STORE_DETAILS = "enableStoreDetails"
+        private const val SHOW_INSTALLMENT_AMOUNT = "showInstallmentAmount"
+
+        // TODO - Installments
+//        private const val INSTALLMENT_OPTIONS = "installmentOptions"
+
+        private const val SHOW_REMOVE_PAYMENT_METHOD_BUTTON = "showRemovePaymentMethodButton"
+
+        @JvmField
+        val SERIALIZER: Serializer<SessionSetupConfiguration> = object : Serializer<SessionSetupConfiguration> {
+            override fun serialize(modelObject: SessionSetupConfiguration): JSONObject {
+                return try {
+                    JSONObject().apply {
+                        putOpt(ENABLE_STORE_DETAILS, modelObject.enableStoreDetails)
+                        putOpt(SHOW_INSTALLMENT_AMOUNT, modelObject.showInstallmentAmount)
+//                        putOpt(
+//                            INSTALLMENT_OPTIONS,
+//                            modelObject.installmentOptions?.let { JSONObject(it) },
+//                        )
+                        putOpt(SHOW_REMOVE_PAYMENT_METHOD_BUTTON, modelObject.showRemovePaymentMethodButton)
+                    }
+                } catch (e: JSONException) {
+                    throw ModelSerializationException(SessionSetupConfiguration::class.java, e)
+                }
+            }
+
+            override fun deserialize(jsonObject: JSONObject): SessionSetupConfiguration {
+                return try {
+                    SessionSetupConfiguration(
+                        enableStoreDetails = jsonObject.getBooleanOrNull(ENABLE_STORE_DETAILS),
+                        showInstallmentAmount = jsonObject.getBooleanOrNull(SHOW_INSTALLMENT_AMOUNT) ?: false,
+//                        installmentOptions = jsonObject.optJSONObject(INSTALLMENT_OPTIONS)
+//                            ?.jsonToMap(SessionSetupInstallmentOptions.SERIALIZER),
+                        showRemovePaymentMethodButton = jsonObject.getBooleanOrNull(SHOW_REMOVE_PAYMENT_METHOD_BUTTON),
+                    )
+                } catch (e: JSONException) {
+                    throw ModelSerializationException(SessionSetupConfiguration::class.java, e)
+                }
+            }
+        }
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/sessions/data/SessionSetupRequest.kt b/core/src/main/java/com/adyen/checkout/core/sessions/data/SessionSetupRequest.kt
new file mode 100644
index 0000000000..8e894a7903
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/sessions/data/SessionSetupRequest.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.sessions.data
+
+import com.adyen.checkout.core.exception.ModelSerializationException
+import com.adyen.checkout.core.internal.data.model.ModelObject
+import com.adyen.checkout.core.internal.data.model.getStringOrNull
+import kotlinx.parcelize.Parcelize
+import org.json.JSONException
+import org.json.JSONObject
+
+@Parcelize
+data class SessionSetupRequest(
+    val sessionData: String,
+    // TODO - Partial Payment Flow
+//    val order: OrderRequest?
+) : ModelObject() {
+
+    companion object {
+        private const val SESSION_DATA = "sessionData"
+//        private const val ORDER = "order"
+
+        @JvmField
+        val SERIALIZER: Serializer<SessionSetupRequest> = object : Serializer<SessionSetupRequest> {
+            override fun serialize(modelObject: SessionSetupRequest): JSONObject {
+                val jsonObject = JSONObject()
+                try {
+                    jsonObject.putOpt(SESSION_DATA, modelObject.sessionData)
+//                    jsonObject.putOpt(ORDER, ModelUtils.serializeOpt(modelObject.order, OrderRequest.SERIALIZER))
+                } catch (e: JSONException) {
+                    throw ModelSerializationException(SessionSetupRequest::class.java, e)
+                }
+                return jsonObject
+            }
+
+            override fun deserialize(jsonObject: JSONObject): SessionSetupRequest {
+                return try {
+                    SessionSetupRequest(
+                        sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(),
+//                        order = ModelUtils.deserializeOpt(jsonObject.optJSONObject(ORDER), OrderRequest.SERIALIZER)
+                    )
+                } catch (e: JSONException) {
+                    throw ModelSerializationException(SessionSetupRequest::class.java, e)
+                }
+            }
+        }
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/sessions/data/SessionSetupResponse.kt b/core/src/main/java/com/adyen/checkout/core/sessions/data/SessionSetupResponse.kt
new file mode 100644
index 0000000000..189ca729ee
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/sessions/data/SessionSetupResponse.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.sessions.data
+
+import com.adyen.checkout.core.data.model.Amount
+import com.adyen.checkout.core.data.model.PaymentMethodsApiResponse
+import com.adyen.checkout.core.exception.ModelSerializationException
+import com.adyen.checkout.core.internal.data.model.ModelObject
+import com.adyen.checkout.core.internal.data.model.ModelUtils
+import com.adyen.checkout.core.internal.data.model.getStringOrNull
+import kotlinx.parcelize.Parcelize
+import org.json.JSONException
+import org.json.JSONObject
+
+@Parcelize
+data class SessionSetupResponse(
+    val id: String,
+    val sessionData: String,
+    val amount: Amount?,
+    val expiresAt: String,
+    val paymentMethodsApiResponse: PaymentMethodsApiResponse?,
+    val returnUrl: String?,
+    val configuration: SessionSetupConfiguration?,
+    val shopperLocale: String?,
+) : ModelObject() {
+
+    companion object {
+        private const val ID = "id"
+        private const val SESSION_DATA = "sessionData"
+        private const val AMOUNT = "amount"
+        private const val EXPIRES_AT = "expiresAt"
+        private const val PAYMENT_METHODS = "paymentMethods"
+        private const val RETURN_URL = "returnUrl"
+        private const val CONFIGURATION = "configuration"
+        private const val SHOPPER_LOCALE = "shopperLocale"
+
+        @JvmField
+        val SERIALIZER: Serializer<SessionSetupResponse> = object : Serializer<SessionSetupResponse> {
+            override fun serialize(modelObject: SessionSetupResponse): JSONObject {
+                val jsonObject = JSONObject()
+                try {
+                    jsonObject.putOpt(ID, modelObject.id)
+                    jsonObject.putOpt(SESSION_DATA, modelObject.sessionData)
+                    jsonObject.putOpt(AMOUNT, ModelUtils.serializeOpt(modelObject.amount, Amount.SERIALIZER))
+                    jsonObject.putOpt(EXPIRES_AT, modelObject.expiresAt)
+                    jsonObject.putOpt(
+                        PAYMENT_METHODS,
+                        ModelUtils.serializeOpt(
+                            modelObject.paymentMethodsApiResponse,
+                            PaymentMethodsApiResponse.SERIALIZER
+                        )
+                    )
+                    jsonObject.putOpt(RETURN_URL, modelObject.returnUrl)
+                    jsonObject.putOpt(
+                        CONFIGURATION,
+                        ModelUtils.serializeOpt(modelObject.configuration, SessionSetupConfiguration.SERIALIZER)
+                    )
+                    jsonObject.putOpt(SHOPPER_LOCALE, modelObject.shopperLocale)
+                } catch (e: JSONException) {
+                    throw ModelSerializationException(SessionSetupResponse::class.java, e)
+                }
+                return jsonObject
+            }
+
+            override fun deserialize(jsonObject: JSONObject): SessionSetupResponse {
+                return try {
+                    SessionSetupResponse(
+                        id = jsonObject.getStringOrNull(ID).orEmpty(),
+                        sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(),
+                        amount = ModelUtils.deserializeOpt(jsonObject.optJSONObject(AMOUNT), Amount.SERIALIZER),
+                        expiresAt = jsonObject.getStringOrNull(EXPIRES_AT).orEmpty(),
+                        paymentMethodsApiResponse = ModelUtils.deserializeOpt(
+                            jsonObject.optJSONObject(PAYMENT_METHODS),
+                            PaymentMethodsApiResponse.SERIALIZER
+                        ),
+                        returnUrl = jsonObject.getStringOrNull(RETURN_URL),
+                        configuration = ModelUtils.deserializeOpt(
+                            jsonObject.optJSONObject(CONFIGURATION),
+                            SessionSetupConfiguration.SERIALIZER
+                        ),
+                        shopperLocale = jsonObject.getStringOrNull(SHOPPER_LOCALE),
+                    )
+                } catch (e: JSONException) {
+                    throw ModelSerializationException(SessionSetupResponse::class.java, e)
+                }
+            }
+        }
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/sessions/data/api/SessionRepository.kt b/core/src/main/java/com/adyen/checkout/core/sessions/data/api/SessionRepository.kt
new file mode 100644
index 0000000000..45bbb9cde2
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/sessions/data/api/SessionRepository.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.sessions.data.api
+
+import androidx.annotation.RestrictTo
+import com.adyen.checkout.core.internal.util.runSuspendCatching
+import com.adyen.checkout.core.sessions.SessionModel
+import com.adyen.checkout.core.sessions.data.SessionSetupRequest
+import com.adyen.checkout.core.sessions.data.SessionSetupResponse
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+class SessionRepository(
+    private val sessionService: SessionService,
+    private val clientKey: String,
+) {
+
+    @Suppress("CommentWrapping")
+    suspend fun setupSession(
+        sessionModel: SessionModel,
+        // TODO - Partial Payment Flow
+//        order: OrderRequest?
+    ): Result<SessionSetupResponse> = runSuspendCatching {
+        val request = SessionSetupRequest(sessionModel.sessionData.orEmpty())
+        sessionService.setupSession(
+            request = request,
+            sessionId = sessionModel.id,
+            clientKey = clientKey,
+        )
+    }
+}
diff --git a/core/src/main/java/com/adyen/checkout/core/sessions/data/api/SessionService.kt b/core/src/main/java/com/adyen/checkout/core/sessions/data/api/SessionService.kt
new file mode 100644
index 0000000000..e2d9128a40
--- /dev/null
+++ b/core/src/main/java/com/adyen/checkout/core/sessions/data/api/SessionService.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.sessions.data.api
+
+import androidx.annotation.RestrictTo
+import com.adyen.checkout.core.DispatcherProvider
+import com.adyen.checkout.core.internal.data.api.HttpClient
+import com.adyen.checkout.core.internal.data.api.post
+import com.adyen.checkout.core.sessions.data.SessionSetupRequest
+import com.adyen.checkout.core.sessions.data.SessionSetupResponse
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.withContext
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+class SessionService(
+    private val httpClient: HttpClient,
+    private val coroutineDispatcher: CoroutineDispatcher = DispatcherProvider.IO,
+) {
+    suspend fun setupSession(
+        request: SessionSetupRequest,
+        sessionId: String,
+        clientKey: String,
+    ): SessionSetupResponse = withContext(coroutineDispatcher) {
+        httpClient.post(
+            path = "v1/sessions/$sessionId/setup",
+            queryParameters = mapOf("clientKey" to clientKey),
+            body = request,
+            requestSerializer = SessionSetupRequest.SERIALIZER,
+            responseSerializer = SessionSetupResponse.SERIALIZER,
+        )
+    }
+}


Reviews:
user: login: OscarSpruit
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T11:23:51Z
user: login: araratthehero
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-26T13:36:43Z
user: login: araratthehero
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-26T13:47:26Z

Review comments:
diff_hunk: @@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.exception
+
+import com.adyen.checkout.core.internal.data.model.ModelObject
+import org.json.JSONException
+
+/**
+ * Exception thrown when an issue occurs during serialization of a [ModelObject].
+ */
+class ModelSerializationException(modelClass: Class<*>, cause: JSONException?) :
+//    CheckoutException("Unexpected exception while serializing ${modelClass.simpleName}.", cause)
+    Exception("Unexpected exception while serializing ${modelClass.simpleName}.", cause)
path: core/src/main/java/com/adyen/checkout/core/exception/ModelSerializationException.kt
user: login: OscarSpruit
body: This should be a `RuntimeException` I think
created_at: 2025-05-06T11:17:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.internal.data.model
+
+import org.json.JSONArray
+import org.json.JSONObject
+import java.util.Collections
+
+object ModelUtils {
path: core/src/main/java/com/adyen/checkout/core/internal/data/model/ModelUtils.kt
user: login: OscarSpruit
body: This can be `internal`
created_at: 2025-05-06T11:19:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.model
+
+import com.adyen.checkout.core.exception.ModelSerializationException
+import com.adyen.checkout.core.internal.data.model.ModelObject
+import com.adyen.checkout.core.internal.data.model.getLongOrNull
+import com.adyen.checkout.core.internal.data.model.getStringOrNull
+import kotlinx.parcelize.Parcelize
+import org.json.JSONException
+import org.json.JSONObject
+
+@Parcelize
+data class Amount(
+    var currency: String? = null,
path: core/src/main/java/com/adyen/checkout/core/model/Amount.kt
user: login: OscarSpruit
body: It would be a good time to convert all these mutable objects to immutable objects with `val`. WDYT?
created_at: 2025-05-06T11:21:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.exception
+
+import com.adyen.checkout.core.internal.data.model.ErrorResponseBody
+
+/**
+ * Indicates that an internal API call has failed.
+ */
+class HttpException(
+    val code: Int,
+    message: String,
+    val errorBody: ErrorResponseBody?,
+    // TODO - Errors
+// ) : CheckoutException(message)
+) : Exception(message)
path: core/src/main/java/com/adyen/checkout/core/exception/HttpException.kt
user: login: araratthehero
body: This should also be `RuntimeException` I guess?
created_at: 2025-05-26T13:28:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2025 Adyen N.V.
+ *
+ * This file is open source and available under the MIT license. See the LICENSE file for more info.
+ *
+ * Created by ozgur on 30/4/2025.
+ */
+
+package com.adyen.checkout.core.exception
+
+import com.adyen.checkout.core.internal.data.model.ModelObject
+import org.json.JSONException
+
+/**
+ * Exception thrown when an issue occurs during serialization of a [ModelObject].
+ */
+class ModelSerializationException(modelClass: Class<*>, cause: JSONException?) :
+//    CheckoutException("Unexpected exception while serializing ${modelClass.simpleName}.", cause)
path: core/src/main/java/com/adyen/checkout/core/exception/ModelSerializationException.kt
user: login: araratthehero
body: Could you add a todo here too, like `// TODO - Error propagation`?
created_at: 2025-05-26T13:35:19Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-26T13:53:05Z
body: # ✅ No public API changes

<!-- thollander/actions-comment-pull-request "api_changes" -->
author_association: CONTRIBUTOR
user: login: sonarqubecloud[bot]
created_at: 2025-05-26T13:59:20Z
body: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=Adyen_adyen-android&pullRequest=2110) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=Adyen_adyen-android&pullRequest=2110&metric=new_coverage&view=list) (required ≥ 80%)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [30.8% Duplication on New Code](https://sonarcloud.io/component_measures?id=Adyen_adyen-android&pullRequest=2110&metric=new_duplicated_lines_density&view=list) (required ≤ 3%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=Adyen_adyen-android&pullRequest=2110)


author_association: NONE