Are you looking for test card numbers?

Would you like to contact support?

Marketpay icon

Using Authentication SDK

Learn how to integrate our Authentication SDK to authenticate your user in your secure application.

Before your user can start using Adyen's business accounts to transfer funds in the European Economic Area (EEA) or check their transaction history, your platform needs to comply with Payment Services Directive 2 (PSD2) that regulates secure payments and account access through Strong Customer Authentication (SCA). This means that during the authentication the user is required to provide two out of three factors:

  • Knowledge: something only the user knows.
  • Possession: something only the user possesses.
  • Inherence: something the user is.

To help you comply with PSD2, we provide a client-side Authentication SDK that uses the possession factor through device binding and either the knowledge or the inherence factor, depending on the user's device access configuration. It's a two-factor authentication that requires a secondary verification method through a separate communication channel. For example, a mobile phone.

With Adyen's Authentication SDK, you can:

  • Check if the user's device is eligible for Strong Customer Authentication (SCA).
  • Register your user's mobile device to create device binding.
  • Authenticate your user's subsequent actions.

The Authentication SDK integration also works with Adyen Issuing to authenticate a cardholder with 3D Secure.

System requirements

We provide the client-side Authentication SDK in the following languages:

  • Kotlin or Java for Android applications
  • Swift for iOS applications

Before you start implementing the SDK, make sure that your system follows the requirements.

  • Your application targets minimum Android API level 21 or later.
  • The authentication feature works on devices running on Android API level 26 and later.
  • The authentication feature requires Google Play Services on the cardholder's device.
To ensure the correct support type for 3D Secure on the card program, contact our Support Team.

Installation

To install the Authentication SDK:

  1. Add the following line to your build.gradle file.
    implementation "com.adyen.authentication:android-authentication:0.1.0"

Register device

Before starting the device registration, make sure that the operating system on the user's device supports SCA.

Step 1: Check SCA eligibility

This functionality requires additional configuration from Adyen. To enable it, contact our Support Team.
To check if the Android device is eligible for SCA:
  1. Initiate the AdyenAuthentication class in your Activity or Fragment.
    Initiate authentication
    private lateinit var adyenAuthentication: AdyenAuthentication
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        adyenAuthentication = AdyenAuthentication(this)
    }
  2. Check if SCA is available on the device.
    Check SCA eligibility
    lifecycleScope.launch {
        val availabilityResult: AvailabilityResult = adyenAuthentication.checkAvailability()
        if (availabilityResult is AvailabilityResult.Available) {
            availabilityResult.sdkOutput
        }
    }
    The output contains sdkOutput that you will use when initiating the registration.
  3. Pass sdkOutput to your server. We suggest that you store sdkOutput for further usage, in case you need to start the registration process again.

Step 2: Initiate device registration

Registering the device is a one-off procedure for each device. In case your user uses multiple devices, you'll need to register each of their devices separately.

To start the device registration:

  1. From your server, make a POST /registeredDevices request. To make this request, your API credential needs the following role:
    • Bank SCA Webservice Role
    Reach out to you Adyen contact to set it up for you. In the request, specify the following:
    Parameter Description
    paymentInstrumentId The unique identifier of the payment instrument you want to register the device for.
    strongCustomerAuthentication.sdkOutput Base64-encoded blob of data created in the previous step.
    Initiate device registration
    curl https://balanceplatform-api-test.adyen.com/bcl/v2/registeredDevices \
    -H "x-api-key: YOUR_BALANCE_PLATFORM_API_KEY" \
    -H "content-type: application/json" \
    -X POST \
    -d '{
        "paymentInstrumentId": "PI00000000000000000000001",
        "strongCustomerAuthentication" : {
            "sdkOutput": "eyJjaGFubmVsIjoiYXBwIiwib3BlcmF0aW5nU3lzdGV..."
        }
    }'
    The response returns: We suggest that you create and store a mapping between the registered device id and the human-readable account holder name. For example, RD00000000000000000000001 is "Cardholder's iPhone". You can use this pair later to show the details, for example, when unbinding the device.
    Initiate device registration response
    {
        "id": "RD00000000000000000000001",
        "paymentInstrumentId": "PI00000000000000000000001",
        "sdkInput": "eyJjaGFsbGVuZ2UiOiJiVlV6ZW5wek0waFNlQzFvVjBGSGRVaDNaVXc1UVE9PSJ9",
        "success": true
    }

