In most cases, banks will redirect users to their website or mobile app. However, there are some scenarios where the bank requires the TPP to capture the fields needed for user authentication. This user experience is referred to as embedded authentication.
See the Token.io API reference for details of the following endpoints:
GET /banksPOST /token-requestGET /token-requests/{request ID}/resultPOST /token-requests/{tokenRequestId}/authorizationGET /transfers/{transferId}
Use our Launchpad to test them.
The image below is a simplified swim lane diagram of the integration flow.

Details of the steps within the integration flow are shown below.
The TPP retrieves the list of available banks using the GET /banks call.
We recommend that this step is performed once daily, outside any payment initiation, e.g., at 11pm UTC, and that the result is cached.
In the GET /banks request, there are numerous filtering criteria you can add as parameters to narrow your query. As a minimum, you should filter by your member ID.
See Mandatory fields for information on which fields must be provided for a given bank to accept a payment initiation request.

a. TPP -> Token.io - The TPP requests the list of banks from Token.io.
b. Token.io -> TPP - Token.io supplies the list of banks to the TPP.
The user selects the bank.

a. TPP -> User - The TPP displays the bank selection screen.
b. User -> TPP - The user selects the bank.
The TPP collects consent from the user. For more information see User consent collection.

a. TPP -> User - The TPP initiates consent acceptance from the user.
b. User -> TPP - The user gives consent to the TPP.
The TPP initiates the token request with Token.io using the POST /token-requests call. Token.io responds by acknowledging the details of the request.

a. TPP -> Token.io - The TPP creates the token request using the POST /token-requests call.
If you're using Settlement accounts and you're an unregulated TPP, you'll always need to send the Settlement account id of the sub-TPP in the POST /token-requests request.
b. Token.io -> TPP - Token.io generates a response to the token request.
The TPP requests authorization using the POST /token-requests/{tokenRequestId}/authorization call. Token.io responds with the fields object, containing the initial fields required for the embedded flow.

a. TPP -> Token.io - The TPP requests the authorization URL using the POST /token-requests/{tokenRequestId}/authorization call. Initial credentialFields from the response to GET /banks may be sent in the credentials field. The useCredentialFlow flag must be set to true. When this flag is set to true, the credential flow is triggered. The credentials map must be populated if required by the bank (see the credentialFields in the response to GET /banks), otherwise empty credentials are used.
The useCredentialFlow field should not be confused with useWebAppCredentialsFlow.
When useWebAppCredentialsFlow is set to true and the bank's flow includes embedded steps, these steps are handled by Token.io's HP, rather than by the customer's own pages.
See the POST /token-requests/{tokenRequestId}/authorization request for more details.
b. Token.io -> TPP - Token.io returns the fields to be used in the embedded flow. The response can contain information relating to additional fields to be captured in the fields object.
The TPP captures additional credentials from the user.

a. TPP -> User - The TPP requests additional credentials from the user.
b. User -> TPP - The user provides additional credentials to the TPP.
Using the POST /token-requests/{tokenRequestId}/authorization call, the TPP submits the additional credentials to the bank via Token.io.

a. TPP -> Token.io - The TPP sends additional credentials using the POST /token-requests/{tokenRequestId}/authorization call.
b. Token.io -> TPP - Token.io acknowledges receipt of the additional credentials and requests more, if required.
c. Token.io -> Bank - Token.io sends this additional information to the bank.
d. Bank -> Token.io - The bank confirms receipt of the information from Token.io.
See Embedded callback for more information on the Token.io callback.
The user completes authorization with the bank.
This is an optional step. For some banks, the user may not be redirected to the bank page for completing authorization.

a. Bank -> User - The bank displays the authorization page to the user.
b. User -> Bank - The user authorizes the payment with the bank.
Token.io recommends that TPPs subscribe to webhooks to receive payment status updates. As a fallback, TPPs can also poll Token.io for the current status of an initiated payment request.

a. Token.io -> TPP - Token.io sends the payment status to the TPP in a webhook.
If you're subscribed to webhooks, Token.io sends the payment status in a webhook every time a transfer is created or updated.
See Webhooks for an example webhook notification.
If the webhook is not received within 30 minutes, the TPP should call GET /transfers/{transferId} to retrieve the payment status.
If you're not using webhooks, you'll need to use GET /token-requests/{tokenRequestId}/result to obtain the transferId to then call GET /transfers/{transferId}.
See Alternative to webhooks for more details.
b. TPP -> Token.io - The TPP checks the status with Token.io with the GET /transfers/{transferId} request.
c. Token.io -> TPP - Token.io confirms the payment status with the GET /transfers/{transferId} response.
If you're using Settlement accounts and the payment initiation request is successful, once the payment has been reconciled, the status will be SETTLEMENT_COMPLETED. Depending on the payment rail used, this can take a while.
If you're not using Settlement accounts and the payment initiation request is successful, the status will be SUCCESS, but this does not guarantee that the payment has been settled.
If the status is non-final, e.g., PROCESSING, the TPP should wait for additional webhooks to be sent. If the webhook is not received, the TPP should use a polling call (GET /transfers/{transferId}) every 15 mins.
The recommended maximum polling time is 30 days. If the bank doesn't update the status, it will change to INITIATED after 30 days.
See HTTP errors for information on HTTP error status codes.
If you have any feedback about the developer documentation, please contact devdocs@token.io