Skip to main content

Mobile SDK

https://img.shields.io/maven-central/v/com.aptopayments.sdk/mobile.svg?style=flat

caution

All card programs using APTO's SDKs or Mobile API are required to implement Signed Payloads. This is a mandatory update that must be completed to avoid program suspension. Please follow the Signed Payloads guide for more information, or contact programsupport@aptopayments.com with any questions.

Welcome to the Apto Android Mobile SDK. This SDK provides access to Apto's Mobile API, and is designed to be used for mobile apps. When using this SDK, there is no need for a separate API integration. All the API endpoints are exposed as simple-to-use SDK methods, and the data returned by the API is already encapsulated in the SDK and is easily accessible.

Note: This SDK can be used in conjunction with our UI SDK. However, if you would like to control your UI/UX, we recommend using the standalone Mobile SDK and implementing your own UI/UX.

With this SDK, you can:

Note: The Apto Mobile API has a request rate limit of 1 request per 30 seconds for the verification and login endpoints.

This document provides an overview of how to:

Note: To enable your cardholders to view PCI Data, you will also need to use our PCI SDK.

You can access the Android Mobile SDK on GitHub.

To contribute to the SDK development, see Contributions & Development

Requirements

  • Android SDK, minimum API Level 23 (Marshmallow)
  • Kotlin, minimum version 1.5.21
  • Gradle, minimum version 7.0.3

Note: The SDK is built using Kotlin, but is fully interoperable with Java. Code adjustments may be needed, if used within a Java project.

The following Android permissions are included with the Mobile SDK:

  • <uses-permission android:name="android.permission.INTERNET" />
  • <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Get the Mobile API key

A Mobile API Key is required to run the SDK. To retrieve your Mobile API Key see Get the Mobile API Key for the SDKs.

Install the SDK

  1. In your project's build.gradle file, add the Apto repository:
    allprojects {
repositories {

...

mavenCentral()
maven { url "https://jitpack.io" }

...
}
}
  1. In your app's build.gradle, add the following compile options:
android {

...

compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}

...

}

Note: This is required if your minimum Android SDK version is below Level 26 (Oreo).

  1. In your app's build.gradle, also add the following dependency:
    dependencies {
...

implementation 'com.aptopayments.sdk:mobile:3.17.0'

...
}

Note: The other files in the repo are not required for installation or initialization. Those files are available so you can:

  • See the SDK code.
  • Modify and recompile the code, to create a custom SDK experience.

Initialize the SDK

The SDK must be initialized using the onCreate method of your Application class, and requires your MOBILE_API_KEY:

  • One-step initialization: Load your MOBILE_API_KEY in the onCreate method of your Application class.
  • Two-step initialization: Initialize the SDK, and set up the MOBILE_API_KEY prior to interacting with the SDK methods.

One-step Initialization

In the onCreate method of your Application class, invoke initializeWithApiKey and pass in the MOBILE_API_KEY from the Apto Developer Portal. This fully initializes the SDK for your application.

class YourApp: Application() {
override fun onCreate() {
super.create()
AptoPlatform.initializeWithApiKey(this, "MOBILE_API_KEY")
...
}
...
}

The default deployment environment is the production environment (AptoSdkEnvironment.PRD). If you are deploying using the sandbox environment, you must set the optional environment parameter to AptoSdkEnvironment.SBX:

AptoPlatform.initializeWithApiKey(application, "MOBILE_API_KEY", AptoSdkEnvironment.SBX)

Two-step Initialization

If you want to defer setting your MOBILE_API_KEY, use the two-step initialization process:

  1. In the onCreate method of your Application class, invoke AptoPlatform.initialize initialize the SDK for your application.
class YourApp: Application() {
override fun onCreate() {
AptoPlatform.initialize(this)
...
}
...
}
  1. Prior to your app's first interaction with the SDK, ensure you set your MOBILE_API_KEY. This fully initializes the SDK for your application.

    The default deployment environment is the production environment (AptoSdkEnvironment.PRD). If you are deploying using the sandbox environment, you must set the optional environment parameter to AptoSdkEnvironment.SBX:

AptoPlatform.setApiKey("MOBILE_API_KEY", AptoSdkEnvironment.SBX)

Signed Payloads

Once you have finished setting up your server, as outlined in the Signed Payloads guide, you will need to create an AptoPlatformWebTokenProvider that fetches the JWT token from that server.

object MyWebTokenProvider() : AptoPlatformWebTokenProvider {
override fun getToken(payload: String, callback: (Either<WebTokenFailure, String>) -> Unit) {
// This is an example that uses okhttp to fetch the JWT from your server
val request = Request.Builder()
.url("http://localhost/sign")
.post(payload)
.build()

client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
// let SDK know an error happened
callback(Either.Left(WebTokenFailure))
}

override fun onResponse(call: Call, response: Response) {
response.use {
if (!response.isSuccessful) {
// let SDK know an error happened
callback(Either.Left(WebTokenFailure))
} else {
// send the JWT back to the SDK
callback(Either.Right(response.body!!.token))
}
}
}
})
}
}

You will then need to set the WebTokenProvider at the same time you initialize the SDK. This class will be called anytime a signed payload is needed.

AptoPlatform.webTokenProvider = MyWebTokenProvider()

SDK Method Callbacks

The Android Mobile SDK includes an Either object class. Most of the SDK methods will return an Either object in a callback.

The Either type is used to represent a correct or error value. By convention:

  • The Left constructor or L is used to represent error values.
  • The Right constructor or R is used to represent correct values.

Note: To help you remember, you can use the mnemonic "right" which also means "correct".

For more information about the Either object see the Either object class.

Verify a User Credential to Obtain a User Token

The SDK enables users to sign up or sign in to the Apto Mobile API.

