Adyen-for-platform icon

SCA for funds transfers

Learn how to use our Authentication SDK to authenticate your users when they make transfers.

Each time a user in the European Economic Area (EEA) wants to transfer funds, you must authenticate them using SCA. To do so:

  1. Check SCA eligibility.
  2. Initiate the transfer using the sdkOutput that you got when you checked the device for SCA eligibility.
  3. Authenticate your user with the Authentication SDK.
  4. Finalize the transfer using the sdkOutput from the authentication step.

Requirements

Check SCA eligibility

Before initiating a transfer, you must check for SCA eligibility and initiate the process to authenticate your users.

The following tabs explain how to check for SCA eligibility and initiate authentication using Kotlin, Swift, or JavaScript.

To check if the Android device is eligible for SCA:

  1. Initiate the AdyenAuthentication class in your Activity or Fragment.

    Initiate authentication
    Expand view
    Copy link to code block
    Copy code
    Copy code
    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
    Expand view
    Copy link to code block
    Copy code
    Copy code
    lifecycleScope.launch {
    val availabilityResult: AvailabilityResult = adyenAuthentication.checkAvailability()
    if (availabilityResult is AvailabilityResult.Available) {
    availabilityResult.sdkOutput
    }
    }

    The function returns an sdkOutput.

  3. Pass the sdkOutput to your server.

You will use the sdkOutput when initiating the transfer.

Initiate transfer

The steps to initiate a transfer depend on whether you want to:

  • Authenticate the user when initiating a transfer request.
  • Authenticate the reviewer when approving a transfer request.

Because a reviewer can approve multiple transfers at the same time, performing SCA during approval allows you to satisfy the authentication requirements for multiple transfers with a single SCA process.

The following tabs explain both methods for initiating a transfer that requires SCA.

To initiate a funds transfer for your user and trigger SCA, do the following:

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

    Parameter Type Required Description
    WWW-Authenticate Header -white_check_mark- SCA realm: Transfer.
    auth-param1: Base64-encoded value of sdkOutput you get when you initiate authentication.
    amount Body -white_check_mark- The amount of the transfer.
    balanceAccountId Body -white_check_mark- The unique identifier of the source balance account.
    category Body -white_check_mark- Set to bank.
    counterparty.bankAccount Body -white_check_mark- Contains information about the target bank account.
    description Body A human-readable description for the transfer.
    reference Body A reference of the transfer, only used internally within your balance platform.
    referenceForBeneficiary Body A reference that is sent to the recipient.
    Initiate funds transfer and trigger SCA
    Expand view
    Copy link to code block
    Copy code
    Copy code
    curl https://balanceplatform-api-test.adyen.com/btl/v4/transfers \
    -H 'x-api-key: ADYEN_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": "bank",
    "description": "YOUR_DESCRIPTION_FOR_THE_TRANSFER",
    "reference": "YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER",
    "referenceForBeneficiary": "YOUR_REFERENCE_SENT_TO_BENEFICIARY",
    "counterparty": {
    "bankAccount": {
    "accountHolder": {
    "fullName": "A. Klaassen"
    },
    "accountIdentification": {
    "type": "iban",
    "iban": "NL91ABNA0417164300"
    }
    }
    }
    }'
  2. Verify that the response header contains the following fields:

    • status: 401
    • auth-param1: Base64-encoded blob of data. You will need auth-param1 when you authenticate your user.
    Response header
    Expand view
    Copy link to code block
    Copy code
    Copy code
    "WWW-Authenticate: SCA realm="Transfer" auth-param1="eyJjaGFsbGVuZ2UiOiJiVlV6ZW5wek0waFNl...""
  3. Verify that the response body contains the following fields:

    • amount: An object containing the amount and currency of the funds that will be transferred.
    • counterparty: An object containing information about the counterparty that will receive the funds.

    You must show this data to your user when you authenticate your user.

    Response for initiating a fund transfer
    Expand view
    Copy link to code block
    Copy code
    Copy code
    {
    "type": "https://docs.adyen.com/errors/unauthorized",
    "title": "Unauthorized",
    "status": 401,
    "response": {
    "amount": {
    "currency": "EUR",
    "value": 1000
    },
    "balanceAccountId": "BA00000000000000000000001",
    "category": "bank",
    "description": "YOUR_DESCRIPTION_FOR_THE_TRANSFER",
    "reference": "YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER",
    "referenceForBeneficiary": "YOUR_REFERENCE_SENT_TO_BENEFICIARY",
    "counterparty": {
    "bankAccount": {
    "accountHolder": {
    "fullName": "A. Klaassen"
    },
    "accountIdentification": {
    "type": "iban",
    "iban": "NL91ABNA0417164300"
    }
    }
    },
    },
    "errorCode": "00_401"
    }
  4. Pass auth-param1 to the SDK as sdkInput.