Step 3: Authenticate user

In your client app, perform user authentication. PSD2 requires you to perform two-factor authentication (2FA) as an extra security step during the login process.

Step 4: Register the device

After you successfully authenticate your user:

  1. Trigger the SDK to start the device registration and pass sdkInput from step 2.
    Register device with SCA SDK
    lifecycleScope.launch {
      val registrationResult: AuthenticationResult = adyenAuthentication.register("sdkInput")
      when (registrationResult) {
          is AuthenticationResult.RegistrationSuccessful -> {
              registrationResult.sdkOutput
          }
          is AuthenticationResult.Canceled -> {
              // cardholder canceled the flow
          }
          is AuthenticationResult.Error -> {
              // Unexpected error
              registrationResult.errorMessage
          }
          is AuthenticationResult.AuthenticationError -> {
              // FIDO API Error
              registrationResult.authenticationError
          }
      }
    }
    After the successful registration, the SDK generates a Base64-encoded sdkOutput data blob.
  2. Pass sdkOutput to your server.

Step 5: Finalize registration

To finalize the device registration:

  1. From your server, make a PATCH /registeredDevices/{id} request, specifying the device id in the path and the following parameters in the request body:
    Parameter Description
    paymentInstrumentId The unique identifier of the payment instrument you want to register the device for.
    strongCustomerAuthentication.sdkOutput Base64-encoded blob of data created in the previous step.
    Finalize device registration
    curl https://balanceplatform-api-test.adyen.com/bcl/v2/registeredDevices/{id} \
    -H "x-api-key: YOUR_BALANCE_PLATFORM_API_KEY" \
    -H "content-type: application/json" \
    -X PATCH \
    -d '{
      "paymentInstrumentId": "PI00000000000000000000001",
      "strongCustomerAuthentication" : {
          "sdkOutput": "eyJhdHRlc3RhdGlvbk9iamVjdCI6Im8yTm1iWF..."
      }
    }'
    The response contains success true.

The registration is now complete. The user can start authenticating future transactions using your app.

Make a transfer

Each time your user wants to make a transfer you need to authenticate them. To do so:

  1. Initiate the transfer.
  2. Authenticate your user using the SDK.
  3. Finalize the transfer.

Step 1: Initiate transfer