A user's credentials must be verified prior to authenticating a user. A successful verification will return a user token, which is used during the authentication process. Depending on your project's configuration, the user's credentials can be:

  • Primary credential: The user's phone number or email address. Green Program is the default program, which uses a phone number as the primary credential. Only Blue or Orange Programs can use an email address as the primary credential, and this must be configured by Apto Payments. Please contact us if you would like to use a different primary credential.
info

The primary credential must be capable of receiving a secret One-Time Passcode (OTP) code which is used to verify the user's Primary credential. For example, the phone number must be able to receive an SMS message, and the email address must be able to receive an email sent by Apto Payments.

  • Secondary credential: The default is the user's date of birth.

There are three main methods for the User Verification Process:

info

When testing your program in Sandbox, you'll only be able to create users with U.S. phone numbers. If you're a customer of one of our Blue or Orange Programs and would like to use non-U.S. phone numbers to test cardholder operations, contact us at support@aptopayments.com

User Verification Process

  1. Start verification for the user's primary credential. See Start a New Verification for more information.

  2. Complete verification for the user's primary credential. See Complete a Verification for more information.

  3. Determine if the user is a new or existing user. Once the user's primary credential is verified, the API response will contain data indicating if the credential belongs to an existing user or a new user.

    If the credentials belong to an existing user:

    1. Verify the user's secondary credential. See Complete a Verification for more information.
    2. Use the SDK's login method to obtain a user session token. The login method consumes the two previous verifications, and the SDK automatically stores and manages the user token. See Login with an Existing User for more information.

    If the credentials don't belong to an existing user:

    • Create a new user with the verified credentials and obtain a user token. The SDK automatically stores and manages the user token.

Start a New Verification

Depending on your project's configuration for your users, use one of the following SDK methods to start a new verification. Green Programs can only use the phone verification.

Phone Verification

The phone number used for a phone verification must be capable of receiving an SMS.

To initialize a user verification with a phone number:

  1. Initialize a PhoneNumber object, passing in the user's country code and phone number as strings:

    Note:

    • The country code for the United States is 1.
    • The PHONE_NUMBER value should only contain numerical values.
var phoneNumber = PhoneNumber("COUNTRY_CODE", "PHONE_NUMBER")
  1. Pass the PhoneNumber object into the startPhoneVerification method to start the phone verification:
AptoPlatform.startPhoneVerification(phoneNumber) {
it.either({ error ->
// Do something with the error
}) { verification ->
// The verification started and the user received an SMS with a single use code (OTP).
}
}
  • When the method succeeds, a Verification object is included in the callback:
  • When the method fails, error handling can be included within the error response. Errors can include an incorrect OTP code submission or connection problems to the API.

Email Verification

Email verification is only available for Blue or Orange Programs. To set the primary credential to use the user's email address, please contact us.

To initialize a user verification with an email address, use the startEmailVerification method and pass in the user's email as a string:

AptoPlatform.startEmailVerification(email) {
it.either({ error ->
// Do something with the error
},
{ verification ->
// The verification started and the user received an email with a single use code (OTP).
this.verification = verification
})
}
  • When the method succeeds, a Verification object is included in the callback:
  • When the method fails, error handling can be included within the error response. Errors can include an incorrect OTP code submission or connection problems to the API.

Complete a Verification

To complete a verification, the user will need to enter their OTP code or date of birth, depending on the type of verification.

Note: If this is the completion of a secondary verification, ensure you use the primary verification's secondaryCredential value as the verification object for this method.

  1. Set the secret property on the Verification object:

    Note: For verifying phone numbers and email addresses, when testing in the sandbox environment, you must use 000000 as the OTP code.

    • If verifying a phone number, replace OTP_CODE_OR_BIRTHDATE with the OTP code received via SMS from the Start a New Verification process. Note: Use only numerical values.
    • If verifying an email address, replace OTP_CODE_OR_BIRTHDATE with the OTP code received via email from the Start a New Verification process. Note: Use only numerical values.
    • If verifying a date of birth, replace OTP_CODE_OR_BIRTHDATE with the user's date of birth, using the format YYYY-MM-DD. For example, 1999-01-01.
verification.secret = "OTP_CODE_OR_BIRTHDATE"
  1. Complete the verification by passing the Verification object into the completeVerification method.
AptoPlatform.completeVerification(verification) {
it.either(
{ error ->
// Do something with the error
},
{ verification ->

if (verification.status == VerificationStatus.PASSED) {
// The verification succeeded. If it belongs to an existing user, it will contain a non null `secondaryCredential`.
} else {
// The verification failed: the secret is invalid.
}
})
}
}
  • When the method succeeds, a Verification object is included in the callback:
    • If the verification's status property is set to VerificationStatus.PASSED, the verification is successful.
      • For primary verifications, if the verification belongs to an existing user, the response will contain a non-null secondaryCredential value. Use the secondaryCredential.secret value to complete verification for the user's secondary credential.
      • For secondary verifications, the user is now fully verified and login can proceed.
    • Otherwise, the verification failed due to an invalid secret value. If this is primary verification, you can add error handling and restart the primary verification for the user to re-enter their OTP code.
  • When the method fails, error handling can be included within the error response.

Restart a Primary Verification

If you previously initialized a phone or email verification, you can restart a verification by passing in the primary verification object into the restartVerification method:

AptoPlatform.restartVerification(primaryVerification) {
it.either({ error ->
// Do something with the error
}, { verification ->
// The verification started and the user received a new OTP code via email or phone.
})
}

  • When the method succeeds, a Verification object is included in the callback:
    • The user will receive a single use code (OTP) via SMS or email (depending on the type of verification). Use that code and the returned Verification object to complete verification for the user's primary credential.
    • (Optional) Add verification handling within the success callback.
  • When the method fails, error handling can be included within the error response.

