Overview
This document provides comprehensive information about integrating the AFT feature into the Paynetics Acquiring product and it is providing requirements for partners using our payment page. It includes functional details, integration requirements, and use case scenarios to assist partners and merchants in implementing AFTs in compliance with Visa regulations. Mastercard transactions are out of scope currently. The requirements below are only applicable for Visa.
Product Description
Merchant and AFT types
What is AFT?
Account Funding Transactions (AFTs) involve transferring funds from a Visa account to another Visa or non-Visa account. These transactions are typically used for:
Account Top-Ups: Funding digital wallets via linked payment cards or bank accounts.
Prepaid Card Load/Reload: Adding funds to prepaid cards owned by the same individual/entity.
Person-to-Person Transfers (P2P): Funding accounts for P2P transfers.
Account-to-Account Transfers (A2A): Moving funds between personal accounts.
Purchase of Liquid and Cryptocurrency Assets.
Out of Scope
The following are out of the current project scope:
Mastercard transactions will be included in the scope later this year starting from August 2025 per mandate.
Pre-authorization and capture transactions.
MCC in scope
The objective of this integration is to:
Replace standard purchase transactions with AFTs for specific MCCs (6051, 6211, 6012, and conditional for 6540, 4829) as per Visa's requirements.
Comply with Visa mandates, including additional information submission for cross-border transactions.
Recipient currency and country coverage
The supported settlement currencies are EUR , USD and GBP. There are no specific restrictions for processing currencies. No change in the current support of countries.
Money flow
The same as purchase transaction
Merchant Onboarding
All merchants are subjected to approval by Visa for AFT to be enabled. This may cause delays in the onboarding process, which are outside of Paynetic's control.
Manual onboarding
AFTs require assigning a Business Application Identifier (BAI) to a merchant based on its business model. Paynetics will define the correct BAI by the merchant onboarding depending on the business case of the merchant. The BAI must be submitted by the partner in the transaction message, and the partner will carry the responsibility to submit the correct BAI.
Fees set-up
This transaction type will have different interchange fees depending on the business case (the business cases must be indicated with a new attribute in the transaction message – BAI). The interchange fees for AFT are in general higher than the ones for standard purchase transactions.
Reporting and reconciliation
No changes in the current reporting and reconciliation.
Profit share
No changes
Technical Integration
Once you have implemented the changes, you will run a set of tests validated by Paynetics and you will be ready to move to production.
Executing AFT
The execute an AFT use POST /v1/{operation}/page endpoint of the Acquiring API. Access to the Acquiring API swagger is private. It will be provided to you upon request. Note that the attributes required differ depending on the country and if the transactions are considered as domestic or cross-border. Currently domestic transactions are only these where the merchant is operating in Bulgaria and the issuing country of the card is Bulgaria. In general, domestic transactions for AFT are these where the country of registration of the acquirer, the merchant and card issued are the same.
Fields:
Field Name | Description | Condition | Format |
account_owner_address1 | Account owner street and number | Mandatory for cross-border transactions originating from or destined to Canada | maximum 99 Bytes, EBCDIC alphanumeric with special characters |
account_owner_address2 | Account owner additional street and number | Mandatory for cross-border transactions originating from or destined to Canada | maximum 99 Bytes, EBCDIC alphanumeric with special characters |
account_owner_street | Account owner street | Mandatory for cross-border transactions originating from or destined to Canada | variable length, max. 50 characters, alphanumeric and special characters, EBCDIC. If present, cannot contain all spaces or all numeric values. |
account_owner_postal_code | Account owner postal code | Mandatory for cross-border transactions originating from or destined to Canada | maximum 16 Bytes, EBCDIC alphanumeric with special characters |
account_owner_city | Account owner city | Mandatory for cross-border transactions originating from or destined to Canada | variable length, max. 25 characters, alphanumeric and special characters, EBCDIC. If present, cannot contain all spaces or all numeric values |
account_owner_subdivision_code | Account owner state | Mandatory for cross-border transactions originating from or destined to US or Canada | variable length, max. 2 characters, alphanumeric, EBCDIC. If present, cannot contain all spaces or all numeric values. |
account_owner_country | Account owner country | Mandatory for cross-border transactions originating from or destined to Canada | variable length, 3 characters, alphanumeric, EBCDIC. If present, cannot contain all spaces or all numeric values. |
merchant_postal_code | Merchant postal code | Mandatory for cross-border AFTs destined to Australia | LLLVARans.8 fixed length (2 bytes EBCDIC) |
merchant_state | Merchant state | Mandatory for cross-border AFTs destined to Australia | LLLVARans.3 fixed length (2 bytes EBCDIC) |
acceptor_legal_name | Full acceptor legal business name required | Optional for Domestic Money and Non-Money Transfer transactions. | maximum 25 Bytes, EBCDIC alphanumeric with special characters |
sender_address | Sender address street and number | Optional for Domestic Money and Non-Money Transfer AFTs. | variable length, max. 35 characters, alphanumeric and special characters, EBCDIC. If present, cannot contain all spaces or all numeric values |
sender_city | Sender city | Optional for Domestic Money and Non-Money Transfer AFTs. | variable length, max. 25 characters, alphanumeric and special characters, EBCDIC. If present, cannot contain all spaces or all numeric values. |
sender_state | Sender state | Optional for Domestic Money and Non-Money Transfer AFTs and Cross-Border with the exclusion of Canada and US, where for these 2 countries is mandatory. | variable length, max. 2 characters, alphanumeric, EBCDIC. If present, cannot contain all spaces or all numeric values. |
sender_country | Issuing country code. | Optional for Domestic Money and Non-Money Transfer AFTs. | ISO 3166-1 alpha-3, variable length, 3 characters, alphanumeric, EBCDIC. If present, cannot contain all spaces or all numeric values. |
sender_name | Cardholder's / User’s name | Mandatory for Cross-border Money and non-Money Transfer AFTs | variable length, max. 30 characters, alphanumeric and special characters, EBCDIC. If present, cannot contain all spaces or all numeric values |
sender_account_number | Account number of the recipient account being funded by the AFT. Account number can be an internal token of the account, a user ID token or another unique identifier of the account. | Mandatory | variable length, max. 34 characters, numeric, EBCDIC. If present, cannot contain all spaces or all numeric values |
recipient_name | Cardholder’s Name | Mandatory | variable length, max. 30 characters, alphanumeric and special characters, EBCDIC. If present, cannot contain all spaces or all numeric values |
bai | Business Application Identifier. Possible values: AA (Account-to-account), FT (Funds Transfer), LA (Liquid Assets) | A valid BAI is required for all AFTs globally. | 2 Bytes, EBCDIC |
mvv | Merchant verification value (MVV) | Required only for staging wallets and not used currently | fixed 10 Bytes, EBCDIC hex digits, left justified with trailing blank |
Fields validations:
When receiving a request Paynetics will checks for the required fields and any field format validations and will reject the transactions if a required field for AFTs is missing or the validation does not pass. An error will be thrown by the first detected missing or incorrect field. Paynetics will reject the transaction with an error which displays which exact field is incorrect/missing information.
Example Request
{
"amount": 11.2,
"currency": "BGN",
"language": "bg",
"transaction_type": "Type of transaction to be performed",
"reference": "payment123",
"reference2": "payment123",
"card": "a8db5888-4d44-4f78-97da-ced9baa59bd2",
"user": "123e4567-e89b-12d3-a456-426655440000",
"success_url": "https://test.com",
"error_url": "https://test.com",
"redirect": true,
"balance": "string",
"aft": {
"account_owner_address1": "James Bourchier 76A",
"account_owner_address2": "James Bourchier 76A",
"account_owner_street": "James Bourchier",
"account_owner_postal_code": "1407",
"account_owner_city": "Sofia",
"account_owner_country": "BGR",
"merchant_postal_code": "1000",
"merchant_state": "Sofia",
"acceptor_legal_name": "Paynetics",
"sender_address": "James Bourchier 76A",
"sender_city": "Sofia",
"sender_state": "Sofia",
"sender_country": "BGR",
"sender_name": "John Doe",
"sender_account_number": "efa213ea-b69d-46c4-a690-dde53d615b85",
"recipient_name": "John Doe",
"bai": "AA",
"account_owner_subdivision_code": "abc",
"mvv": "13456ABCD"
},
"recurring_end_date": "2025-01-30T14:27:33.930Z",
"recurring_frequency": 0
}
Example domestic payment page:
{
"amount": 0.2,
"currency": "BGN",
"language": "bg",
"transaction_type": "purchase",
"merchant": "string",
"reference": "payment123",
"reference2": "payment123",
"card": "string", //example a8db5888-4d44-4f78-97da-ced9baa59bd2
"user": "string", //example 123e4567-e89b-12d3-a456-426655440000
"success_url": "https://www.paynetics.digital",
"error_url": "https://test.com",
"redirect": true,
"balance": "string",
"aft": {
"bai": "AA"
},
"recurring_end_date": "2025-01-30T08:22:07.186Z",
"recurring_frequency": 0
}Example cross-border payment page
{
"amount": 0.2,
"currency": "EUR",
"language": "en",
"transaction_type": "purchase",
"merchant": "string",
"reference": "payment123",
"reference2": "payment123",
"card": "string", //example a8db5888-4d44-4f78-97da-ced9baa59bd2
"user": "string", //example 123e4567-e89b-12d3-a456-426655440000
"success_url": "https://www.paynetics.digital",
"error_url": "https://test.com",
"redirect": true,
"balance": "string",
"aft": {
"account_owner_address1": "James Bourchier 76A",
"account_owner_address2": "James Bourchier 76A",
"account_owner_street": "James Bourchier",
"account_owner_postal_code": "1407",
"account_owner_city": "Sofia",
"account_owner_country": "BGR",
"merchant_postal_code": "1000",
"merchant_state": "BGR",
"acceptor_legal_name": "Paynetics",
"sender_address": "James Bourchier 76A",
"sender_city": "Sofia",
"sender_state": "BGR",
"sender_country": "BGR",
"sender_name": "John Doe",
"sender_account_number": "efa213ea-b69d-46c4-a690-dde53d615b85",
"recipient_name": "John Doe",
"bai": "AA",
"account_owner_subdivision_code": "abc",
"mvv": "13456ABCD"
},
"recurring_end_date": "2025-01-30T08:22:07.186Z",
"recurring_frequency": 0
}Example Response
{{
"code": 0,
"data": {
"url": "string"
}
} Errors by missing fields:
{
code: 11001,
message: 'services.general.validation_error',
key: 'services.general.validation_error',
errors: {
aft_acceptor_legal_name: 'This value should not be blank.',
aft_sender_address: 'This value should not be blank.',
aft_sender_city: 'This value should not be blank.',
aft_sender_country: 'This value should not be blank.',
aft_sender_name: 'This value should not be blank.',
aft_sender_account_number: 'This value should not be blank.',
aft_recipient_name: 'This value should not be blank.',
aft_bai: 'This value should not be blank.',
aft_account_owner_address1: 'This value should not be blank.',
aft_account_owner_address2: 'This value should not be blank.',
aft_account_owner_street: 'This value should not be blank.',
aft_account_owner_postal_code: 'This value should not be blank.',
aft_account_owner_city: 'This value should not be blank.',
aft_account_owner_country: 'This value should not be blank.',
aft_merchant_postal_code: 'This value should not be blank.',
aft_merchant_state: 'This value should not be blank.',
aft_sender_state: 'This value should not be blank.'
}Note that errors are received by field format validations as well.