Initiating Payment

Currently, the Token.io API supports payment initiation for the following transaction categories:

Each flow is covered in more detail in the topics links above. But, before delving deeperinto the payment flows, there are some general concepts with which to become familiar. Obviously, only banks supporting the transaction category (single, future-dated, recurring) requested by the user should be displayed to the user for selection after appropriate filtering of the GET /banks payload.

Additionally, in the parlance of Open Banking, "payments" are often referred to as "transfers" because the user is requesting that money be moved from one place to another. How and where it is transferred are called "beneficiary account details." Via the API, a TPP passes this information to its user's selected bank at the time of payment initiation. Money can be moved by the bank via domestic payment systems, SEPA SCT , or the cross-border payment systems supported.

Supported Payment Systems (Rails)

The following table lists the various payment systems currently supported by the Token.io API and the respective routing information required.

Beneficiary Account Details
Payment System Fields to Set Applicable Country/Area Supported by Token?
SEPA • IBAN
• BIC

Europe

Supported
SEPA Instant • IBAN
• BIC
Europe Supported
Faster Payments • Sort code
• Account number
UK Supported
Elixir Enter the IBAN in the Account number field Poland Supported
Domestic Non Euro • IBAN
• BIC
EU domestic payments systems Supported
Bankgiro • Bankgiro number Sweden In development
Plusgiro • PlusGiro number Sweden In developement

Use Cases: Which payment system to use

Some objects and fields in a payment request are common to all banks. Others are bank-dependent, like the payment system(s) supported by a bank. The information requirements imposed by different countries can vary, as well. In general, however, there are two primary use cases for A2A payment initiation: domestic payments and cross-border payments, although even here certain nuances may apply.

A domestic payment transfers money from a payer's bank account to the recipient's bank account within the same country. Interbank transfers within the same country can use one or more domestic payment systems operated and administered within that country, depending on the type and volume of the transaction. For instance, FPS is a domestic payment system in the UK, as seen in the Beneficiary Accounts table above. Elixir is a domestic payment systems in Poland; Bankgiro and Plusgiro are the domestic payment systems in Sweden; and so forth.

Cross-border payments happen when the payee and the recipient are in different countries. However, with the advent of the single euro payments market, SEPA makes it possible for retail transactions to directly debit accounts in another SEPA member country, as well as to receive direct deposit payments and pay bills by electronic transfer from another member country, but only for euro-denominated transactions. SEPA is ruled out as a payment method when a non-euro currency is involved on either side (or both sides) of the transaction, even between SEPA member countries.

To help you in determining the appropriate payment method/system to use in a payment request, let's explore a number of general use cases for single immediate payment and what the minimally required request payload looks like for each. Other cases can then be extrapolated and modelled based on these examples.

Send EUR from EU to UK

This entails a cross-border interbank transfer in which the payer's bank is located in an EU member country and the payee's bank is in the UK. We will assume that the bank has already been selected by the user and the currency is EUR.

Based on these assumptions, the TPP handling this transfer will need to specify, at minimum, the following information in its API request payload:

  • a unique TPP-generated reference identifier (refId), identifying the request
  • the TPP to whom the money is being paid, identified by its Token member ID
  • the payment details
    • currency
    • amount
    • execution date (required only if you want the transfer to take place in the future, rather than immediately)
    • destination – the beneficiary account details: SEPA, and the legal name of the payee/creditor
  • a description of the payment – an identifier that will be used for reconciliation when funds are cleared within beneficiary’s account
  • a redirect URL – address where the TPP wants its user redirected after authentication and consent
  • any information required by the bank in mandatoryFields when the source bank is selected by the user. These fields are entirely bank-dependent. See Mandatory Fields under Bank Selection for details.

You can provide more information for traceability and reconciliation in accordance with your business practices (see Swagger Object and Field Definitions for the complete set of options), but the list above contains the essentials. In our payload example, we will omit any providerTransferMetadata the bank may or may not require. These metadata are based on the API standard adopted by the particular bank — CMA9, NextGenPSD2, PolishAPI, or STET — and typically contain debtor/creditor identifiers and regulatory reporting codes for international payments.

The payment rail (transfer method) can be SEPA, which requires the payee's IBAN and a BIC.