Authenticate a User

A user session token is required for authentication. A session token is generated once you successfully sign up a new user or log a user into the SDK. The session token is valid until:

  • The user is logged out of the SDK.

  • A timeout occurs. IE The user doesn't interact with the app for one year in production mode or one month in sandbox mode.

    Note: The session length may be configured to a custom duration. Please contact us if you'd like to customize the session length.

For Green Programs, the session token is created by the SDK after verifying the user.

Blue or Orange Programs, have access to our Core API which enables you to leverage an existing session token for a user. Use the setUserToken method and replace USER_TOKEN with your existing user token. This enables the user to bypass the requirement to enter an OTP code they receive via SMS or email.

Note: Ensure your user token is passed in as a string.

AptoPlatform.setUserToken("USER_TOKEN")

Note: This is optional. If a session token is not provided, the SDK will obtain one by verifying the user.

Manage Users

The SDK enables you to:

Create a New User

A user's primary credential must be verified prior to creating a new user. Once the primary credential verification is complete, if a user already exists, a new user can not be created. See the User Verification Process for more info.

Once a user's primary credential is verified and a new user can be created, use the createUser method to create a new user.

  1. Create a primary credential object and set its verification property.

    This example, creates a PhoneNumber object for project configurations that use a phone number as the primary credential.

val primaryCredential = PhoneNumber(countryCode, phoneNumber)
primaryCredential.verification = verification // The verification obtained before.
  1. Create a DataPointList object and add the following information:

    • Verified primary credential object
    • Phone Number Note: The PhoneNumber object requires a numerical country code and numerical phone number passed in as strings.
    • Email
    • First and last name
    • Address
    • Date Of Birth
    • (Optional) Any additional DataPoint.Type enum data.
val userData = DataPointList()

userData.add(primaryCredential)

val phoneNumber = PhoneNumber("1", "1234567890")
val phone = PhoneDataPoint()
userData.add(phone)

val email = EmailDataPoint("user@gmail.com")
userData.add(email)

val name = NameDataPoint(firstName = "Jane", lastname = "Smith")
userData.add(name)

val address = AddressDataPoint(streetOne = "123 Main Street", locality = "San Francisco", region = "CA", postalCode = "94103", country = "US")
userData.add(address)

val birthdate = BirthDataPoint(LocalDate.of(year = 1963, month = 1, dayOfMonth: 31 ))
userData.add(birthdate)
  1. Pass the userData object into the createUser method to create a new user.
AptoPlatform.createUser(userData) {
it.either({ error ->
// Do something with the error
},
{ user ->
// The user created. It contains the user id and the user session token.
})
}
  • When the method succeeds, a User object is returned containing the user ID and user session token.
  • When the method fails, error handling can be included within the error response.

Note: The createUser method can accept the following optional parameters:

  • custodianUid - Use this parameter to send Apto the user's ID for inclusion in future webhook notifications. This simplifies the process of matching the user with the notification event.
  • metadata - Use this parameter to send Apto metadata about the new user (Max 256 chars).
val custodianUid = "custodian_uid"
AptoPlatform.createUser(userData, custodianUid) {
...
}

Login with an Existing User

Once the primary and secondary credentials are verified, you log the user in with the loginUserWith method and obtain a user token for the existing user.

Note: Ensure you pass in the successful verifications for your primary primaryVerification and secondary secondaryVerification verifications.

AptoPlatform.loginUserWith(listOf(primaryVerification, secondaryVerification) as List<Verification>) {
it.either(
{ error ->
// Do something with the error
},
{ user ->
// The user logged in. The user variable contains the user id and the user session token.
}
)
}
  • When the method succeeds, a User object is returned containing the user ID and user session token.
  • When the method fails, error handling can be included within the error response.

Update a User's Info

You can update the user's info, with the updateUserInfo method:

  1. Create DataPoint objects for the data you want to update.
val addressDataPoint = AddressDataPoint(streetOne = "123 Main Street", country = "US", locality = "San Francisco", region = "CA", postalCode = "12345")

val nameDataPoint = NameDataPoint(firstName = "John", lastName = "Doe")

The available list of DataPoint objects are:

DataPointDescription
AddressDataPointObject containing the address information for the update.
NameDataPointObject containing the user's first and last name for the update.
PhoneDataPointObject containing the phone's country code and number for the update.
EmailDataPointObject containing the email address for the update.
BirthdateDataPointObject containing the user's date of birth for the update.
IdDocumentDataPointObject containing the user's ID verification document for the update.
  1. Create a DataPointList object using the DataPoint objects:
val userDataList = listOf<DataPoint>(addressDataPoint, nameDataPoint)
val userData = DataPointList(userDataList)
  1. Pass the userData into the updateUserInfo method:
// Add to user PII (Personal Identifiable Information) the datapoints that you want to update
AptoPlatform.updateUserInfo(userData) {
it.either({ error ->
// Do something with the error
},
{ user ->
// Update successful.
})
}
  • When the method succeeds, the update is successful and a User object is returned containing the updated user information.
  • When the method fails, error handling can be included within the error response.

Close a User Session

When a session is closed, it will log the user out of all sessions on all devices.

To close the current user's session, use the logout SDK method:

AptoPlatform.logout()

Note: If the user closes the app without invoking the logout method (i.e. the user jumps to another app, manually closes the app, etc.), the user's session will still be active.

Manage Card Programs

The SDK enables you to manage card programs. This document explains how to use the SDK to:

Note: Card Programs used to be called Card Products, so you may see the SDK methods reflect the term products. These method names may change in the future to match the correct term programs.

Get Available Card Programs

To retrieve a list of all the available card programs, use the fetchCardProducts method:

AptoPlatform.fetchCardProducts {
it.either(
{ error ->
// Do something with the error
}, { cardProducts ->
// cardProducts is a list of CardProduct objects.
}
)
}
  • When the method succeeds, a list of CardProductSummary objects are returned, containing details for each card program.
  • When the method fails, error handling can be included within the error response.

Get Card Program Details

To retrieve a specific card program, pass a card program ID and forceRefresh value into the fetchCardProduct method:

forceRefresh is a boolean value indicating if transactions should be retrieved from the Apto Mobile API or the local cached transaction list. If true, transactions are retrieved from the Apto Mobile API.

val forceRefresh = false
AptoPlatform.fetchCardProduct(cardProduct, forceRefresh) {
it.either(
{ error ->
// Do something with the error
}, { cardProduct ->
// cardProduct is a CardProduct object.
}
)
}
  • When the method succeeds, a CardProduct object is returned containing details for the card program.
  • When the method fails, error handling can be included within the error response.

Manage Cards

The SDK enables you to manage cards. This feature is only available for Blue or Orange Programs.

Note: Green Programs only support one card per user.

This document explains how to use the SDK to:

Get the List of Cards for the User

To retrieve a list of cards for the current user, pass the pagination value into the fetchCards method:

The Optional pagination parameter is a ListPagination object. Use the is parameter to filter cards for the requested page.

PropertyTypeDescription
limitIntThis value specifies the upper limit of the number of payment sources returned per call. The maximum value for this parameter is 50.
startingAfterStringIf this value is set, only payment source ID's larger than this value are returned.
endingBeforeStringIf this value is set, only payment source ID's less than this value are returned.

Note: The startingAfter and endingBefore parameters are mutually exclusive. Only one of these parameters may be present per call. If both parameters are set, an error will be thrown.

AptoPlatform.fetchCards(pagination) {
it.either({ error ->
// Do something with the error
},
{ cards ->
// cards.data contains an array of Card objects
})
}
  • When the method succeeds, a cards object is returned. The data property contains a list of Card objects. Note: the Card objects can also be retrieved directly on the cards object, but this method is deprecated.
  • When the method fails, error handling can be included within the error response.

Retrieve a Card by ID

To retrieve a specific card program, pass the following into the fetchCard method:

  • cardId - A String representing the ID of the card you want to retrieve.

  • forceRefresh - A Boolean value which forces data to be returned from an API call rather than the local cache.

    Note: When this value is set to false, if local cache data does not exist, an API call is triggered.

AptoPlatform.fetchCard(cardId = cardId, forceRefresh = true) {
it.either({ error ->
// Do something with the error
},
{ card ->
// contains Card object
})
}
  • When the method succeeds, a Card object is returned containing details for the card.
  • When the method fails, error handling can be included within the error response.

Change a Card PIN

If your app enables users to change their card pin, we recommend asking the user to confirm their current PIN prior to entering and confirming a new PIN.

To set or change the card pin, use the changeCardPin method and pass in the following:

  • accountID - The cardProductId of the Card object you want to change.
  • pin - A four-digit pin passed in as a string.
val pin = "1234"
AptoPlatform.changeCardPin(accountID, pin) {
it.either(
{ error ->
// Do something with the error
}, { card ->
// Operation successful
}
)
}

Note: The returned Card object will not contain the pin property.

  • When the method succeeds, a Card object is returned containing information about the updated card.
  • When the method fails, error handling can be included within the error response.

Lock / Unlock a Card

You can enable users to lock and unlock their cards.

Transactions using a locked card will be rejected by the merchant's POS, and therefore we recommend to lock cards only if a user makes an explicit request to lock their card.

Lock a Card

To lock a card, pass the card's accountID into the lockCard method:

AptoPlatform.lockCard(accountID) {
it.either(
{ error ->
// Do something with the error
}, { card ->
// Operation successful
}
)
}
  • When the method succeeds:
    • A Card object is returned containing information about the locked card, and the card's state property will be listed as INACTIVE.
    • The registered user will receive an email confirmation that the card has been deactivated.
  • When the method fails, error handling can be included within the error response.

Unlock a Card

To unlock a card, pass the card's accountID into the unlockCard method:

AptoPlatform.unlockCard(accountID) {
it.either(
{ error ->
// Do something with the error
}, { card ->
// Operation successful
}
)
}
  • When the method succeeds, a Card object is returned containing information about the unlocked card, and the card's state property will be listed as ACTIVE. Note: Unlike the lock method, the registered user will NOT receive an email confirmation that the card has been activated.
  • When the method fails, error handling can be included within the error response.

Issue a New card

Once a user is created, you can issue a card for the user.

The steps to issue a card are:

  1. Get Card Programs
  2. Apply for a Card
  3. Get the Next Application Step
  4. Issue the Card

Get Card Programs

Each card must be issued under a card program.

To retrieve a list of all the available card programs, use the fetchCardProducts method:

AptoPlatform.fetchCardProducts {
it.either(
{ error ->
// Do something with the error
}, { cardProducts ->
// cardProducts is a list of CardProduct objects.
when (c cardProducts.size) {
0 -> {} // Error
1 -> {
val cardProductId = cardProductList[0].id
}
2 -> {
// Show screen to select the card program
}
}
}
)
}

Note: Card Programs used to be called Card Products, so you may see the SDK methods reflect the term products. These method names may change in the future to match the correct term programs.

  • When the method succeeds, a list of CardProductSummary objects are returned, containing details for each card program. Save the card program's ID you want to use to apply for a new card.
  • When the method fails, error handling can be included within the error response.

Apply for a Card

Use the card program's ID from the previous step to apply for a card.

To apply for a card:

  1. Create a CardProduct object passing in the cardProductId:
val cardProduct = CardProduct(cardProductId)
  1. Pass cardProduct into the applyToCard SDK method:
AptoPlatform.applyToCard(cardProduct) { result ->
result.either({
// handle failure
}, { cardApplication ->
// In this step we have successfully applied for a card.
// Check the cardApplication.nextAction property to identify the next step of the application
})
}
  • When the method succeeds, a CardApplication object is returned, containing details for the card application. Save the cardApplication object for the remaining steps of the application.
  • When the method fails, error handling can be included within the error response.

Get the Next Application Step

Once you have a card application initiated, check for the next application step in the nextAction property.

Note: Prior to checking for the next application step, ensure you update the card application status using the fetchCardApplicationStatus() method. For example:

AptoPlatform.fetchCardApplicationStatus(cardApplication.id) { result ->
result.either({
// Failure to retrieve application status
}, { updatedCardApplication ->
// Check for the next step.
if (updatedCardApplication.nextAction is WorkflowActionType.SHOW_DISCLAIMER) {
// Show the disclaimer
}
})
}

The cardApplication.nextAction is a WorkflowActionType value. The available WorkflowActionType values are:

ValueDescription
COLLECT_USER_DATAIf any required user information is missing, the next action value will be COLLECT_USER_DATA.
SELECT_BALANCE_STOREFor Blue or Orange Programs, if using an OAuth application process and all required user information was submitted during user creation, this is the default step. See Set the Balance Store using OAuth (Blue or Orange Programs Only) to process this step.
SHOW_DISCLAIMERFor every program, if all required user information was submitted during user creation, this is the default step prior to issuing a card. See Accept the Disclaimer to process this step.
ISSUE_CARDThis indicates the application is complete and a card can be issued for the user. See Issue the Card to issue a card for the user.
UNSUPPORTED_ACTION_TYPEThis indicates the next step is not currently supported.
Set the Balance Store using OAuth (Blue or Orange Programs only)

To set the balance store using OAuth:

  1. Get the allowed balance type from the nextAction's actionConfiguration.allowedBalanceTypes.first() property.
val allowedBalanceType = cardApplication.nextAction.actionConfiguration.allowedBalanceTypes.first()
  1. Pass the allowed balance type into the startOauthAuthentication method:
AptoPlatform.startOauthAuthentication(allowedBalanceType) { result ->
result.either({
// handle failure
}, { oauthAttempt ->
val url = oauthAttempt.url
// Start the oauth attempt in a separate screen
})
}
  • When the method succeeds, an OAuth attempt object will be returned. Save its url property for the next OAuth process.
  • When the method fails, error handling can be included within the error response.
  1. Load the OAuth attempt URL in a web view.

Note: Your OAuth server must call the Apto OAuth callback endpoint /v1/oauth/callback adhering to OAuth2 standards, including passing in the token and secret, or the error message (if any).

  1. Once the user completes the OAuth process, the user will be redirected to the apto-sdk://oauth-finish URL. Use this to check for the OAuth status.
AptoPlatform.verifyOauthAttemptStatus(oauthAttempt) { result ->
result.either({
// handle failure
}, { oauthAttempt ->
// Verify that the state is PASSED
if (oauthAttempt.state == "PASSED") {
// The OAuth attempt is successful
} else {
// The OAuth attempt failed
}
})
}

The available values for the OAuth state are PASSED or FAILED:

  • If the OAuth state is PASSED, proceed to the next step to set the balance store using the returned OAuth token ID.
  • If the OAuth state is FAILED, the user must restart the OAuth process to retrieve an OAuth token ID.
  1. Once the OAuth completes successfully, pass the card application ID and OAuth token ID into the setBalanceStore method:
aptoPlatformProtocol.setBalanceStore(cardApplication.id, oauthAttempt.tokenId) { result ->
result.either({
// handle failure
}, { selectBalanceStoreResult ->
// selectBalanceStoreResult.result should be VALID
})
}
  • When the method succeeds, a select balance store result object is returned. Ensure the result property is VALID before proceeding to the next step.
  • When the method fails, error handling can be included within the error response.
  1. Check the application status by passing the card application ID into the fetchCardApplicationStatus method:
AptoPlatform.fetchCardApplicationStatus(cardApplication.id) { result ->
result.either({
// failure
}, { updatedCardApplication ->
// Check the next step. After the balance store the result should be SHOW_DISCLAIMER
if (updatedCardApplication.nextAction is WorkflowActionType.SHOW_DISCLAIMER) {
// Show the disclaimer
}
})
}
  • When the method succeeds, check the application's nextAction property. The value should be SHOW_DISCLAIMER to indicate the next step in the application is to display the disclaimer. See Accept the Disclaimer to process this step.
  • When the method fails, error handling can be included within the error response.
Accept the Disclaimer

The user must accept the disclaimer to complete their card application. To process the user's disclaimer acceptance:

  1. Display the disclaimer to the user and ask for their acceptance.

  2. Once the user confirms they accept the disclaimer, pass the application's workflowObjectId and nextAction properties into the acceptDisclaimer method to mark the disclaimer as accepted:

AptoPlatform.acceptDisclaimer(cardApplication.workflowObjectId, cardApplication.nextAction) { result ->
result.either({
// failure
}, {
// disclaimer has been accepted
})
}
  • When the method succeeds, the disclaimer has been successfully processed.
  • When the method fails, error handling can be included within the error response.
  1. Check the application status by passing the card application ID into the fetchCardApplicationStatus method:
AptoPlatform.fetchCardApplicationStatus(cardApplication.id) { result ->
result.either({
// failure
}, { updatedCardApplication ->
// Check the next step. After the disclaimer the result should be ISSUE_CARD
if (updatedCardApplication.nextAction is WorkflowActionType.ISSUE_CARD) {
// Issue the card
}
})
}
  • When the method succeeds, check the application's nextAction property. The value should be ISSUE_CARD to indicate the application is approved so you may issue a card to the user.
  • When the method fails, error handling can be included within the error response.

