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.

#### Integrate with Plaid Payment Initiation and enable Virtual Accounts 

Virtual accounts are designed to be used in conjunction with the Payment Initiation and Variable Recurring Payments APIs. To get the most out of Plaid virtual accounts, first [add Payment Initiation to your app](https://plaid.com/docs/payment-initiation/payment-initiation-one-time/add-to-app/index.html.md) . In order to get started, you must first have a wallet set up. Virtual Accounts are not enabled by default in Sandbox. To get access in Sandbox or Production, [contact sales](https://plaid.com/contact) or your account manager. Once enabled, create a virtual account via [/wallet/create](https://plaid.com/docs/api/products/virtual-accounts/index.html.md#walletcreate) .

```go
request := plaid.NewWalletCreateRequest(isoCurrencyCode)
response, _, err := client.PlaidApi.WalletCreate(ctx).WalletCreateRequest(*request).Execute()
walletID := response.GetWalletId()
balance := response.GetBalance()
numbers := response.GetNumbers()
recipientID := response.GetRecipientId()

```

```java
WalletCreateRequest request = new WalletCreateRequest()
  .isoCurrencyCode(isoCurrencyCode);
Response response = client()
  .walletCreate(request)
  .execute();
String walletId = response.body().getWalletId();
WalletBalance balance = response.body().getBalance();
WalletNumbers numbers = response.body().getNumbers();
String recipientId = response.body().getRecipientId();

```

```ruby
request = Plaid::WalletCreateRequest.new({ iso_currency_code: iso_currency_code })
response = client.wallet_create(request)
wallet_id = response.wallet_id
balance = response.balance
numbers = response.numbers
recipient_id = response.recipient_id

```

```node
const request: WalletCreateRequest = {
  iso_currency_code: isoCurrencyCode,
};
try {
  const response = await plaidClient.walletCreate(request);
  const walletID = response.data.wallet_id;
  const balance = response.data.balance;
  const numbers = response.data.numbers;
  const recipientID = response.data.recipient_id;
} catch (error) {
  // handle error
}

```

```bash
curl -X POST https://sandbox.plaid.com/wallet/create \
-H 'Content-Type: application/json' \
-d '{
  "client_id": "${PLAID_CLIENT_ID}",
  "secret": "${PLAID_SECRET}",
  "iso_currency_code": "${ISO_CURRENCY_CODE}"
}'

```

```python
request = WalletCreateRequest(iso_currency_code=iso_currency_code)
response = client.wallet_create(request)
wallet_id = response['wallet_id']
balance = response['balance']
numbers = response['numbers']
recipient_id = response['recipient_id']

```

#### Enable Virtual Account Transaction webhooks 

Enable [virtual account webhooks](https://plaid.com/docs/payment-initiation/virtual-accounts/managing-virtual-accounts/index.html.md#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 

```go
request := plaid.NewPaymentInitiationPaymentCreateRequest(
  recipientID,
  "TestPayment",
  *plaid.NewPaymentAmount("GBP", 100.0),
)

response, _, err := client.PlaidApi.PaymentInitiationPaymentCreate(ctx).PaymentInitiationPaymentCreateRequest(*request).Execute()
paymentID := response.GetPaymentId()
status := response.GetStatus()

```

```python
request = PaymentInitiationPaymentCreateRequest(
    recipient_id=recipient_id,
    reference='TestPayment',
    amount=Amount(
        currency='GBP',
        value=100.00
    )
)
response = client.payment_initiation_payment_create(request)
payment_id = response["payment_id"]
status = response["status"]

```

```java
PaymentAmount amount = new PaymentAmount()
  .currency(PaymentAmount.CurrencyEnum.GBP)
  .value(100.00);
PaymentInitiationPaymentCreateRequest request = new PaymentInitiationPaymentCreateRequest()
  .recipientId(recipientId)
  .reference("TestPayment")
  .amount(amount);
Response response = client
  .paymentInitiationPaymentCreate(request)
  .execute();

```

```bash
curl -X POST https://sandbox.plaid.com/payment_initiation/payment/create \
-H 'Content-Type: application/json' \
-d '{
  "client_id": "${PLAID_CLIENT_ID}",
  "secret": "${PLAID_SECRET}",
  "recipient_id": "${RECIPIENT_ID}",
  "reference": "TestPayment",
  "amount": {
    "value": 100.00,
    "currency": "GBP"
  }
}'

```

```ruby
request = Plaid::PaymentInitiationPaymentCreateRequest.new(
  {
    recipient_id: recipient_id,
    reference: "TestPayment",
    amount: {
      value: 100.00,
      currency: "GBP"
    }
  }
)
response = client.payment_initiation_payment_create(request)
payment_id = response.payment_id
status = response.status

```

```node
const request: PaymentInitiationPaymentCreateRequest = {
  recipient_id: recipientID,
  reference: 'TestPayment',
  amount: {
    currency: 'GBP',
    value: 100.0,
  },
};
try {
  const response = await plaidClient.paymentInitiationPaymentCreate(request);
  const paymentID = response.data.payment_id;
  const status = response.data.status;
} catch (error) {
  // handle error
}

```

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](https://plaid.com/docs/payment-initiation/payment-initiation-one-time/add-to-app/index.html.md#launch-the-payment-initiation-flow-in-link) .

##### Confirm that the payment has settled via a payment webhook 

For more details, see the [PAYMENT\_STATUS\_UPDATE](https://plaid.com/docs/api/products/payment-initiation/index.html.md#payment_status_update) webhook.

PAYMENT\_STATUS\_UPDATE

```json
{
  "webhook_type": "PAYMENT_INITIATION",
  "webhook_code": "PAYMENT_STATUS_UPDATE",
  "payment_id": "<PAYMENT_ID>",
  "new_payment_status": "PAYMENT_STATUS_SETTLED",
  "old_payment_status": "PAYMENT_STATUS_EXECUTED",
  "original_reference": "Account Funding 99744",
  "adjusted_reference": "Account Funding 99",
  "original_start_date": "2017-09-14",
  "adjusted_start_date": "2017-09-15",
  "timestamp": "2017-09-14T14:42:19.350Z"
}
```

##### Confirm that funds have arrived in your virtual account via a transaction webhook 

For more details, see the [WALLET\_TRANSACTION\_STATUS\_UPDATE](https://plaid.com/docs/api/products/virtual-accounts/index.html.md#wallet_transaction_status_update) webhook.

WALLET\_TRANSACTION\_STATUS\_UPDATE

```json
{
  "webhook_type": "WALLET",
  "webhook_code": "WALLET_TRANSACTION_STATUS_UPDATE",
  "transaction_id": "<TRANSACTION_ID>",
  "payment_id": "<PAYMENT_ID>",
  "wallet_id": "<WALLET_ID>",
  "new_status": "SETTLED",
  "old_status": "INITIATED",
  "timestamp": "2021-09-14T14:42:19.350Z"
}
```

#### Executing a Payout 

##### Fetch your virtual account to confirm it has sufficient balance 

```go
request := plaid.NewWalletGetRequest(walletID)
response, _, err := client.PlaidApi.WalletGet(ctx).WalletGetRequest(*request).Execute()
walletID := response.GetWalletId()
balance := response.GetBalance()
numbers := response.GetNumbers()

```

```java
WalletGetRequest request = new WalletGetRequest()
  .walletId(walletId);
Response response = client()
  .walletGet(request)
  .execute();
String walletId = response.body().getWalletId();
WalletBalance balance = response.body().getBalance();
WalletNumbers numbers = response.body().getNumbers();

```

```ruby
request = Plaid::WalletGetRequest.new({ wallet_id: wallet_id })
response = client.wallet_get(request)
wallet_id = response.wallet_id
balance = response.balance
numbers = response.numbers

```

```node
const request: WalletGetRequest = {
  wallet_id: walletID,
};
try {
  const response = await plaidClient.walletGet(request);
  const walletID = response.data.wallet_id;
  const balance = response.data.balance;
  const numbers = response.data.numbers;
} catch (error) {
  // handle error
}

```

```bash
curl -X POST https://sandbox.plaid.com/wallet/get \
-H 'Content-Type: application/json' \
-d '{
  "client_id": "${PLAID_CLIENT_ID}",
  "secret": "${PLAID_SECRET}",
  "wallet_id": "${WALLET_ID}"
}'

```

```python
request = WalletGetRequest(wallet_id=wallet_id)
response = client.wallet_get(request)
wallet_id = response['wallet_id']
balance = response['balance']
numbers = response['numbers']

```

##### Execute a payout 

```go
counterpartyBACS := plaid.NewWalletTransactionCounterpartyBACS()
counterpartyBACS.SetAccount("12345678")
counterpartyBACS.SetSortCode("123456")

request := plaid.NewWalletTransactionExecuteRequest(
  "39fae5f2-b2b4-48b6-a363-5328995b2753",
  walletID,
  plaid.WalletTransactionCounterparty{
    Name: "Test",
    Numbers: plaid.WalletTransactionCounterpartyNumbers{
      Bacs: counterpartyBACS,
    },
  },
  plaid.WalletTransactionAmount{
    Value: 1.00,
    IsoCurrencyCode: plaid.WALLETISOCURRENCYCODE_GBP,
  },
  "transaction ABC123",
)
response, _, err := client.PlaidApi.WalletTransactionExecute(ctx).WalletTransactionExecuteRequest(*request).Execute()
transactionID := response.GetTransactionId()
status := response.GetStatus()

```

```java
WalletTransactionCounterparty counterparty = new WalletTransactionCounterparty()
  .name("Test")
  .numbers(new WalletTransactionCounterpartyNumbers()
    .bacs(new WalletTransactionCounterpartyBACS()
      .account("12345678")
      .sortCode("123456")
    )
  );
WalletTransactionAmount amount = new WalletTransactionAmount()
  .value(1.00)
  .isoCurrencyCode(WalletISOCurrencyCode.GBP);

WalletTransactionExecuteRequest request = new WalletTransactionExecuteRequest()
  .walletId(walletId)
  .counterparty(counterparty)
  .amount(amount)
  .reference("transaction ABC123")
  .idempotencyKey("39fae5f2-b2b4-48b6-a363-5328995b2753");

Response response = client()
  .walletTransactionExecute(request)
  .execute();
String transactionId = response.body().getTransactionId();
WalletTransactionStatus status = response.body().getStatus();

```

```ruby
request = Plaid::WalletTransactionExecuteRequest.new(
  {
    wallet_id: wallet_id,
    counterparty: {
      name: 'Test',
      numbers: {
        bacs: {
          account: '12345678',
          sort_code: '123456'
        }
      }
    },
    amount: {
      value: 1,
      iso_currency_code: 'GBP'
    },
    reference: 'transaction ABC123',
    idempotency_key: '39fae5f2-b2b4-48b6-a363-5328995b2753'
  }
)
response = client.wallet_transaction_execute(request)
transaction_id = response.transaction_id
status = response.status

```

```node
const request: WalletTransactionExecuteRequest = {
  wallet_id: walletID,
  counterparty: {
    name: 'Test',
    numbers: {
      bacs: {
        account: '12345678',
        sort_code: '123456',
      },
    },
  },
  amount: {
    value: 1,
    iso_currency_code: 'GBP',
  },
  reference: 'transaction ABC123',
  idempotency_key: '39fae5f2-b2b4-48b6-a363-5328995b2753',
};
try {
  const response = await plaidClient.walletTransactionExecute(request);
  const transactionID = response.data.transaction_id;
  const status = response.data.status;
} catch (error) {
  // handle error
}

```

```bash
curl -X POST https://sandbox.plaid.com/wallet/transaction/execute \
-H 'Content-Type: application/json' \
-d '{
  "client_id": "${PLAID_CLIENT_ID}",
  "secret": "${PLAID_SECRET}",
  "wallet_id": "${WALLET_ID}",
  "counterparty": {
    "name": "Test",
    "numbers": {
      "bacs": {
        "account": "12345678",
        "sort_code": "123456"
      }
    }
  },
  "amount": {
    "value": 1,
    "iso_currency_code": "GBP"
  },
  "reference": "transaction ABC123",
  "idempotency_key": "39fae5f2-b2b4-48b6-a363-5328995b2753"
}'

```

```python
request = WalletTransactionExecuteRequest(
  wallet_id=wallet_id,
  counterparty=WalletTransactionCounterparty(
    name='Test',
    numbers=WalletTransactionCounterpartyNumbers(
      bacs=WalletTransactionCounterpartyBACS(
        account='12345678',
        sort_code='123456'
      )
    )
  ),
  amount=WalletTransactionAmount(
    value=1,
    iso_currency_code='GBP'
  ),
  reference='transaction ABC123',
  idempotency_key='39fae5f2-b2b4-48b6-a363-5328995b2753'
)
response = client.wallet_transaction_execute(request)
transaction_id = response['transaction_id']
status = response['status']

```

##### Confirm the payout was executed, via a transaction webhook 

For more details, see the [WALLET\_TRANSACTION\_STATUS\_UPDATE](https://plaid.com/docs/api/products/virtual-accounts/index.html.md#wallet_transaction_status_update) webhook.

WALLET\_TRANSACTION\_STATUS\_UPDATE

```json
{
  "webhook_type": "WALLET",
  "webhook_code": "WALLET_TRANSACTION_STATUS_UPDATE",
  "transaction_id": "<TRANSACTION_ID>",
  "wallet_id": "<WALLET_ID>",
  "new_status": "EXECUTED",
  "old_status": "INITIATED",
  "timestamp": "2021-09-14T14:42:19.350Z"
}
```

#### Refunding a Payment Initiation payment 

##### Fetch your virtual account to confirm it has sufficient balance 

```go
request := plaid.NewWalletGetRequest(walletID)
response, _, err := client.PlaidApi.WalletGet(ctx).WalletGetRequest(*request).Execute()
walletID := response.GetWalletId()
balance := response.GetBalance()
numbers := response.GetNumbers()

```

```java
WalletGetRequest request = new WalletGetRequest()
  .walletId(walletId);
Response response = client()
  .walletGet(request)
  .execute();
String walletId = response.body().getWalletId();
WalletBalance balance = response.body().getBalance();
WalletNumbers numbers = response.body().getNumbers();

```

```ruby
request = Plaid::WalletGetRequest.new({ wallet_id: wallet_id })
response = client.wallet_get(request)
wallet_id = response.wallet_id
balance = response.balance
numbers = response.numbers

```

```node
const request: WalletGetRequest = {
  wallet_id: walletID,
};
try {
  const response = await plaidClient.walletGet(request);
  const walletID = response.data.wallet_id;
  const balance = response.data.balance;
  const numbers = response.data.numbers;
} catch (error) {
  // handle error
}

```

```bash
curl -X POST https://sandbox.plaid.com/wallet/get \
-H 'Content-Type: application/json' \
-d '{
  "client_id": "${PLAID_CLIENT_ID}",
  "secret": "${PLAID_SECRET}",
  "wallet_id": "${WALLET_ID}"
}'

```

```python
request = WalletGetRequest(wallet_id=wallet_id)
response = client.wallet_get(request)
wallet_id = response['wallet_id']
balance = response['balance']
numbers = response['numbers']

```

##### Refund a Payment Initiation payment 

```python
request = PaymentInitiationPaymentReverseRequest(
  payment_id=payment_id,
  reference='RefundABC123',
  idempotency_key='ae009325-df8d-4f52-b1e0-53ff26c23912'
)
response = client.payment_initiation_payment_reverse(request)
refund_id = response['refund_id']
status = response['status']

```

```go
request := plaid.NewPaymentInitiationPaymentReverseRequest(
  paymentID,
  "ae009325-df8d-4f52-b1e0-53ff26c23912",
  "RefundABC123",
)
response, _, err := client.PlaidApi.PaymentInitiationPaymentReverse(ctx).PaymentInitiationPaymentReverseRequest(*request).Execute()
refundID := response.GetRefundId()
status := response.GetStatus()

```

```bash
curl -X POST https://sandbox.plaid.com/payment_initiation/payment/reverse \
-H 'Content-Type: application/json' \
-d '{
  "client_id": "${PLAID_CLIENT_ID}",
  "secret": "${PLAID_SECRET}",
  "payment_id": "${PAYMENT_ID}",
  "reference": "RefundABC123",
  "idempotency_key": "ae009325-df8d-4f52-b1e0-53ff26c23912"
}'

```

```ruby
request = Plaid::PaymentInitiationPaymentReverseRequest.new(
  {
    payment_id: payment_id,
    reference: 'RefundABC123',
    idempotency_key: 'ae009325-df8d-4f52-b1e0-53ff26c23912'
  }
)
response = client.payment_initiation_payment_reverse(request)
refund_id = response.refund_id
status = response.status

```

```java
PaymentInitiationPaymentReverseRequest request = new PaymentInitiationPaymentReverseRequest()
  .paymentId(paymentId)
  .reference("RefundABC123")
  .idempotencyKey("ae009325-df8d-4f52-b1e0-53ff26c23912");

Response response = client()
  .paymentInitiationPaymentReverse(request)
  .execute();
String refundId = response.body().getRefundId();
PaymentInitiationRefundStatus status = response.body().getStatus();

```

```node
const request: PaymentInitiationPaymentReverseRequest = {
  payment_id: paymentID,
  reference: 'RefundABC123',
  idempotency_key: 'ae009325-df8d-4f52-b1e0-53ff26c23912',
};
try {
  const response = await plaidClient.paymentInitiationPaymentReverse(request);
  const refundID = response.data.refund_id;
  const status = response.data.status;
} catch (error) {
  // handle error
}

```

##### Confirm the refund was executed, via a transaction webhook 

For more details, see the [WALLET\_TRANSACTION\_STATUS\_UPDATE](https://plaid.com/docs/api/products/virtual-accounts/index.html.md#wallet_transaction_status_update) webhook.

WALLET\_TRANSACTION\_STATUS\_UPDATE

```json
{
  "webhook_type": "WALLET",
  "webhook_code": "WALLET_TRANSACTION_STATUS_UPDATE",
  "transaction_id": "<TRANSACTION_ID>",
  "wallet_id": "<WALLET_ID>",
  "new_status": "EXECUTED",
  "old_status": "INITIATED",
  "timestamp": "2021-09-14T14:42:19.350Z"
}
```