Redeeming an Access Token
The account information access permissions you specify in your access token request are reflected in the access token generated. Consequently, if you don't ask for access to a resource type in your access token request, it won't be granted in the access token.
Keeping that in mind, the server-side call forAccessToken() is used to get the object — called a — representing your customer-user. You can then make getResource calls on the Representable object— getAccounts(), getBalances(), getTransactions(), getStandingOrders() and/or getTransferDestinations() — depending on the resource permissions granted in the access token.
A getAccounts() call retrieves a list of accounts the customer holds in the selected bank. Similarly, getBalances() fetches the current balance of each listed account. getTransactions() for a specified account returns a of transactions made to/from that account, which can be filtered by booking date — startDate and/or endDate. A getTransferDestinations() call fetches the beneficiary accounts associated with each transaction.
Field | Description | Required/ Optional |
---|---|---|
balance | This is the access object; contains the account information requested | Required |
customerInitiated | Boolean value. Set it to true if the customer initiates the access to bypass the cache. | Optional |
grantee | TPP that has been granted information access by grantor | Required |
grantor | The customer-user granting access consent to the TPP (grantee) | Required |
refId | Reference identifier for the token; not to be confused with requestId. This field is typically used by the TPP to de-duplicate requests. If not provided, Token.io generates a random string as the refId. | Required |
tokenId | Identifies the access token to be redeemed | Required |
Get Balances
For an account balance query, here's the quick form:
public static
Money redeemBalanceAccessToken
(Member grantee
, String tokenId
) {
// specifies whether the request originated from a customer
boolean
customerInitiated = true
;
// access grantor's account list by applying
// access token to the grantee client
Representable grantor
= grantee.forAccessToken
(tokenId
, customerInitiated);
List<Account> accounts
= grantor.getAccountsBlocking
();
// get the data we want — here, STANDARD is the key-pair level for the grantor
Money balance
= accounts.get
(0
).getBalanceBlocking
(STANDARD
).getCurrent
();
return
balance
;
}
Tip: Because the forAccessToken method lets you specify which access token to apply to access account information, you should establish your own server-side mechanism to correlate access tokens with users. For more on member key pairs, see the onboarding topic on managing keys.
Get Transactions
To get a paged list of transactions for one or more customer-user accounts:
public static
List<Transaction> redeemTransactionsAccessToken
(Member grantee
, String tokenId
) {
// Specifies whether the request originated from a customer
boolean
customerInitiated = true
;
// access grantor's account list by applying
// access token to the grantee client
Representable grantor
= grantee.forAccessToken
(tokenId
, customerInitiated);
List<Account> accounts
= grantor.getAccountsBlocking
();
// get the 10 most recent transactions —
// here, STANDARD is the key-pair level for the grantor
PagedList<Transaction
, String> transactions = accounts
.get(0
)
.getTransactionsBlocking
(null, 10
, STANDARD
);
// get the 10 most recent transactions in the specified start-end date range
PagedList<Transaction, String> transactionsByDate
= accounts
.get(0
)
.getTransactionsBlocking
(null, 10
, STANDARD
, "2019-01-15"
, "2022-01-15"
);
// pass this offset to the next getTransactions
// call to fetch the next page of transactions
String nextOffset
= transactions.getOffset
();
return
transactions.getList
();
}
Certain banks do not encode the transaction id returned in their response; in which case, it falls to the TPP itself to encode the transaction id in order to retrieve an individual transaction record in a subsequent access request. Token.io does not manipulate or alter data returned by the bank.
For all calls, field values in the response are populated based on data returned by the bank. Field values that are not populated in a response were not provided by the bank.
Payee Information
customerData
within providerTransactionDetails
for single transactions.
-
STET requires creditor account information.
-
CMA9, NextGenPSD2, and PolishAPI have the creditor name and account identifiers, as well as the creditor agent BIC. However, these are optional fields, so the presence of creditor account information is bank-dependent.
-
CMA9 needs the creditor agent address, whilst PolishAPI requires the creditor's address.
Return of payee information is not supported by all banks. When available from the bank, the response payload includes creditor account (payee) information (legal name and/or address) in customerData within providerTransactionDetails based on the API standard adopted by the bank, outlined as follows:
- does not require creditor account information.
- , , and have the creditor name and account identifiers, as well as the . However, these are optional fields, so the presence of creditor account information is bank-dependent.
- CMA9 needs the creditor agent address, whilst PolishAPI has the creditor address.
Get Standing Orders
Accessing a customer's list of standing orders works in much the same way as one-time transactions. Here's the quick form:
public static
List<StandingOrder> redeemStandingOrdersAccessToken
(
Member grantee
,
String tokenId
) {
// Specifies whether the request originated from a customer
boolean
customerInitiated = true
;
// access grantor's account list by applying
// access token to the grantee client
Representable grantor
= grantee.forAccessToken
(tokenId
, customerInitiated);
List<Account> accounts
= grantor.getAccountsBlocking
();
// get the first 5 standing orders — here, STANDARD is the key-pair level
// for the grantor
PagedList<StandingOrder
, String> standingOrders = accounts
.get(0)
.getStandingOrdersBlocking
(null, 5
, STANDARD
);
// pass this offset to the next getStandingOrders
// call to fetch the next page of standing orders
String nextOffset
= standingOrders.getOffset
();
return
standingOrders.getList
();
}
As with providerTransactionDetails, the response payload for standing orders includes creditor account (payee) information (legal name and/or address) in customerData within providerStandingOrderDetails outlined as follows:
- does not require creditor account information
- , , and have the creditor name and account identifiers, as well as the
- CMA9 needs the creditor agent address, whilst PolishAPI has the creditor address.
Tip: You can add a CustomerTrackingMetadata object to furnish the bank with customer tracking fields — token-customer-ip-address and token-customer-device-id — for getBalances(), getTransactions(), and getStandingOrders() to let the bank know a particular API call was initiated by the . When you do, the SDK sets the customer-initiated header as true automatically.
This may be useful in circumnavigating bank restrictions that impose a 4-times-a-day (i.e., within the same 24-hour period) access limit on the same in accordance with .
For example:
token-customer-ip-address
: "127.0.0.1"
token-customer-device-id
: "mozilla/5.0 (Windows NT 6.1; Win64; rv47.0) Gecko/20100101 Firefox/47.0:"
Hence, when an access request is explicitly initiated by the customer, the bank may waive the standard TPP access limit. However, this is bank-dependent and can vary from bank to bank.
* * * *
Using its tokenId, you can fetch any unredeemed (active), redeemed (endorsed), or canceled (canceled) token at any time after the token is generated to review its parameters or to cancel the token altogether, as covered next.