Issue the Card

To issue a card to the user, pass in the card's approved application ID into the issueCard method.

Note: This method also accepts as the following optional parameters:

  • cardMetadata - String that will be stored with the card data.
  • design - An IssueCardDesign containing information about the design (Blue or Orange Programs only).
AptoPlatform.issueCard(cardApplication.id) { result ->
result.either({
// failure
}, { card ->
// card has been issued
})
}
  • When the method succeeds, the card has been issued.
  • When the method fails, error handling can be included within the error response.

Order a Physical Card

Depending on the program, the card configuration may have the "digital with optional physical" configuration. This configuration enables the cardholder to issue a digital card during the onboarding process. Afterwards, the user can choose to order a physical card. See Get Program Configuration for Physical Card for more information.

If enabled, registered cardholders can order a physical card matching the same PAN as their virtual card. Once ordered, the card will be sent by postal mail to their registered address.

A cardholder should:

  • Have an existing virtual card. A physical card can only be ordered if the user already has an existing virtual card
  • Be aware of potential costs when ordering a new physical card.
  • Have enough funds to purchase a card (if there is a cost) prior to proceeding with the order request.

Ensure you validate this information prior to issuing a physical card request.

Get Configuration for Physical Card

Depending on your program configuration, there may be a cost associated with ordering a physical card.

To check if the physical card requires a fee, use the getOrderPhysicalCardConfig method to retrieve the configuration details:

AptoPlatform.getOrderPhysicalCardConfig(cardId) { result ->
result.either({
// failure
}, { config ->
// card has been ordered
})
}
  • When the method succeeds, an OrderPhysicalCardConfig object is returned containing information about the card configuration for the physical card ordering process.
    • issuanceFee refers to the amount the user will have to pay for the physical card.
    • userAddress is the address where the physical card will be shipped.
  • When the method fails, error handling can be included within the error response.

Submit a Physical Card Order

To order a physical card, pass the card accountID into the orderPhysicalCard method:

AptoPlatform.orderPhysicalCard(accountID) { result ->
result.either({
// failure
}, { card ->
// card has been ordered
})
}
  • When the method succeeds, a card object is returned containing information about the status of the order in the orderedStatus property, which can be one of the following values: notApplicable, available, ordered, received.
  • When the method fails, error handling can be included within the error response.

Activate a Physical Card

Physical cards need to be activated using the provided activation code sent to the cardholder.

For Green Programs, physical cards are shipped to user in a card carrier envelope. This carrier contains:

  • The physical card
  • The card’s Activation Code
  • The issuing statement and the name of your program.

For more information about physical cards, see the Apto Developer Guides.

To activate a physical card, use the activatePhysicalCard method and pass in the card's account ID accountID and the user's Activation Code PHYSICAL_CARD_ACTIVATION_CODE as a string:

val code = "PHYSICAL_CARD_ACTIVATION_CODE"

AptoPlatform.activatePhysicalCard(accountID, code) {
it.either(
{ error ->
// Do something with the error
}, { result ->
// Result contains information about the activation process and, if it failed, the reason why it failed.
}
)
}
  • When the method succeeds, a result object is returned containing information about the activation process.
  • When the method fails, an error object will contain the reason for the failure. Error handling can be included within the error response. Reasons for failure may include: internet connection issues, inoperable API, bad code, etc.

View Card Transactions and Spending

The SDK provides methods to:

View Card Transactions

To retrieve a list of transactions, pass the following into the fetchCardTransactions method:

  • accountID - The card's account ID
  • filters - A TransactionListFilters object, which filters the transactions by page, row, date, mcc, type, etc. For more information about the parameters for this object, see the Mobile API
    • page - This is the page number, specifying the portion of the list of filters.
    • rows - This is the number of filters to display per page.
  • forceRefresh - A boolean value indicating if transactions should be retrieved from the Apto Mobile API or the local cached transaction list. If true, transactions are retrieved from the Apto Mobile API.
  • clearCachedValues - A boolean value indicating if the old cached data should be removed and replaced with the new API values.
val page = 0
val rows = 10
val filters = TransactionListFilters(page, rows)
val forceRefresh = false
val clearCachedValues = false

AptoPlatform.fetchCardTransactions(accountID, filters, forceRefresh, clearCachedValues) {
it.either({ error ->
// Do something with the error
},
{ transactions ->
// transactions contains a list of Transaction objects.
})
}
  • When the method succeeds, a list of Transaction objects are returned.
  • When the method fails, error handling can be included within the error response.

View Monthly Spending Stats

The SDK enables you to view the monthly spending for cards, classified by category.

To retrieve information about the monthly spending for a card, use the cardMonthlySpending method with the following parameters:

  • accountID - This is the card's account ID.
  • month - This is the spending month, specified as an Int, from 1 (January) to 12 (December).
  • year - This is the four-digit spending year, specified as an Int. For example 2018, 2019, 2020, etc.
val month = 1
val year = 2020

AptoPlatform.cardMonthlySpending(accountID, month, year) {
it.either(
{ error ->
// Do something with the error
}, { monthlySpending ->
// Returns a MonthlySpending object containing the stats of the given month.
}
)
}
  • When the method succeeds, a MonthlySpending object is returned containing the stats for the provided month. The spending is classified by transaction category, and the difference from the previous month.
  • When the method fails, error handling can be included within the error response.

Manage Card Payment Sources / Load Funds

Funds loaded onto a user's card is automatically deducted from the payment source. The balance is maintained on the user's card, managed by Apto Payments. You can load money onto a user's card using a valid debit card.

Sandbox Cards for Testing

We've provided a list of cards that can be used to test adding card funds, within the sandbox environment:

Card TypeCard Number
Visa4111111111111111
Visa400000076000002
Mastercard5200828282828210
Mastercard2223000048400011

