Each time a user in the European Economic Area (EEA) wants to transfer funds, you must authenticate them using SCA. To do so:
- Check SCA eligibility.
- Initiate the transfer using the
sdkOutput
that you got when you checked the device for SCA eligibility. - Authenticate your user with the Authentication SDK.
- Finalize the transfer using the
sdkOutput
from the authentication step.
Requirements
- Make sure that you have installed the Authentication SDK.
Make sure that you have registered a device for your user. - Make sure that your API credential has the following role:
- TransferService Webservice Initiate role
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:
-
Initiate the
AdyenAuthentication
class in your Activity or Fragment.Initiate authenticationExpand viewCopy link to code blockCopy codeprivate lateinit var adyenAuthentication: AdyenAuthentication override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) adyenAuthentication = AdyenAuthentication(this) } -
Check if SCA is available on the device.
Check SCA eligibilityExpand viewCopy link to code blockCopy codelifecycleScope.launch { val availabilityResult: AvailabilityResult = adyenAuthentication.checkAvailability() if (availabilityResult is AvailabilityResult.Available) { availabilityResult.sdkOutput } } The function returns an
sdkOutput
. -
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:
-
Make a POST /transfers request, specifying the following parameters:
Parameter Type Required Description WWW-Authenticate Header SCA realm
: Transfer.auth-param1
: Base64-encoded value of sdkOutput you get when you initiate authentication.amount Body The amount of the transfer. balanceAccountId Body The unique identifier of the source balance account. category Body Set to bank. counterparty.bankAccount Body 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 SCAExpand viewCopy link to code blockCopy codecurl 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" } } } }' -
Verify that the response header contains the following fields:
status
: 401auth-param1
: Base64-encoded blob of data. You will needauth-param1
when you authenticate your user.
Response headerExpand viewCopy link to code blockCopy code"WWW-Authenticate: SCA realm="Transfer" auth-param1="eyJjaGFsbGVuZ2UiOiJiVlV6ZW5wek0waFNl...""
-
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 transferExpand viewCopy link to code blockCopy 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" } -
Pass
auth-param1
to the SDK assdkInput
.
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:
-
Trigger the SDK to start user authentication and pass the
auth-param1
value from the previous step assdkInput
.Authenticate with SCA SDKExpand viewCopy link to code blockCopy codelifecycleScope.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. -
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:
-
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 transferExpand viewCopy link to code blockCopy codecurl '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" } } } }' -
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 responseExpand viewCopy link to code blockCopy 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" }