Given the preceding assumptions, here's the minimally required token request payload we'll need to construct:

{

    "requestPayload":

        "refId": "xyztyuberty", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq" // Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "EUR",

            "lifetimeAmount": "500",

            "transferInstructions": {

                "transferDestinations": {

                     "sepa": {

                         "account": "GB29 NWBK 6016 1331 9268 19", // payee's IBAN

                         "bic": "LOYDGB2LXXX"// payee's BIC code

                     }

                }

            }

        },

        "description": "Airfare to EU",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

The response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of your request payload, confirming its details.

Send EUR from UK to EU

A user in the UK wants to make a payment somewhere in the EU. This is the reverse of the previous use case. In this one, we'll request a cross-border interbank transfer in which the payer's bank is located in the UK and the payee's bank is in an EU member country. Again, we will assume that the bank has already been selected by the user.

If we also apply the other assumptions we made in the previous use case, the request payload will look like this:

{

    "requestPayload":

        "refId": "ytrebuytzyx", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq" // Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "EUR",

            "lifetimeAmount": "500",

            "transferInstructions": {

                "transferDestinations": {

                     "sepa": {

                         "account": "FR14 2004 1010 0505 0001 3M02 606", // payee's IBAN

                         "bic": "XYZDDGTYXXX"// payee's BIC code

                     }

                }

            }

        },

        "description": "Airfare to UK",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

The response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of the request payload received, confirming its details.

Send GBP from UK to EU

In this case, we're making a transfer from the UK to somewhere in the EU. The source currency is GBP. For purposes of this example, we'll assume the destination currency is EUR. If payment is expected in a non-euro currency, that currency should be specified in the transferBody. The bank will handle the FX.

{

    "requestPayload":

        "refId": "bbbcccxyz", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq"// Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "GBP",

            "lifetimeAmount": "428.21",

            "transferInstructions": {

                "transferDestinations": {

                     "bic": {

                         "account": "FR14 2004 1010 0505 0001 3M02 606", // payee's IBAN

                         "bic": "XYZDDGTYXXX"// payee's BIC code

                     }

                }

            }

        },

        "description": "Online purchase",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

Once again, the response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of the request payload received, confirming its details.

Send EUR from EU to EU

This case initiates an interbank transfer between banks both located within the EU. If both banks support SEPA Instant (sometimes called SCT Inst) and this is an urgent SIP, sepaInstant should be specified as the payment rail. If either the sending or receiving bank doesn't support SCT Inst, you'll need to specify standard sepa. Here's a request payload example:

{

    "requestPayload":

        "refId": "lkjhgffds", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq"// Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "EUR",

            "lifetimeAmount": "500",

            "transferInstructions": {

                "transferDestinations": {

                     "sepa": {

                         "iban": "FR14 2004 1010 0505 0001 3M02 606", // payee's IBAN

                         "bic": "XYZDDGTYXXX"// payee's BIC code

                     }

                }

            }

        },

        "description": "Online purchase",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

As in the previous examples, the response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of the request payload received, confirming its details.

Send GBP from UK to UK

Here, we're initiating an interbank transfer between banks which are both located in the UK. If this is an urgent SIP, you'll want to use Faster Payments (fasterPayments).

{

    "requestPayload":

        "refId": "bksrtywer", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq"// Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "GBP",

            "lifetimeAmount": "100.00",

            "transferInstructions": {

                "transferDestinations": {

                     "fasterPayments": {

                         "accountNumber": "555555555", // payee's IBAN

                         "sortCode": "200415"// payee's BIC code

                     }

                }

            }

        },

        "description": "Online purchase",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

Yet again, as in the previous examples, the response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of the request payload received, confirming its details.

Restricting Beneficiary Accounts

 

The transfer destinations designated in your PIS calls can be manually added to the dashboard.

Please contact Support to use this feature.

 

Transfer destinations are typically TPP-controlled accounts administered for appropriate funds distribution according to the governing regulations where the TPP is licensed. In all cases, for proper payment request initiation, execution, and funds transfer to the correct beneficiary account(s), take the following steps:

  1. Sign in to the Dashboard and select Beneficiary under Settings.
    The List of Accounts is displayed; initially, your list will be empty until you make some entries. Here you can Add, Modify and Delete accounts.
  2. Add an account by clicking the Add button, then enter the required information: Account Name, Currency, Country, Account Type, and IBAN. BIC is optional.
  3. Click Save to add the information.