Authenticate user

When authenticating your user, PSD2 requires you to show to your user the amount and the counterparty (payee) of the transfer that the user is authenticating for. To comply with these regulations, we recommend that you implement a push notification and use the amount and counterparty fields from:

  • The response to the POST /transfers request you used to create the transfer.
  • The response to a GET /transfers/{id} request.

To authenticate your user with the Authentication SDK:

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

    Authenticate with SCA SDK
    Expand view
    Copy link to code block
    Copy code
    Copy code
    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
    }
    }

    If successful, the SDK generates a Base64-encoded sdkOutput data blob.

  2. Pass sdkOutput to your server.

Finalize transfer

The steps to initiate a transfer depend on whether you:

  • Authenticated the user when initiating a transfer request.
  • Authenticated the reviewer when approving a transfer request.

The following tabs explain both methods for finalizing a transfer after completing SCA.

To finalize the transfer:

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

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

    Parameter Type Description
    WWW-Authenticate Header SCA realm: Transfer.
    auth-param1: Base64-encoded value of sdkOutput you get from the Authentication SDK when you authenticate the user.
    amount Body The amount of the transfer.
    category Body Set to bank.
    description Body A human-readable description for the transfer.
    balanceAccountId Body The unique identifier of the source balance account.
    reference Body A reference of the transfer, only used internally within your balance platform.
    referenceForBeneficiary Body A reference that is sent to the recipient.
    counterparty.balanceAccountId Body The unique identifier of the target balance account.
    Finalize funds transfer
    Expand view
    Copy link to code block
    Copy code
    Copy code
    curl 'https://balanceplatform-api-test.adyen.com/btl/v4/transfers' \
    -H 'x-api-key: ADYEN_BALANCE_PLATFORM_API_KEY' \
    -H 'content-type: application/json' \
    -H 'WWW-Authenticate: SCA realm="Transfer" auth-param1="CeCcEEJf2UPC7pB0K7AtEgLZX7cTvnqNznJF...' \
    -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": {
    "bankAccount": {
    "accountHolder": {
    "fullName": "A. Klaassen"
    },
    "accountIdentification": {
    "type": "iban",
    "iban": "NL91ABNA0417164300"
    }
    }
    }
    }'
  2. Verify that the response header contains status authorised. This means that the authentication and transfer request were successful.
    The following example shows a response for a successful funds transfer.

    Finalize funds transfer response
    Expand view
    Copy link to code block
    Copy code
    Copy code
    {
    "id": "1W1UG35U8A9J5ZLG",
    "amount": {
    "currency": "EUR",
    "value": 1000
    },
    "balanceAccountId": "BA00000000000000000000001",
    "category": "bank",
    "counterparty": {
    "bankAccount": {
    "accountHolder": {
    "fullName": "A. Klaassen"
    },
    "accountIdentification": {
    "type": "iban",
    "iban": "NL91ABNA0417164300"
    }
    }
    },
    "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"
    }