Let's assume that your user chooses to make a funds transfer. To start the transfer:

  1. Make a POST /transfers request, specifying the following parameters in the header:

    Request header Description
    WWW-Authenticate SCA realm: Transfer.
    auth-param1: Base64-encoded value of sdkOutput from checking SCA eligibility.

    Provide the following parameters in the request body:

    Parameter Description
    amount The amount of the transfer.
    category Set to internal.
    description A human-readable description for the transfer.
    balanceAccountId Unique identifier of the source balance account.
    reference A reference of the transfer, only used internally within your platform.
    referenceForBeneficiary A reference that is sent to the recipient.
    counterparty.balanceAccountId Unique identifier of the target balance account.
    Start funds transfer
    curl https://balanceplatform-api-test.adyen.com/btl/v3/transfers \
    -H "x-api-key: YOUR_BALANCE_PLATFORM_API_KEY" \
    -H "content-type: application/json" \
    -H "WWW-Authenticate: SCA realm="Transfer" auth-param1="eyJjaGFsbGVuZ2UiOiJiVlV6ZW5wek0waFNl..."" \
    -X POST \
    -d '{
      "amount": {
          "currency": "EUR",
          "value": 1000
      },
      "balanceAccountId": "BA00000000000000000000001",
      "category": "internal",
      "description": "YOUR_DESCRIPTION_FOR_THE_TRANSFER",
      "reference": "YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER",
      "referenceForBeneficiary": "YOUR_REFERENCE_SENT_TO_BENEFICIARY",
      "counterparty": {
          "balanceAccountId": "BA00000000000000000000002"
      }
    }'

    The response contains the following fields in the header:

    • status: 401
    • auth-param1: Base64-encoded blob of data

    You will need auth-param1 when authenticating your user using the SDK.

    Start funds transfer response
    {
      "type": "https://docs.adyen.com/errors/unauthorized",
      "title": "Unauthorized",
      "status": 401,
      "response": {
          "amount": {
              "currency": "EUR",
              "value": 1000
          },
          "balanceAccountId": "BA00000000000000000000001",
          "category": "internal",
          "description": "YOUR_DESCRIPTION_FOR_THE_TRANSFER",
          "reference": "YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER",
          "referenceForBeneficiary": "YOUR_REFERENCE_SENT_TO_BENEFICIARY",
          "counterparty": {
              "balanceAccountId": "BA00000000000000000000002"
          }
      },
      "errorCode": "00_401"
    }
  2. Pass auth-param1 to the SDK.

Step 2: Authenticate user

Authenticate your user using the SDK. To do so:

  1. Trigger the SDK to start user authentication and pass the auth-param1 value from the previous step as sdkInput. As required by PSD2, the amount and the counterparty (payee) of the transfer that the user is authenticating for must be shown during the authentication. To comply with the regulations, we recommend that you implement a push notification and use the amount and counterparty from the response in the previous step to show this information.

    lifecycleScope.launch {
            if (adyenAuthentication.hasCredential("sdkInput")) {
                // Authenticate existing credential
                val authenticationResult: AuthenticationResult = adyenAuthentication.authenticate("sdkInput")
                when (authenticationResult) {
                    is AuthenticationResult.AuthenticationSuccessful -> {
                        authenticationResult.sdkOutput
                    }
                    is AuthenticationResult.Canceled -> {
                        // User cancelled the authentication flow
                    }
                    is AuthenticationResult.Error -> {
                        // Unexpected error
                        authenticationResult.errorMessage
                    }
                    is AuthenticationResult.AuthenticationError -> {
                        // FIDO API Error
                        authenticationResult.authenticationError
                    }
                }
            } else {
                // None of the existing credentials exist in this device
            }
        }
    delegatedAuthenticationSession.authenticate(withBase64URLString: sdkInput) { [weak self] result in
            switch result {
            case let .success(sdkOutput):
                /// send the sdkOutput to the backend
            case let .failure(error):
                /// authentication failed
            }
        }
  2. Pass sdkOutput to your server.

Step 3: Finalize transfer