Once saved, beneficiary accounts in the list are available as transfer destinations for the payments you initiate by specifying the Account Number/IBAN and optional BIC, as appropriate.

Source Account Validation

The requirement to specify the source account for a transfer is bank-dependent, based on the API standard adopted by the bank and whether the bank supports 1-step or 2-step payment. When required, the instructions.source object specifies the user's bank account from which the payment amount is being debited, and it is set using an accountIdentifier object, which allows the following types of identifiers:

  • Token, for linked accounts
  • iban – IBAN
  • bban – BBAN
  • gbDomestic – 8-digit bank account number in the UK;  also requires the sort_code
  • bankgiro – identifier for domestic bank accounts in Sweden
  • plusgiro – identifier for domestic transaction clearing system in Sweden
  • msisdn – mobile station international subscriber director number is basically the user's mobile phone number; used as a unique identity to enable routing of voice and SMS traffic to and from a specific subscription/ device on a wireless/mobile network

In EU countries that don't use the euro as their domestic currency, iban should be used for domestic source accounts, with the exception of Sweden. For Swedish domestic, the accountIdentifier can be either bankgiro or plusgiro. Specify a plusgiroNumber for the plusgiro payment rail. If the payment rail is bankgiro, provide a bankgiroNumber.

In addition to the Token Platform's bankId and the bank's bic (BIC), the source also contains a customerData object identifying the payer's legalNames and address (see Swagger Object and Field Definitions for complete object-field specifications).

In accordance with the following rules, Token verifies the source in token requests to avoid preventable account identification errors during payment processing:

  1. If a transfer token request has a non-empty source object, it must also have a populated accountIdentifier. Populating customerData.legalNames without identifying the bank account, for example, will throw an InvalidArgument "Missing required field bank_account or account_identifier in source account" error.

  2. If the accountIdentifier object is populated, it must also have a populated identifier type; otherwise, an InvalidArgument "Missing required field<field name>in source account" error will result. Here, field name depends on the identifier type. For most types — bban, iban, msisdn, bankgiro, and plusgiro — only one field is mandatory. However, gbDomestic requires both accountNumber and sortCode.

  3. The bankAccount cases, when supported by the source bank, that cannot be mapped to an accountIdentifier type and are therefore excluded from the source validation check comprise CUSTOM, BANK, GUEST, SWIFT, ACH, TOKEN_AUTHORIZATION, and SECRET.

Populating the source object is required for one-step payment; optional for two-step payment.

Initiating Payment

Currently, the Token.io API supports payment initiation for the following transaction categories:

Each flow is covered in more detail in the topics links above. But, before delving deeperinto the payment flows, there are some general concepts with which to become familiar. Obviously, only banks supporting the transaction category (single, future-dated, recurring) requested by the user should be displayed to the user for selection after appropriate filtering of the GET /banks payload.

Additionally, in the parlance of Open Banking, "payments" are often referred to as "transfers" because the user is requesting that money be moved from one place to another. How and where it is transferred are called "beneficiary account details." Via the API, a TPP passes this information to its user's selected bank at the time of payment initiation. Money can be moved by the bank via domestic payment systems, SEPA SCT , or the cross-border payment systems supported.

Supported Payment Systems (Rails)

The following table lists the various payment systems currently supported by the Token.io API and the respective routing information required.

Beneficiary Account Details
Payment System Fields to Set Applicable Country/Area Supported by Token?
SEPA • IBAN
• BIC

Europe

Supported
SEPA Instant • IBAN
• BIC
Europe Supported
Faster Payments • Sort code
• Account number
UK Supported
Elixir Enter the IBAN in the Account number field Poland Supported
Domestic Non Euro • IBAN
• BIC
EU domestic payments systems Supported
Bankgiro • Bankgiro number Sweden In development
Plusgiro • PlusGiro number Sweden In developement

Use Cases: Which payment system to use

Some objects and fields in a payment request are common to all banks. Others are bank-dependent, like the payment system(s) supported by a bank. The information requirements imposed by different countries can vary, as well. In general, however, there are two primary use cases for A2A payment initiation: domestic payments and cross-border payments, although even here certain nuances may apply.