For all test cards:

  • Any expiration date set to a future date may be used.
  • Any CVV value may be used.
  • Any 5-digit postal code value may be used.

Get Payment Sources

A list of payment sources can be retrieved using the getPaymentSources method. The method accepts three optional parameters:

ParameterTypeDescription
limitIntThis value specifies the upper limit of the number of payment sources returned per call. The maximum value for this parameter is 50.
startingAfterStringIf this value is set, only payment source ID's larger than this value are returned.
endingBeforeStringIf this value is set, only payment source ID's less than this value are returned.

Note: The startingAfter and endingBefore parameters are mutually exclusive. Only one of these parameters may be present per call. If both parameters are set, an error will be thrown.

val limit = 10
val startingAfter = "id_123"
AptoPlatform.getPaymentSources( {
it.either(
{ error ->
// Do something with the error
}, { paymentSources ->
// paymentSources contains a list of PaymentSource objects.
}
)
},
limit,
startingAfter
)
  • When the method succeeds, a paymentSources object is returned containing a list of PaymentSource objects.
  • When the method fails, error handling can be included within the error response.

Add a Payment Source

To add a payment source:

  1. Create a NewCard object:

    Note: Currently only cards are accepted.

val paymentSource = NewCard(
description = "test description",
pan = "4111111111111111",
cvv = "123",
expirationMonth = "12",
expirationYear = "22",
zipCode = "12345"
)
  1. Pass paymentSource into the addPaymentSource method:

    Note: Added payment sources are automatically marked as preferred and will be set as the new default payment source.

AptoPlatform.addPaymentSource(paymentSource) {
it.either({ error ->
// Do something with the error
}, { source ->
// source contains a PaymentSource object.
})
}
  • When the method succeeds, the added PaymentSource object is returned without the PII (Personal Identifiable Information).
  • When the method fails, error handling can be included within the error response.

Delete a Payment Source

To delete a payment source, pass the payment source ID into the deletePaymentSource method:

Note: A preferred payment source can not be deleted.

val paymentSourceId = "payment_source_XXXXXXXXX"
AptoPlatform.deletePaymentSource(paymentSourceId) {
it.either(
{ error ->
// Do something with the error
}, { source ->
}
)
}
  • When the method succeeds, no response will be returned.
  • When the method fails, error handling can be included within the error response.

Add Funds to a Card

To add funds to a card, pass the following parameters into the pushFunds method:

ParameterTypeDescription
balanceIdStringThis is the card's funding source ID you want to fund. See Get a Card's Default Funding Source to retrieve the balance ID property.
paymentSourceIdStringThis is the Payment Source ID that will be used to add funds.
amountMoneyThis object specifies the amount and currency that will be added to the balance. Note: The amount parameter of this object must use the Double format.
val balanceId = "bal_XXXXXXXXX"
val paymentSourceId = "payment_source_XXXXXXXXX"
val money = Money("USD", 100.00)

AptoPlatform.pushFunds(balanceId, paymentSourceId, money) {
it.either(
{ error ->
// Do something with the error
}, { payment ->
// result contains a Payment object.
}
)
}
  • When the method succeeds, a Payment object is returned with the completed payment information.
  • When the method fails, error handling can be included within the error response.

Add Funds using Direct Deposit

For Green Programs, ACH is enabled be default, and users can use their registered ACH account to add funds to their card.

Blue or Orange Programs that do not enable ACH upon account creation, must enable is separately. See Set up Direct Deposit for an Existing User for more information.

To retrieve the ACH account information:

  1. Retrieve the card you want to add money to using the Retrieve a Card by cardId method.
  2. Use the returned Card object to find the card feature list (Features object).
  3. One of the Features properties is named achAccount.
card.features?.achAccount
PropertyTypeDescription
isEnabledBooleanIndicates if the card has the ACH feature enabled.
isAccountProvisionedBooleanIndicates if the account has accepted the ACH disclaimers and the ACH account has been created.
disclaimerDisclaimerIn the case that the user has not accepted the ACH related disclaimer, an instance of it will be provided
accountDetailsAchAccountDetailsContains the routing number and the account number used to load funds.
Set up Direct Deposit for an Existing User

For Blue or Orange Programs that do not have ACH enabled upon account creation, but would like to enable it:

  1. Retrieve the card you want to add money to, using the Retrieve a Card by cardId method.
  2. Use the returned Card object to find the card feature list (Features object).
  3. One of the Features properties is named achAccount. Find the Disclaimer object of the achAccount card feature.
  4. Present the disclaimer to the user. For example:
val agreements = card.features?.achAccount.disclaimer.keys

AptoPlatform.reviewAgreements(agreements, AgreementAction.ACCEPTED) {
it.either(
{ error ->
// Do something with the error
}, {
// The agreement acceptance has been correctly saved
}
)
}

Note: If the disclaimer is not accepted, you can not assign the ACH account to the funding source.

  1. Once the disclaimer is accepted, get the card's funding source. For example:
val forceRefresh = false

AptoPlatform.fetchCardFundingSource(balanceId, forceRefresh) {
it.either(
{ error ->
// Do something with the error
}, { fundingSource ->
// Returns a FundingSource object containing details about the funding source.
}
)
}
  1. Once the funding source is obtained, assign the ACH account to the funding source:
val balanceId = fundings

AptoPlatform.assignAchAccount(fundingSource.id) {
it.either(
{ error ->
// Do something with the error
}, { accountDetails ->
// Returns a AchAccountDetails object containing details of the ACH account just created.
}
)
}

Manage Card Funding Sources for On-demand Debits (Blue or Orange Programs only)

Funding sources may be used for on-demand debiting. When a user spends using their card, the amount can be debited from a specified funding source, rather than using the funds loaded onto their card. A card can have more than one funding source.