To finalize the transfer:

  1. Make a POST /transfers request, specifying the following parameter in the request header:

    Request header Description
    WWW-Authenticate SCA realm: Transfer.
    auth-param1: Base64-encoded value of sdkOutput from user authentication.

    Provide the following parameters in the request body:

    The parameter values must match the ones submitted to the /transfers endpoint previously when initiating the transfer.

    Parameter Description
    amount The amount of the transfer.
    category Set to internal.
    description A human-readable description of the transfer.
    balanceAccountId Unique identifier of the source balance account.
    reference A reference for the transfer, only used internally within your platform.
    referenceForBeneficiary A reference that is sent to the recipient.
    counterparty.balanceAccountId Unique identifier of the target balance account.
    Finalize funds transfer
    curl https://balanceplatform-api-test.adyen.com/btl/v3/transfers \
    -H "x-api-key: YOUR_BALANCE_PLATFORM_API_KEY" \
    -H "content-type: application/json" \
    -H "WWW-Authenticate: SCA realm="Transfer" auth-param1="eyJjaGFsbGVuZ2UiOiJiVlV6ZW5wek0waFNlQzF..."" \
    -X POST \
    -d '{
      "amount": {
          "currency": "EUR",
          "value": 1000
      },
      "balanceAccountId": "BA00000000000000000000001",
      "category" : "internal",
      "description": "YOUR_DESCRIPTION_FOR_THE_TRANSFER",
      "reference": "YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER",
      "referenceForBeneficiary": "YOUR_REFERENCE_SENT_TO_BENEFICIARY",
      "counterparty": {
          "balanceAccountId": "BA00000000000000000000002"
      }
    }'

    The response header contains status authorised in the header, meaning the authentication and the transfer request were successful.

    Finalize funds transfer response
    {
      "id": "1W1UG35U8A9J5ZLG",
      "amount": {
          "currency": "EUR",
          "value": 1000
      },
      "balanceAccountId": "BA00000000000000000000001",
      "category": "internal",
      "counterparty": {
          "balanceAccountId": "BA00000000000000000000002"
      },
      "description": "YOUR_DESCRIPTION_FOR_THE_TRANSFER",
      "reference": "YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER",
      "referenceForBeneficiary": "YOUR_REFERENCE_SENT_TO_BENEFICIARY",
      "direction": "outgoing",
      "reason": "approved",
      "status": "authorised"
    }

Get transaction history

Each time your user wants to check their transaction history, you need to authenticate them. To do so:

  1. Request your user's transaction history.
  2. Authenticate your user using the SDK.
  3. Get the transaction history.

Step 1: Request transaction history

To request the transaction history for the specified balance account:

  1. Make a GET /transactions request, specifying the following parameter in the header:

    Request header Description
    WWW-Authenticate SCA realm: Transaction.
    auth-param1: Base64-encoded value of sdkOutput from checking SCA eligibility.

    Provide the following query parameters:

    Parameter Description
    balanceAccountId Unique identifier of the balance account to get the transaction history for.
    createdSince Only include transactions that have been created on or after this point in time. The value must be in ISO 8601 format. For example, 2022-05-30T15:07:40Z.
    createdUntil Only include transactions that have been created on or before this point in time. The value must be in ISO 8601 format. For example, 2022-05-31T15:07:40Z.
    Request transaction history
    curl https://balanceplatform-api-test.adyen.com/btl/v3/transactions?balanceAccountId=BA00000000000000000000002&createdSince=2022-05-30T15:07:40Z&createdUntil=2022-05-31T15:07:40Z\
    -H "x-api-key: YOUR_BALANCE_PLATFORM_API_KEY" \
    -H "content-type: application/json" \
    -H "WWW-Authenticate: SCA realm="Transaction" auth-param1="eyJjaGFsbGVuZ2UiOiJiVlV6ZW5wek0waFNl..."" \
    -X GET \
    -d '{
    }'

    The response contains the following field in the header:

    • auth-param1: Base64-encoded blob of data.

    You will need auth-param1 when authenticating your user using the SDK.

    Response
    {
    "type": "https://docs.adyen.com/errors/unauthorized",
    "title": "Unauthorized",
    "status": 401,
    "errorCode": "00_401"
    }
  2. Pass auth-param1 to the SDK.

Step 2: Authenticate user