A domestic payment transfers money from a payer's bank account to the recipient's bank account within the same country. Interbank transfers within the same country can use one or more domestic payment systems operated and administered within that country, depending on the type and volume of the transaction. For instance, FPS is a domestic payment system in the UK, as seen in the Beneficiary Accounts table above. Elixir is a domestic payment systems in Poland; Bankgiro and Plusgiro are the domestic payment systems in Sweden; and so forth.

Cross-border payments happen when the payee and the recipient are in different countries. However, with the advent of the single euro payments market, SEPA makes it possible for retail transactions to directly debit accounts in another SEPA member country, as well as to receive direct deposit payments and pay bills by electronic transfer from another member country, but only for euro-denominated transactions. SEPA is ruled out as a payment method when a non-euro currency is involved on either side (or both sides) of the transaction, even between SEPA member countries.

To help you in determining the appropriate payment method/system to use in a payment request, let's explore a number of general use cases for single immediate payment and what the minimally required request payload looks like for each. Other cases can then be extrapolated and modelled based on these examples.

Send EUR from EU to UK

This entails a cross-border interbank transfer in which the payer's bank is located in an EU member country and the payee's bank is in the UK. We will assume that the bank has already been selected by the user and the currency is EUR.

Based on these assumptions, the TPP handling this transfer will need to specify, at minimum, the following information in its API request payload:

  • a unique TPP-generated reference identifier (refId), identifying the request
  • the TPP to whom the money is being paid, identified by its Token member ID
  • the payment details
    • currency
    • amount
    • execution date (required only if you want the transfer to take place in the future, rather than immediately)
    • destination – the beneficiary account details: SEPA, and the legal name of the payee/creditor
  • a description of the payment – an identifier that will be used for reconciliation when funds are cleared within beneficiary’s account
  • a redirect URL – address where the TPP wants its user redirected after authentication and consent
  • any information required by the bank in mandatoryFields when the source bank is selected by the user. These fields are entirely bank-dependent. See Mandatory Fields under Bank Selection for details.

You can provide more information for traceability and reconciliation in accordance with your business practices (see Swagger Object and Field Definitions for the complete set of options), but the list above contains the essentials. In our payload example, we will omit any providerTransferMetadata the bank may or may not require. These metadata are based on the API standard adopted by the particular bank — CMA9, NextGenPSD2, PolishAPI, or STET — and typically contain debtor/creditor identifiers and regulatory reporting codes for international payments.

The payment rail (transfer method) can be SEPA, which requires the payee's IBAN and a BIC.

Given the preceding assumptions, here's the minimally required token request payload we'll need to construct:

{

    "requestPayload":

        "refId": "xyztyuberty", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq" // Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "EUR",

            "lifetimeAmount": "500",

            "transferInstructions": {

                "transferDestinations": {

                     "sepa": {

                         "account": "GB29 NWBK 6016 1331 9268 19", // payee's IBAN

                         "bic": "LOYDGB2LXXX"// payee's BIC code

                     }

                }

            }

        },

        "description": "Airfare to EU",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

The response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of your request payload, confirming its details.

Send EUR from UK to EU

A user in the UK wants to make a payment somewhere in the EU. This is the reverse of the previous use case. In this one, we'll request a cross-border interbank transfer in which the payer's bank is located in the UK and the payee's bank is in an EU member country. Again, we will assume that the bank has already been selected by the user.

If we also apply the other assumptions we made in the previous use case, the request payload will look like this:

{

    "requestPayload":

        "refId": "ytrebuytzyx", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq" // Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "EUR",

            "lifetimeAmount": "500",

            "transferInstructions": {

                "transferDestinations": {

                     "sepa": {

                         "account": "FR14 2004 1010 0505 0001 3M02 606", // payee's IBAN

                         "bic": "XYZDDGTYXXX"// payee's BIC code

                     }

                }

            }

        },

        "description": "Airfare to UK",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

The response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of the request payload received, confirming its details.

Send GBP from UK to EU

In this case, we're making a transfer from the UK to somewhere in the EU. The source currency is GBP. For purposes of this example, we'll assume the destination currency is EUR. If payment is expected in a non-euro currency, that currency should be specified in the transferBody. The bank will handle the FX.