Note: Only Blue or Orange Programs may use this feature to connect a funding source to a card. Green Programs may only load funds onto a card.

The Mobile SDK enables you to:

Get a Card's Default Funding Source

To retrieve a card's default funding source, pass the following parameters into the fetchCardFundingSource method.

  • accountID - The card's account ID
  • forceRefresh - Boolean value indicating if transactions should be retrieved from the Apto Mobile API or the local cached transaction list. If true, transactions are retrieved from the Apto Mobile API.

Note: If no default funding source is specified, the first available funding source will be used as the default funding source.

val forceRefresh = false

AptoPlatform.fetchCardFundingSource(accountID, forceRefresh) {
it.either(
{ error ->
// Do something with the error
}, { fundingSource ->
// Returns a FundingSource object containing details about the funding source.
}
)
}
  • When the method succeeds, a FundingSource object is returned containing information about the funding source.
  • When the method fails, error handling can be included within the error response.

List a Card's Available Funding Sources

Apto cards may have multiple funding sources. To retrieve a list of available funding sources for a card, pass the following parameters into the fetchCardFundingSources method:

  • accountID - This is the card's account ID.
  • page - This is the page number, specifying the portion of the list of funding sources.
  • rows - This is the number of funding sources to display per page.
  • forceRefresh - Boolean value indicating if transactions should be retrieved from the Apto Mobile API or the local cached transaction list. If true, transactions are retrieved from the Apto Mobile API.
val page = 0
val rows = 10
val forceRefresh = false

AptoPlatform.fetchCardFundingSources(accountID, page, rows, forceRefresh) {
it.either(
{ error ->
// Do something with the error
}, { fundingSources ->
// fundingSources contains a list of FundingSource objects.
}
)
}
  • When the method succeeds, a list of FundingSource objects are returned.
  • When the method fails, error handling can be included within the error response.

Connect a Funding Source to a Card

Blue or Orange Programs can issue cards connected to a funding source not controlled by Apto Payments. Therefore, only Blue or Orange Programs can manage funding sources.

For example, when using the Coinbase card program, users connect their Coinbase wallet and select whether the card is Bitcoin or Ethereum using these funding source management methods.

To connect a funding source to a card, pass the card accountID and funding source id into the setCardFundingSource method:

AptoPlatform.setCardFundingSource(accountID, fundingSource.id) {
it.either(
{ error ->
// Do something with the error
}, { fundingSource ->
// Operation successful.
}
)
}
  • When the method succeeds, a FundingSource object is returned containing information for the funding source.
  • When the method fails, error handling can be included within the error response.

Set Notification Preferences

Push notifications for users are available for several events (transactions, card status changes, etc.). The SDK can enable the users to decide how they receive some of these notifications.

Notifications

This section demonstrates how to:

Get Notification Preferences

To retrieve the current user's notification preferences, use the fetchNotificationPreferences method.

AptoPlatform.fetchNotificationPreferences {
it.either(
{ error ->
// Do something with the error
}, { notificationPreferences ->
// Returns a NotificationPreferences object containing all the information regarding the current user preferences.
}
)
}
  • When the method succeeds, a NotificationPreferences object is returned containing the information for current user's notification preferences. Its preferences property contains a list of NotificationGroup objects, containing details for each notification.
  • When the method fails, error handling can be included within the error response.

Update Notification Preferences

To update the current user's notification preferences:

  1. Create a NotificationPreferences object.
val existingNotificationGroup = notificationPreferences.preferences?.first()
val notificationGroup = NotificationGroup(existingNotificationGroup?.categoryId, existingNotificationGroup?.groupId, NotificationGroup.State.DISABLED, existingNotificationGroup?.activeChannels)
val preferences = NotificationPreferences(listOf(notificationGroup))
  1. Pass the preferences object into the updateNotificationPreferences method.
AptoPlatform.updateNotificationPreferences(preferences) {
it.either(
{ error ->
// Do something with the error
}, { notificationPreferences ->
// Operation successful
}
)
}
  • When the method succeeds, a notificationPreferences object is returned containing the information for current user's notification preferences.
  • When the method fails, error handling can be included within the error response.

P2P Payments

P2P payments are transactions between users of the same card program with many use cases like splitting a dinner bill between friends. The process to send money to another users is divided in two:

Find the recipient

To retrieve a recipient, pass the following parameters into the p2pFindRecipient method:

  • (Optional) phone - This is the recipient phone number.
  • (Optional) email - This is the email address.

Note: Include only the primary credential of your card program.

AptoPlatform.p2pFindRecipient(
phone: PhoneNumber? = null,
email: String? = null,
) {
it.either(
{ error ->
// Do something with the error
}, { cardHolderData ->
// Operation successful
}
)
}
  • When the method succeeds, a CardHolderData object is returned containing information about the recipient.
  • When the method fails, error handling can be included within the error response.

Make the transfer

To complete the transfer you must call this method with the following parameters:

  • sourceId - Users balance id that will be the source of the funds.
  • recipientId - The recipientId found in cardHolderData object from Find the recipient.
  • amount - This object specifies the amount and currency that will be sent to the recipient.
AptoPlatform.p2pMakeTransfer(
sourceId,
recipientId,
amount
) {
it.either(
{ error ->
// Do something with the error
}, { cardHolderData ->
// Operation successful
}
)
}

Contributions & Development

We look forward to receiving your feedback, including new feature requests, bug fixes and documentation improvements.

If you would like to help:

  1. Refer to the issues section of the repository first, to ensure your feature or bug doesn't already exist (The request may be ongoing, or newly finished task).
  2. If your request is not in the issues section, please feel free to create one. We'll get back to you as soon as possible.

If you want to help improve the SDK by adding a new feature or bug fix, we'd be happy to receive pull requests!