To authenticate your user using the SDK:

  1. Trigger the SDK and pass the auth-param1 value from the previous step as sdkInput.

    lifecycleScope.launch {
            if (adyenAuthentication.hasCredential("sdkInput")) {
                // Authenticate existing credential
                val authenticationResult: AuthenticationResult = adyenAuthentication.authenticate("sdkInput")
                when (authenticationResult) {
                    is AuthenticationResult.AuthenticationSuccessful -> {
                        authenticationResult.sdkOutput
                    }
                    is AuthenticationResult.Canceled -> {
                        // User cancelled the authentication flow
                    }
                    is AuthenticationResult.Error -> {
                        // Unexpected error
                        authenticationResult.errorMessage
                    }
                    is AuthenticationResult.AuthenticationError -> {
                        // FIDO API Error
                        authenticationResult.authenticationError
                    }
                }
            } else {
                // None of the existing credentials exist in this device
            }
        }
    delegatedAuthenticationSession.authenticate(withBase64URLString: sdkInput) { [weak self] result in
            switch result {
            case let .success(sdkOutput):
                /// send the sdkOutput to the backend
            case let .failure(error):
                /// authentication failed
            }
        }
  2. Pass sdkOutput to your server.

Step 3: Get transaction history

To get the transactions history:

  1. Make a GET /transactions request, specifying the following parameter in the request header.

    Request header Description
    WWW-Authenticate SCA realm: Transaction.
    auth-param1: Base64-encoded value of sdkOutput from user authentication.
    Get user transaction history
    curl https://balanceplatform-api-test.adyen.com/btl/v3/transactions?balanceAccountId=BA00000000000000000000002&createdSince=2022-05-30T15:07:40Z&createdUntil=2022-05-31T15:07:40Z\
    -H "x-api-key: YOUR_BALANCE_PLATFORM_API_KEY" \
    -H "content-type: application/json" \
    -H "WWW-Authenticate: SCA realm="Transaction" auth-param1="eyJjaGFsbGVuZ2UiOiJiVlV6ZW5wek0waFNl..."" \
    -X GET \
    -d '{
    }'

    The response contains the data array with the details of all transactions for the specified period.

    Response
    {
    "data": [
      {
        "accountHolderId": "AH00000000000000000000001",
        "amount": {
          "currency": "EUR",
          "value": -9
        },
        "balanceAccountId": "BA00000000000000000000001",
        "balancePlatform": "YOUR_BALANCE_PLATFORM",
        "bookingDate": "2022-05-30T11:21:24+01:00",
        "category": "internal",
        "createdAt": "2022-05-30T11:21:24+01:00",
        "id": "1VVF0D5U66PIUIVP",
        "instructedAmount": {
          "currency": "EUR",
          "value": -9
        },
        "reference": "REFERENCE_46e8c40e",
        "status": "booked",
        "transferId": "1VVF0D5U66PIUIVP",
        "type": "fee",
        "valueDate": "2022-05-30T11:21:24+01:00"
      },
      {
        "accountHolderId": "AH00000000000000000000001",
        "amount": {
          "currency": "EUR",
          "value": -46
        },
        "balanceAccountId": "BA00000000000000000000001",
        "balancePlatform": "YOUR_BALANCE_PLATFORM",
        "bookingDate": "2022-05-31T14:22:52+01:00",
        "category": "internal",
        "createdAt": "2022-05-31T14:22:52+01:00",
        "id": "1WEPGD5U6MS1CFK3",
        "instructedAmount": {
          "currency": "EUR",
          "value": -46
        },
        "reference": "YOUR_REFERENCE",
        "status": "booked",
        "transferId": "1WEPGD5U6MS1CFK3",
        "type": "fee",
        "valueDate": "2022-05-31T14:22:52+01:00"
      }
    ],
    "_links": {
      "next": {
        "href": "https://balanceplatform-api-test.adyen.com/btl/v3/transactions?balancePlatform=YOUR_BALANCE_PLATFORM&createdUntil=2022-05-30T00%3A00%3A00Z&createdSince=2022-05-31T00%3A00%3A00Z&limit=3&cursor=S2B-TSAjOkIrYlIlbjdqe0RreHRyM32lKRSxubXBHRkhHL2E32XitQQz5SfzpucD5HbHwpM1p6NDR1eXVQLFF6MmY33J32sobDxQYT90MHIud1hwLnd6JitcX32xJ"
      }
    }
    }

Next steps

Create an Adyen business account to start sending and receiving funds.