{

    "requestPayload":

        "refId": "bbbcccxyz", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq"// Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "GBP",

            "lifetimeAmount": "428.21",

            "transferInstructions": {

                "transferDestinations": {

                     "bic": {

                         "account": "FR14 2004 1010 0505 0001 3M02 606", // payee's IBAN

                         "bic": "XYZDDGTYXXX"// payee's BIC code

                     }

                }

            }

        },

        "description": "Online purchase",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

Once again, the response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of the request payload received, confirming its details.

Send EUR from EU to EU

This case initiates an interbank transfer between banks both located within the EU. If both banks support SEPA Instant (sometimes called SCT Inst) and this is an urgent SIP, sepaInstant should be specified as the payment rail. If either the sending or receiving bank doesn't support SCT Inst, you'll need to specify standard sepa. Here's a request payload example:

{

    "requestPayload":

        "refId": "lkjhgffds", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq"// Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "EUR",

            "lifetimeAmount": "500",

            "transferInstructions": {

                "transferDestinations": {

                     "sepa": {

                         "iban": "FR14 2004 1010 0505 0001 3M02 606", // payee's IBAN

                         "bic": "XYZDDGTYXXX"// payee's BIC code

                     }

                }

            }

        },

        "description": "Online purchase",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

As in the previous examples, the response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of the request payload received, confirming its details.

Send GBP from UK to UK

Here, we're initiating an interbank transfer between banks which are both located in the UK. If this is an urgent SIP, you'll want to use Faster Payments (fasterPayments).

{

    "requestPayload":

        "refId": "bksrtywer", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq"// Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "GBP",

            "lifetimeAmount": "100.00",

            "transferInstructions": {

                "transferDestinations": {

                     "fasterPayments": {

                         "accountNumber": "555555555", // payee's IBAN

                         "sortCode": "200415"// payee's BIC code

                     }

                }

            }

        },

        "description": "Online purchase",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

Yet again, as in the previous examples, the response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of the request payload received, confirming its details.

Restricting Beneficiary Accounts

 

The transfer destinations designated in your PIS calls can be manually added to the dashboard.

Please contact Support to use this feature.

 

Transfer destinations are typically TPP-controlled accounts administered for appropriate funds distribution according to the governing regulations where the TPP is licensed. In all cases, for proper payment request initiation, execution, and funds transfer to the correct beneficiary account(s), take the following steps:

  1. Sign in to the Dashboard and select Beneficiary under Settings.
    The List of Accounts is displayed; initially, your list will be empty until you make some entries. Here you can Add, Modify and Delete accounts.
  2. Add an account by clicking the Add button, then enter the required information: Account Name, Currency, Country, Account Type, and IBAN. BIC is optional.
  3. Click Save to add the information.

Once saved, beneficiary accounts in the list are available as transfer destinations for the payments you initiate by specifying the Account Number/IBAN and optional BIC, as appropriate.

Source Account Validation

The requirement to specify the source account for a transfer is bank-dependent, based on the API standard adopted by the bank and whether the bank supports 1-step or 2-step payment. When required, the instructions.source object specifies the user's bank account from which the payment amount is being debited, and it is set using an accountIdentifier object, which allows the following types of identifiers:

  • Token, for linked accounts
  • iban – IBAN
  • bban – BBAN
  • gbDomestic – 8-digit bank account number in the UK;  also requires the sort_code
  • bankgiro – identifier for domestic bank accounts in Sweden
  • plusgiro – identifier for domestic transaction clearing system in Sweden
  • msisdn – mobile station international subscriber director number is basically the user's mobile phone number; used as a unique identity to enable routing of voice and SMS traffic to and from a specific subscription/ device on a wireless/mobile network

In EU countries that don't use the euro as their domestic currency, iban should be used for domestic source accounts, with the exception of Sweden. For Swedish domestic, the accountIdentifier can be either bankgiro or plusgiro. Specify a plusgiroNumber for the plusgiro payment rail. If the payment rail is bankgiro, provide a bankgiroNumber.

In addition to the Token Platform's bankId and the bank's bic (BIC), the source also contains a customerData object identifying the payer's legalNames and address (see Swagger Object and Field Definitions for complete object-field specifications).

