Plaid logo
Docs
ALL DOCS

Payment Initiation (UK and Europe)

  • Introduction to Payment Initiation
  • Add Payment Initiation to your app
  • User onboarding and account funding
  • Add Variable Recurring Payments to your app
  • Virtual Accounts
Plaid logo
Docs
Close search modal
Ask Bill!
Ask Bill!
Hi! I'm Bill! You can ask me all about the Plaid API. Try asking questions like:
    Note: Bill isn't perfect. He's just a robot platypus that reads our docs for fun. You should treat his answers with the same healthy skepticism you might treat any other answer on the internet. This chat may be logged for quality and training purposes. Please don't send Bill any PII -- he's scared of intimacy. All chats with Bill are subject to Plaid's Privacy Policy.
    Plaid.com
    Log in
    Get API Keys
    Open nav

    Add Virtual Accounts to your app

    Use virtual accounts to gain additional insight and control over the flow of funds

    In this guide, we'll walk through how to set up and manage virtual accounts. After integrating you will be able to send and receive money, make withdrawals and refunds, and reconcile funds for faster reconciliation.

    Note: The Sandbox environment uses test data and does not interact with financial institutions.

    Integrate with Plaid Payment Initiation and enable Virtual Accounts

    Virtual accounts are designed to be used in conjunction with the Payment Initiation APIs. To get the most out of Plaid virtual accounts, first add Payment Initiation to your app. In order to be enabled for Virtual Accounts in Production, contact your Account Manager. To test in Sandbox, begin by creating a virtual account via /wallet/create.

    Select Language
    1const request: WalletCreateRequest = {
    2 iso_currency_code: isoCurrencyCode,
    3};
    4try {
    5 const response = await plaidClient.walletCreate(request);
    6 const walletID = response.data.wallet_id;
    7 const balance = response.data.balance;
    8 const numbers = response.data.numbers;
    9 const recipientID = response.data.recipient_id;
    10} catch (error) {
    11 // handle error
    12}

    Enable Virtual Account Transaction webhooks

    Enable virtual account webhooks to receive notifications when new transaction events occur. Plaid will send a webhook for each transaction event. These notifications can be used to stay updated on transaction status information.

    Funding your Virtual Account through Payment Initiation

    Create a Payment that will be initiated to your virtual account
    Select Language
    1const request: PaymentInitiationPaymentCreateRequest = {
    2 recipient_id: recipientID,
    3 reference: 'TestPayment',
    4 amount: {
    5 currency: 'GBP',
    6 value: 100.0,
    7 },
    8};
    9try {
    10 const response = await plaidClient.paymentInitiationPaymentCreate(request);
    11 const paymentID = response.data.payment_id;
    12 const status = response.data.status;
    13} catch (error) {
    14 // handle error
    15}

    Use the recipient_id associated with your wallet_id so Plaid knows to route the payment to your virtual account.

    Launch and complete the Payment Initiation flow in Link

    For more details on how to do this, see the Payment Initiation documentation.

    Confirm that the payment has settled via a payment webhook

    For more details, see the PAYMENT_STATUS_UPDATE webhook.

    1{
    2 "webhook_type": "PAYMENT_INITIATION",
    3 "webhook_code": "PAYMENT_STATUS_UPDATE",
    4 "payment_id": "<PAYMENT_ID>",
    5 "new_payment_status": "PAYMENT_STATUS_SETTLED",
    6 "old_payment_status": "PAYMENT_STATUS_EXECUTED",
    7 "original_reference": "Account Funding 99744",
    8 "adjusted_reference": "Account Funding 99",
    9 "original_start_date": "2017-09-14",
    10 "adjusted_start_date": "2017-09-15",
    11 "timestamp": "2017-09-14T14:42:19.350Z"
    12}
    Confirm that funds have arrived in your virtual account via a transaction webhook

    For more details, see the WALLET_TRANSACTION_STATUS_UPDATE webhook.

    1{
    2 "webhook_type": "WALLET",
    3 "webhook_code": "WALLET_TRANSACTION_STATUS_UPDATE",
    4 "wallet_id": "<WALLET_ID>",
    5 "new_status": "SETTLED",
    6 "old_status": "INITIATED",
    7 "timestamp": "2021-09-14T14:42:19.350Z"
    8}

    Executing a Payout

    Fetch your virtual account to confirm it has sufficient balance
    Select Language
    1const request: WalletGetRequest = {
    2 wallet_id: walletID,
    3};
    4try {
    5 const response = await plaidClient.walletGet(request);
    6 const walletID = response.data.wallet_id;
    7 const balance = response.data.balance;
    8 const numbers = response.data.numbers;
    9} catch (error) {
    10 // handle error
    11}
    Execute a payout
    Select Language
    1const request: WalletTransactionExecuteRequest = {
    2 wallet_id: walletID,
    3 counterparty: {
    4 name: 'Test',
    5 numbers: {
    6 bacs: {
    7 account: '12345678',
    8 sort_code: '123456',
    9 },
    10 },
    11 },
    12 amount: {
    13 value: 1,
    14 iso_currency_code: 'GBP',
    15 },
    16 reference: 'transaction ABC123',
    17 idempotency_key: '39fae5f2-b2b4-48b6-a363-5328995b2753',
    18};
    19try {
    20 const response = await plaidClient.walletTransactionExecute(request);
    21 const transactionID = response.data.transaction_id;
    22 const status = response.data.status;
    23} catch (error) {
    24 // handle error
    25}
    Confirm the payout was executed, via a transaction webhook

    For more details, see the WALLET_TRANSACTION_STATUS_UPDATE webhook.

    1{
    2 "webhook_type": "WALLET",
    3 "webhook_code": "WALLET_TRANSACTION_STATUS_UPDATE",
    4 "wallet_id": "<WALLET_ID>",
    5 "new_status": "EXECUTED",
    6 "old_status": "INITIATED",
    7 "timestamp": "2021-09-14T14:42:19.350Z"
    8}

    Refunding a Payment Initiation payment

    Fetch your virtual account to confirm it has sufficient balance
    Select Language
    1const request: WalletGetRequest = {
    2 wallet_id: walletID,
    3};
    4try {
    5 const response = await plaidClient.walletGet(request);
    6 const walletID = response.data.wallet_id;
    7 const balance = response.data.balance;
    8 const numbers = response.data.numbers;
    9} catch (error) {
    10 // handle error
    11}
    Refund a Payment Initiation payment
    Select Language
    1const request: PaymentInitiationPaymentReverseRequest = {
    2 payment_id: paymentID,
    3 reference: 'Refund for purchase ABC123',
    4 idempotency_key: 'ae009325-df8d-4f52-b1e0-53ff26c23912',
    5};
    6try {
    7 const response = await plaidClient.paymentInitiationPaymentReverse(request);
    8 const refundID = response.data.refund_id;
    9 const status = response.data.status;
    10} catch (error) {
    11 // handle error
    12}
    Confirm the refund was executed, via a transaction webhook

    For more details, see the WALLET_TRANSACTION_STATUS_UPDATE webhook.

    1{
    2 "webhook_type": "WALLET",
    3 "webhook_code": "WALLET_TRANSACTION_STATUS_UPDATE",
    4 "wallet_id": "<WALLET_ID>",
    5 "new_status": "EXECUTED",
    6 "old_status": "INITIATED",
    7 "timestamp": "2021-09-14T14:42:19.350Z"
    8}

    Next steps

    If you're ready to launch to Production, see the Launch checklist.

    Launch checklist

    Recommended steps to take before launching in Production

    Launch

    Launch checklist

    Recommended steps to take before launching in Production

    Launch
    Was this helpful?
    Developer community
    GitHub
    GitHub
    Stack Overflow
    Stack Overflow
    YouTube
    YouTube
    Discord
    Discord