In accordance with the following rules, Token verifies the source in token requests to avoid preventable account identification errors during payment processing:

  1. If a transfer token request has a non-empty source object, it must also have a populated accountIdentifier. Populating customerData.legalNames without identifying the bank account, for example, will throw an InvalidArgument "Missing required field bank_account or account_identifier in source account" error.

  2. If the accountIdentifier object is populated, it must also have a populated identifier type; otherwise, an InvalidArgument "Missing required field<field name>in source account" error will result. Here, field name depends on the identifier type. For most types — bban, iban, msisdn, bankgiro, and plusgiro — only one field is mandatory. However, gbDomestic requires both accountNumber and sortCode.

  3. The bankAccount cases, when supported by the source bank, that cannot be mapped to an accountIdentifier type and are therefore excluded from the source validation check comprise CUSTOM, BANK, GUEST, SWIFT, ACH, TOKEN_AUTHORIZATION, and SECRET.

Populating the source object is required for one-step payment; optional for two-step payment.

Initiating Payment

Currently, the Token.io API supports payment initiation for the following transaction categories:

Each flow is covered in more detail in the topics links above. But, before delving deeperinto the payment flows, there are some general concepts with which to become familiar. Obviously, only banks supporting the transaction category (single, future-dated, recurring) requested by the user should be displayed to the user for selection after appropriate filtering of the GET /banks payload.

Additionally, in the parlance of Open Banking, "payments" are often referred to as "transfers" because the user is requesting that money be moved from one place to another. How and where it is transferred are called "beneficiary account details." Via the API, a TPP passes this information to its user's selected bank at the time of payment initiation. Money can be moved by the bank via domestic payment systems, SEPA SCT , or the cross-border payment systems supported.

Supported Payment Systems (Rails)

The following table lists the various payment systems currently supported by the Token.io API and the respective routing information required.

Beneficiary Account Details
Payment System Fields to Set Applicable Country/Area Supported by Token?
SEPA • IBAN
• BIC

Europe

Supported
SEPA Instant • IBAN
• BIC
Europe Supported
Faster Payments • Sort code
• Account number
UK Supported
Elixir Enter the IBAN in the Account number field Poland Supported
Domestic Non Euro • IBAN
• BIC
EU domestic payments systems Supported
Bankgiro • Bankgiro number Sweden In development
Plusgiro • PlusGiro number Sweden In developement

Use Cases: Which payment system to use

Some objects and fields in a payment request are common to all banks. Others are bank-dependent, like the payment system(s) supported by a bank. The information requirements imposed by different countries can vary, as well. In general, however, there are two primary use cases for A2A payment initiation: domestic payments and cross-border payments, although even here certain nuances may apply.

A domestic payment transfers money from a payer's bank account to the recipient's bank account within the same country. Interbank transfers within the same country can use one or more domestic payment systems operated and administered within that country, depending on the type and volume of the transaction. For instance, FPS is a domestic payment system in the UK, as seen in the Beneficiary Accounts table above. Elixir is a domestic payment systems in Poland; Bankgiro and Plusgiro are the domestic payment systems in Sweden; and so forth.

Cross-border payments happen when the payee and the recipient are in different countries. However, with the advent of the single euro payments market, SEPA makes it possible for retail transactions to directly debit accounts in another SEPA member country, as well as to receive direct deposit payments and pay bills by electronic transfer from another member country, but only for euro-denominated transactions. SEPA is ruled out as a payment method when a non-euro currency is involved on either side (or both sides) of the transaction, even between SEPA member countries.

To help you in determining the appropriate payment method/system to use in a payment request, let's explore a number of general use cases for single immediate payment and what the minimally required request payload looks like for each. Other cases can then be extrapolated and modelled based on these examples.

Send EUR from EU to UK

This entails a cross-border interbank transfer in which the payer's bank is located in an EU member country and the payee's bank is in the UK. We will assume that the bank has already been selected by the user and the currency is EUR.

Based on these assumptions, the TPP handling this transfer will need to specify, at minimum, the following information in its API request payload:

  • a unique TPP-generated reference identifier (refId), identifying the request
  • the TPP to whom the money is being paid, identified by its Token member ID
  • the payment details
    • currency
    • amount
    • execution date (required only if you want the transfer to take place in the future, rather than immediately)
    • destination – the beneficiary account details: SEPA, and the legal name of the payee/creditor
  • a description of the payment – an identifier that will be used for reconciliation when funds are cleared within beneficiary’s account
  • a redirect URL – address where the TPP wants its user redirected after authentication and consent
  • any information required by the bank in mandatoryFields when the source bank is selected by the user. These fields are entirely bank-dependent. See Mandatory Fields under Bank Selection for details.

You can provide more information for traceability and reconciliation in accordance with your business practices (see Swagger Object and Field Definitions for the complete set of options), but the list above contains the essentials. In our payload example, we will omit any providerTransferMetadata the bank may or may not require. These metadata are based on the API standard adopted by the particular bank — CMA9, NextGenPSD2, PolishAPI, or STET — and typically contain debtor/creditor identifiers and regulatory reporting codes for international payments.

The payment rail (transfer method) can be SEPA, which requires the payee's IBAN and a BIC.

Given the preceding assumptions, here's the minimally required token request payload we'll need to construct:

{

    "requestPayload":

        "refId": "xyztyuberty", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq" // Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "EUR",

            "lifetimeAmount": "500",

            "transferInstructions": {

                "transferDestinations": {

                     "sepa": {

                         "account": "GB29 NWBK 6016 1331 9268 19", // payee's IBAN

                         "bic": "LOYDGB2LXXX"// payee's BIC code

                     }

                }

            }

        },

        "description": "Airfare to EU",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

The response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of your request payload, confirming its details.

Send EUR from UK to EU

A user in the UK wants to make a payment somewhere in the EU. This is the reverse of the previous use case. In this one, we'll request a cross-border interbank transfer in which the payer's bank is located in the UK and the payee's bank is in an EU member country. Again, we will assume that the bank has already been selected by the user.

If we also apply the other assumptions we made in the previous use case, the request payload will look like this:

{

    "requestPayload":

        "refId": "ytrebuytzyx", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq" // Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "EUR",

            "lifetimeAmount": "500",

            "transferInstructions": {

                "transferDestinations": {

                     "sepa": {

                         "account": "FR14 2004 1010 0505 0001 3M02 606", // payee's IBAN

                         "bic": "XYZDDGTYXXX"// payee's BIC code

                     }

                }

            }

        },

        "description": "Airfare to UK",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

The response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of the request payload received, confirming its details.

Send GBP from UK to EU

In this case, we're making a transfer from the UK to somewhere in the EU. The source currency is GBP. For purposes of this example, we'll assume the destination currency is EUR. If payment is expected in a non-euro currency, that currency should be specified in the transferBody. The bank will handle the FX.

{

    "requestPayload":

        "refId": "bbbcccxyz", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq"// Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "GBP",

            "lifetimeAmount": "428.21",

            "transferInstructions": {

                "transferDestinations": {

                     "bic": {

                         "account": "FR14 2004 1010 0505 0001 3M02 606", // payee's IBAN

                         "bic": "XYZDDGTYXXX"// payee's BIC code

                     }

                }

            }

        },

        "description": "Online purchase",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

Once again, the response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of the request payload received, confirming its details.

Send EUR from EU to EU

This case initiates an interbank transfer between banks both located within the EU. If both banks support SEPA Instant (sometimes called SCT Inst) and this is an urgent SIP, sepaInstant should be specified as the payment rail. If either the sending or receiving bank doesn't support SCT Inst, you'll need to specify standard sepa. Here's a request payload example:

{

    "requestPayload":

        "refId": "lkjhgffds", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq"// Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "EUR",

            "lifetimeAmount": "500",

            "transferInstructions": {

                "transferDestinations": {

                     "sepa": {

                         "iban": "FR14 2004 1010 0505 0001 3M02 606", // payee's IBAN

                         "bic": "XYZDDGTYXXX"// payee's BIC code

                     }

                }

            }

        },

        "description": "Online purchase",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

As in the previous examples, the response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of the request payload received, confirming its details.

Send GBP from UK to UK

Here, we're initiating an interbank transfer between banks which are both located in the UK. If this is an urgent SIP, you'll want to use Faster Payments (fasterPayments).

{

    "requestPayload":

        "refId": "bksrtywer", // TPP-generated reference ID

        "to": {

            "id": "m:nP4w3u5y8ddrxDJkjimgSX9e4fZ:5zKtXEAq"// Member ID of the TPP initiating the request

        },

        "transferBody": {

            "currency": "GBP",

            "lifetimeAmount": "100.00",

            "transferInstructions": {

                "transferDestinations": {

                     "fasterPayments": {

                         "accountNumber": "555555555", // payee's IBAN

                         "sortCode": "200415"// payee's BIC code

                     }

                }

            }

        },

        "description": "Online purchase",

        "redirectUrl": "https://sample-merchant-domain.com/transfer"

    }

}

Yet again, as in the previous examples, the response payload from the bank via Token for a successful request will contain a request id that uniquely identifies this transfer request, along with a duplicate of the request payload received, confirming its details.

Restricting Beneficiary Accounts

 

The transfer destinations designated in your PIS calls can be manually added to the dashboard.

Please contact Support to use this feature.

 

Transfer destinations are typically TPP-controlled accounts administered for appropriate funds distribution according to the governing regulations where the TPP is licensed. In all cases, for proper payment request initiation, execution, and funds transfer to the correct beneficiary account(s), take the following steps:

  1. Sign in to the Dashboard and select Beneficiary under Settings.
    The List of Accounts is displayed; initially, your list will be empty until you make some entries. Here you can Add, Modify and Delete accounts.
  2. Add an account by clicking the Add button, then enter the required information: Account Name, Currency, Country, Account Type, and IBAN. BIC is optional.
  3. Click Save to add the information.

Once saved, beneficiary accounts in the list are available as transfer destinations for the payments you initiate by specifying the Account Number/IBAN and optional BIC, as appropriate.

Source Account Validation

The requirement to specify the source account for a transfer is bank-dependent, based on the API standard adopted by the bank and whether the bank supports 1-step or 2-step payment. When required, the instructions.source object specifies the user's bank account from which the payment amount is being debited, and it is set using an accountIdentifier object, which allows the following types of identifiers:

  • Token, for linked accounts
  • iban – IBAN
  • bban – BBAN
  • gbDomestic – 8-digit bank account number in the UK;  also requires the sort_code
  • bankgiro – identifier for domestic bank accounts in Sweden
  • plusgiro – identifier for domestic transaction clearing system in Sweden
  • msisdn – mobile station international subscriber director number is basically the user's mobile phone number; used as a unique identity to enable routing of voice and SMS traffic to and from a specific subscription/ device on a wireless/mobile network

In EU countries that don't use the euro as their domestic currency, iban should be used for domestic source accounts, with the exception of Sweden. For Swedish domestic, the accountIdentifier can be either bankgiro or plusgiro. Specify a plusgiroNumber for the plusgiro payment rail. If the payment rail is bankgiro, provide a bankgiroNumber.

In addition to the Token Platform's bankId and the bank's bic (BIC), the source also contains a customerData object identifying the payer's legalNames and address (see Swagger Object and Field Definitions for complete object-field specifications).

In accordance with the following rules, Token verifies the source in token requests to avoid preventable account identification errors during payment processing:

  1. If a transfer token request has a non-empty source object, it must also have a populated accountIdentifier. Populating customerData.legalNames without identifying the bank account, for example, will throw an InvalidArgument "Missing required field bank_account or account_identifier in source account" error.

  2. If the accountIdentifier object is populated, it must also have a populated identifier type; otherwise, an InvalidArgument "Missing required field<field name>in source account" error will result. Here, field name depends on the identifier type. For most types — bban, iban, msisdn, bankgiro, and plusgiro — only one field is mandatory. However, gbDomestic requires both accountNumber and sortCode.

  3. The bankAccount cases, when supported by the source bank, that cannot be mapped to an accountIdentifier type and are therefore excluded from the source validation check comprise CUSTOM, BANK, GUEST, SWIFT, ACH, TOKEN_AUTHORIZATION, and SECRET.

Populating the source object is required for one-step payment; optional for two-step payment.

 

 

© 2023 TOKEN, INC.     ALL RIGHTS RESERVED.