Add Variable Recurring Payments to your app 
============================================

#### Learn how to use Variable Recurring Payments in your application 

In this guide, we start from scratch and walk through how to set up a Variable Recurring Payments (VRP) flow. For a high-level overview of all of Plaid's European payment offerings, see [Introduction to Payments (Europe)](https://plaid.com/docs/payment-initiation/index.html.md) .

#### Variable Recurring Payments flow overview 

Variable Recurring Payments consist of two main phases: creating a consent, and making payments using the authorised consent. The Plaid flow begins when your user wants to set up a consent with your app to make regular payments.

The sections below outline the general flow for VRP. The rest of the guide will cover the end-to-end process in more detail, including sample code and instructions for creating your Plaid developer account.

##### Creating a consent 

1.  If you haven't already done so, call [/payment\_initiation/recipient/create](https://plaid.com/docs/api/products/payment-initiation/index.html.md#payment_initiationrecipientcreate) , specifying at least a `name` and a `bacs` or `iban`, to create the `recipient_id` of the recipient. You can re-use this `recipient_id` for other payment consents in the future.
2.  Call [/payment\_initiation/consent/create](https://plaid.com/docs/api/products/payment-initiation/index.html.md#payment_initiationconsentcreate) , specifying the `recipient_id` and the type and limitations of the consent, including the maximum amount and frequency, and when the consent expires. This endpoint will return a `consent_id`, which you should store associated with the end user who created it. You will need this value when making a payment.
3.  Call [/link/token/create](https://plaid.com/docs/api/link/index.html.md#linktokencreate) , passing in the `consent_id`. This creates a `link_token` containing all the information needed to display the correct details in Link to your end user.
4.  Pass the `link_token` to your client and launch Link on the client side.
5.  The end user goes through the Link flow. During this flow, they will consent to the terms as specified in the [/payment\_initiation/consent/create](https://plaid.com/docs/api/products/payment-initiation/index.html.md#payment_initiationconsentcreate) call in step 2.

##### Making payments using the consent 

Call [/payment\_initiation/consent/payment/execute](https://plaid.com/docs/api/products/payment-initiation/index.html.md#payment_initiationconsentpaymentexecute) , passing in the details of the specific payment, such as the amount and the `consent_id`. Plaid will fire `PAYMENT_STATUS_UPDATE` webhooks as the payment is processed, to allow you to track the status of the payment.

##### Revoking consent (optional) 

End users can revoke consent via either their bank or the [Plaid Portal](https://my.plaid.com) . You can also allow them to revoke consent within your app via [/payment\_initiation/consent/revoke](https://plaid.com/docs/api/products/payment-initiation/index.html.md#payment_initiationconsentrevoke) .

#### Get Plaid API keys and complete application and company profile 

If you don't already have one, you'll need to [create a Plaid developer account](https://dashboard.plaid.com/signup) . After creating your account, you can find your [API keys](https://dashboard.plaid.com/developers/keys) under the Developers menu on the Plaid Dashboard.

You will also need to complete your [application profile](https://dashboard.plaid.com/settings/company/app-branding) and [company profile](https://dashboard.plaid.com/settings/company/profile) on the Dashboard. The information in your profile will be shared with users of your application when they manage their connection on the [Plaid Portal](https://my.plaid.com) , and must be completed before connecting to certain institutions.

#### Access Variable Recurring Payments 

Variable Recurring Payments is enabled in Sandbox by default. It uses test data and does not interact with financial institutions. For Production access, contact your account manager or [sales](https://plaid.com/contact/) .

#### Install and initialize Plaid libraries 

You can use our official server-side client libraries to connect to the Plaid API from your application:

```node
// Install via npm
npm install --save plaid

```

```bash
## Not applicable with curl calls

```

```ruby
# Available as a gem
gem install plaid

```

```java
/*
For Gradle, add the following dependency to your build.gradle and replace {VERSION} with the version number you want to use from
- https://github.com/plaid/plaid-java/releases/latest
*/
implementation "com.plaid:plaid-java:{VERSION}"

/*
For Maven, add the following dependency to your POM and replace {VERSION} with the version number you want to use from
- https://github.com/plaid/plaid-java/releases/latest
*/

  com.plaid
  plaid-java
  {VERSION}


```

```python
# Install through pip, only supports Python 3
pip install --upgrade plaid-python

```

```go
go get github.com/plaid/plaid-go

```

After you've installed Plaid's client libraries, you can initialize them by passing in your `client_id`, `secret`, and the environment you wish to connect to (Sandbox or Production). This will make sure the client libraries pass along your `client_id` and `secret` with each request, and you won't need to include them in any other calls.

```node
// Using Express
const express = require('express');
const app = express();
app.use(express.json());

const { Configuration, PlaidApi, PlaidEnvironments } = require('plaid');

const configuration = new Configuration({
  basePath: PlaidEnvironments.sandbox,
  baseOptions: {
    headers: {
      'PLAID-CLIENT-ID': process.env.PLAID_CLIENT_ID,
      'PLAID-SECRET': process.env.PLAID_SECRET,
    },
  },
});

const client = new PlaidApi(configuration);

```

```bash
## Not applicable with curl calls

```

```ruby
require 'sinatra'
require 'plaid'

set :port, ENV['APP_PORT'] || 8000

configuration = Plaid::Configuration.new
configuration.server_index = Plaid::Configuration::Environment[ENV['PLAID_ENV'] || 'sandbox']
configuration.api_key['PLAID-CLIENT-ID'] =  ENV['PLAID_CLIENT_ID']
configuration.api_key['PLAID-SECRET'] = ENV['PLAID_SECRET']

api_client = Plaid::ApiClient.new(
  configuration
)

client = Plaid::PlaidApi.new(api_client)

```

```java
import java.net.*;
import java.io.*;
import retrofit2.Response;
import java.util.Arrays;
import com.sun.net.httpserver.*;

import com.plaid.client.ApiClient;
import com.plaid.client.request.PlaidApi;

public class PlaidExample {
  private static final String CLIENT_ID = System.getenv("PLAID_CLIENT_ID");
  private static final String SECRET = System.getenv("PLAID_SECRET");

  public static void main(String[] args) {
    HttpServer server = HttpServer.create(
      new InetSocketAddress("localhost", 8000), 0);
    server.createContext("/create_link_token", new GetLinkToken());
    server.setExecutor(null);
    server.start();
  }

  // Additional server code goes here

}

```

```python
import plaid
from plaid.api import plaid_api

from flask import Flask
from flask import render_template
from flask import request
from flask import jsonify

app = Flask(name)

configuration = plaid.Configuration(
  host=plaid.Environment.Sandbox,
  api_key={
    'clientId': PLAID_CLIENT_ID,
    'secret': PLAID_SECRET,
  }
)

api_client = plaid.ApiClient(configuration)
client = plaid_api.PlaidApi(api_client)

# Additional server code goes here

if __name__ == "__main__":
    app.run(port=8000)

```

```go
import (
    "context"
    "net/http"
    "os"

    "github.com/gin-gonic/gin"
    "github.com/plaid/plaid-go/v3/plaid"
)


configuration := plaid.NewConfiguration()
configuration.AddDefaultHeader("PLAID-CLIENT-ID", os.Getenv("CLIENT_ID"))
configuration.AddDefaultHeader("PLAID-SECRET", os.Getenv("SECRET"))
configuration.UseEnvironment(plaid.Sandbox)
client := plaid.NewAPIClient(configuration)


func main() {
  r := gin.Default()
  // Server endpoints would be declared here
  // e.g.  r.POST("/create_link_token", createLinkToken)
 r.POST("/create_link_token", createLinkToken)

  err := r.Run(":8000")
  if err != nil {
    panic("unable to start server")
  }
}

```

#### Setting up the payment 

##### Creating a recipient 

To create a recipient, call [/payment\_initiation/recipient/create](https://plaid.com/docs/api/products/payment-initiation/index.html.md#payment_initiationrecipientcreate) . You must provide a `name` and either an `iban` or `bacs` for the recipient. You'll receive a `recipient_id`, which you can re-use for future payments.

```node
// Using BACS, without IBAN or address
const request: PaymentInitiationRecipientCreateRequest = {
  name: 'John Doe',
  bacs: {
    account: '26207729',
    sort_code: '560029',
  },
};
try {
  const response = await plaidClient.paymentInitiationRecipientCreate(request);
  const recipientID = response.data.recipient_id;
} catch (error) {
  // handle error
}

```

```bash
curl -X POST https://sandbox.plaid.com/payment_initiation/recipient/create \
-H 'Content-Type: application/json' \
-d '{
  "client_id": "${PLAID_CLIENT_ID}",
  "secret": "${PLAID_SECRET}",
  "name": "John Doe",
  "iban": "GB33BUKB20201555555555",
  "address": {
    "street": ["street name 999"],
    "city": "city",
    "postal_code": "99999",
    "country": "GB"
    }
  }'

```

```ruby
request = Plaid::PaymentInitiationRecipientCreateRequest.new(
  {
    name: "John Doe",
    iban: "GB33BUKB20201555555555",
    address: {
      street: ["Street Name 999"],
      city: "City",
      postal_code: "99999",
      country: "GB",
    },
    bacs: {
      account: "26207729",
      sort_code: "560029",
    }
  }
)
response = client.payment_initiation_recipient_create(request)
recipient_id = response.recipient_id

```

```java
PaymentInitiationAddress address = new PaymentInitiationAddress()
  .street(Arrays.asList("Street Name 999"))
  .city("City")
  .postalCode("99999")
  .country("GB");
NullableRecipientBACS bacs = new NullableRecipientBACS()
  .account("26207729")
  .sortCode("560029");

PaymentInitiationRecipientCreateRequest request = new PaymentInitiationRecipientCreateRequest()
  .name("John Doe")
  .bacs(bacs)
  .address(address);

Response response = client
  .paymentInitiationRecipientCreate(request)
  .execute();

```

```python
request = PaymentInitiationRecipientCreateRequest(
    name='John Doe',
    iban='GB33BUKB20201555555555',
    address=PaymentInitiationAddress(
        street=['street name 999'],
        city='city',
        postal_code='99999',
        country='GB'
    )
)
response = client.payment_initiation_recipient_create(request)
recipient_id = response["recipient_id"]

```

```go
request := plaid.NewPaymentInitiationRecipientCreateRequest("John Doe")
request.SetBacs(plaid.RecipientBACSNullable{
  Account:  plaid.PtrString("26207729"),
  SortCode: plaid.PtrString("560029"),
})
request.SetAddress(plaid.PaymentInitiationAddress{
  Street:     []string{"Street Name 999"},
  City:       "City",
  PostalCode: "99999",
  Country:    "GB",
})
paymentRecipientCreateResp, _, err := client.PlaidApi.PaymentInitiationRecipientCreate(ctx).PaymentInitiationRecipientCreateRequest(*request).Execute()
recipientID := paymentRecipientCreateResp.GetRecipientId()

```

##### Creating a consent 

Create a consent by calling [/payment\_initiation/consent/create](https://plaid.com/docs/api/products/payment-initiation/index.html.md#payment_initiationconsentcreate) . You must provide the `recipient_id`, as well as a payment type and a set of constraints that align to your billing use case. This includes the maximum amount for a single payment, the frequency of payments, and the maximum cumulative amount for all payments over the consent period.

[/payment\_initiation/consent/create](https://plaid.com/docs/api/products/payment-initiation/index.html.md#payment_initiationconsentcreate) will return a `consent_id`, which you should store associated with this end user, as it will be needed every time you execute a payment. If you forget to store the `consent_id`, there is no way to retrieve it; you will need to make a new call to [/payment\_initiation/consent/create](https://plaid.com/docs/api/products/payment-initiation/index.html.md#payment_initiationconsentcreate) and send your user back through the Link flow to grant consent.

Once the `consent_id` is created, it will have an initial status of `UNAUTHORISED`.

When `alignment` is set to `CALENDAR`, the first period of the consent is pro-rated based on when the consent is created within the calendar period. For example, if a monthly consent with a `max_payment_amount` of £300 is created on the 10th of the month, only approximately 30% of the monthly allowance (about £100) will be available for the remainder of that first month. The full allowance becomes available at the start of the next calendar period.

```python
request = PaymentInitiationConsentCreateRequest(
  recipient_id=recipient_id,
  reference="TestPaymentConsent",
  type="COMMERCIAL",
  constraints=PaymentInitiationConsentConstraints(
    valid_date_time=PaymentConsentValidDateTime(to="2026-12-31T23:59:59Z"),
    max_payment_amount=PaymentConsentMaxPaymentAmount(currency="GBP",value=15.00),
    periodic_amounts=[
      PaymentConsentPeriodicAmount(
        amount=PaymentConsentPeriodicAmountAmount(currency="GBP",value=40.00),
        interval=PaymentConsentPeriodicInterval("MONTH"),
        alignment=PaymentConsentPeriodicAlignment("CALENDAR")
      )
    ]
  )
)

response = client.payment_initiation_consent_create(request)
consent_id = response["consent_id"]
status = response["status"]

```

```go
constraints := plaid.NewPaymentInitiationConsentConstraints(
  *plaid.NewPaymentConsentMaxPaymentAmount("GBP", 15),
  []plaid.PaymentConsentPeriodicAmount{
    *plaid.NewPaymentConsentPeriodicAmount(
      *plaid.NewPaymentConsentPeriodicAmountAmount("GBP", 40),
      plaid.PAYMENTCONSENTPERIODICINTERVAL_MONTH,
      plaid.PAYMENTCONSENTPERIODICALIGNMENT_CALENDAR,
    ),
  },
)
consentValidDateTime := plaid.NewPaymentConsentValidDateTime()
validUntil := time.Date(2026, time.December, 31, 23, 59, 59, 0, time.UTC)
consentValidDateTime.To = *plaid.NewNullableTime(&validUntil)
constraints.SetValidDateTime(*consentValidDateTime)

request := plaid.NewPaymentInitiationConsentCreateRequest(
  recipientID,
  "TestPaymentConsent",
  *constraints,
)

request.SetType(plaid.PAYMENTINITIATIONCONSENTTYPE_COMMERCIAL);

response, _, err := client.PlaidApi.PaymentInitiationConsentCreate(ctx).PaymentInitiationConsentCreateRequest(*request).Execute()
consentID := response.GetConsentId()

```

```bash
curl -X POST https://sandbox.plaid.com/payment_initiation/consent/create \
-H 'Content-Type: application/json' \
-d '{
  "client_id": "${PLAID_CLIENT_ID}",
  "secret": "${PLAID_SECRET}",
  "recipient_id": String,
  "reference": "TestPaymentConsent",
  "type": "COMMERCIAL",
  "constraints": {
    "valid_date_time": {
      "to": "2026-12-31T23:59:59Z"
    },
    "max_payment_amount": {"currency": "GBP", "value": 15},
    "periodic_amounts": [
      {"amount": {"currency": "GBP", "value": 40}, "alignment": "CALENDAR", "interval": "MONTH"}
    ]
  }
}'

```

```ruby
request = Plaid::PaymentInitiationConsentCreateRequest.new(
  {
    recipient_id: recipient_id,
    reference: 'TestPaymentConsent',
    type: 'COMMERCIAL',
    constraints: {
      valid_date_time: {
        to: '2026-12-31T23:59:59Z'
      },
      max_payment_amount: {currency: 'GBP', value: 15},
      "periodic_amounts": [
        {
          amount: {currency: 'GBP', value: 40},
          alignment: 'CALENDAR',
          interval: 'MONTH'
        }
      ]
    }
  }
)

response = client.payment_initiation_consent_create(request)
consent_id = response.consent_id

```

```java
PaymentConsentValidDateTime validDateTime = new PaymentConsentValidDateTime()
  .to(OffsetDateTime.of(2026, 12, 31, 23, 59, 59, 0, ZoneOffset.UTC));
PaymentConsentMaxPaymentAmount maxPaymentAmount = new PaymentConsentMaxPaymentAmount()
  .currency(PaymentAmountCurrency.GBP)
  .value(15.00);
List periodicAmounts = Arrays.asList(
  new PaymentConsentPeriodicAmount()
    .amount(new PaymentConsentPeriodicAmountAmount().currency(PaymentAmountCurrency.GBP).value(40.00))
    .alignment(PaymentConsentPeriodicAlignment.CALENDAR)
    .interval(PaymentConsentPeriodicInterval.MONTH)
);
PaymentInitiationConsentConstraints constraints = new PaymentInitiationConsentConstraints()
  .validDateTime(validDateTime)
  .maxPaymentAmount(maxPaymentAmount)
  .periodicAmounts(periodicAmounts);

PaymentInitiationConsentCreateRequest request = new PaymentInitiationConsentCreateRequest()
  .recipientId(recipientId)
  .reference("TestPaymentConsent")
  .type(PaymentInitiationConsentType.COMMERCIAL)
  .constraints(constraints);

Response response = client
  .paymentInitiationConsentCreate(request)
  .execute();

```

```node
const request: PaymentInitiationConsentCreateRequest = {
  recipient_id: recipientID,
  reference: 'TestPaymentConsent',
  type: PaymentInitiationConsentType.Commercial,
  constraints: {
    valid_date_time: {
      to: '2026-12-31T23:59:59Z',
    },
    max_payment_amount: {
      currency: PaymentAmountCurrency.Gbp,
      value: 15,
    },
    periodic_amounts: [
      {
        amount: {
          currency: PaymentAmountCurrency.Gbp,
          value: 40,
        },
        alignment: PaymentConsentPeriodicAlignment.Calendar,
        interval: PaymentConsentPeriodicInterval.Month,
      },
    ],
  },
};

try {
  const response = await plaidClient.paymentInitiationConsentCreate(request);
  const consentID = response.data.consent_id;
  const status = response.data.status;
} catch (error) {
  // handle error
}

```

#### Create a Link token 

From your backend, call [/link/token/create](https://plaid.com/docs/api/link/index.html.md#linktokencreate) , passing in the `consent_id`, to create a `link_token`.

```node
const request: LinkTokenCreateRequest = {
  loading_sample: true
};
try {
  const response = await plaidClient.linkTokenCreate(request);
  const linkToken = response.data.link_token;
} catch (error) {
  // handle error
}
```

```python
request = LinkTokenCreateRequest(
  loading_sample=True
)
# create link token
response = client.link_token_create(request)
link_token = response['link_token']
```

```bash
curl -X POST https://sandbox.plaid.com/link/token/create -H 'Content-Type: application/json' -d '{
  "client_id": "${PLAID_CLIENT_ID}",
  "secret": "${PLAID_SECRET}",
  "loading_sample": true
}'
```

```ruby
link_token_create_request = Plaid::LinkTokenCreateRequest.new(
  {
    loading_sample: true
  }
)

response = client.link_token_create(
  link_token_create_request
)
link_token = response.link_token
```

```java
LinkTokenCreateRequest request = new LinkTokenCreateRequest()
  .loadingSample(true);

Response response = client
  .linkTokenCreate(request)
  .execute();

String linkToken = response.body().getLinkToken();
```

```go
request := plaid.NewLinkTokenCreateRequest(
  "Sample App App",
  "en",
  []plaid.CountryCode{plaid.COUNTRYCODE_US},
  user,
)
request.SetLoadingSample(true)

linkTokenCreateResp, _, err := client.PlaidApi.LinkTokenCreate(ctx).LinkTokenCreateRequest(*request).Execute()
if err != nil {
  panic(err)
}
linkToken := linkTokenCreateResp.GetLinkToken();
```

#### Launch the payment flow in Link 

Plaid Link is a drop-in module that provides a secure, elegant authentication flow for the many financial institutions that Plaid supports. Link makes it secure and easy for users to connect their bank accounts to Plaid.

Because Link has access to all the details of the payment consent at the time of initialisation, it will display a screen with the consent details already populated. All your end user has to do is log in to their financial institution through a Link-initiated OAuth flow, select a funding account, and consent to the VRP details. When the end user has successfully done this, you will receive an `onSuccess` callback.

Note that these instructions cover Link on the web. For instructions on using Link within mobile apps, see the [Link documentation](https://plaid.com/docs/link/index.html.md) . If you want to customise Link's look and feel, you can do so from the [Dashboard](https://dashboard.plaid.com/link) .

##### Install Link dependency 

index.html

```html
<head>
  <title>Link for VRP</title>
  <script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js"></script>
</head>
```

##### Configure the client-side Link handler 

Plaid communicates to you certain events that relate to how the user is interacting with Link. What you do with each of these event triggers depends on your particular use case, but a basic scaffolding might look like this:

app.js

```javascript
const linkHandler = Plaid.create({
  // Use the link_token created in the previous step to initialize Link
  token: (await $.post('/create_link_token')).link_token,
  onSuccess: (public_token, metadata) => {
    // Show a success page to your user confirming that the
    // payment consent and bank account details were received.
    //
    // The 'metadata' object contains info about the institution
    // the user selected.
    // For example:
    //  metadata  = {
    //    link_session_id: "123-abc",
    //    institution: {
    //      institution_id: "ins_117243",
    //      name:"Monzo"
    //    }
    //  }
  },
  onExit: (err, metadata) => {
    // The user exited the Link flow.
    if (err != null) {
      // The user encountered a Plaid API error prior to exiting.
    }
    // 'metadata' contains information about the institution
    // that the user selected and the most recent API request IDs.
    // Storing this information can be helpful for support.
  },
  onEvent: (eventName, metadata) => {
    // Optionally capture Link flow events, streamed through
    // this callback as your users connect with Plaid.
    // For example:
    //  eventName = "TRANSITION_VIEW",
    //  metadata  = {
    //    link_session_id: "123-abc",
    //    mfa_type:        "questions",
    //    timestamp:       "2017-09-14T14:42:19.350Z",
    //    view_name:       "MFA",
    //  }
  },
});

linkHandler.open();
```

Unlike most other Plaid products, it is not necessary to exchange the `public_token` you receive from the `onSuccess` callback for an `access_token` when using Variable Recurring Payments.

#### Making payments using the consent 

Once a user has completed the consent flow in Link, the consent status will update to `AUTHORISED` and Plaid will send a [CONSENT\_STATUS\_UPDATE](https://plaid.com/docs/api/products/payment-initiation/index.html.md#consent_status_update) webhook to the webhook listener endpoint that you specified during the [/link/token/create](https://plaid.com/docs/api/link/index.html.md#linktokencreate) call.

At this point you can make payments within the consent parameters, with no user input required.

To make a payment, call [/payment\_initiation/consent/payment/execute](https://plaid.com/docs/api/products/payment-initiation/index.html.md#payment_initiationconsentpaymentexecute) . You will need to provide the `consent_id`, as well as the `amount` of the payment, a `reference` string of your choice to identify the payment, and an `idempotency_key`.

The `idempotency_key` should be a string that is unique per payment and is used to ensure that you do not accidentally make the same payment twice when re-trying a payment attempt (e.g., when retrying after receiving a 500 error that does not guarantee whether or not the payment was successful); if you have already made a payment with the same `idempotency_key`, the payment attempt will fail.

```python
request = PaymentInitiationConsentPaymentExecuteRequest(
    consent_id=consent_id,
    amount=PaymentAmount(currency="GBP",value=7.99),
    idempotency_key=idempotency_key,
    reference="Payment1"
)

response = client.payment_initiation_consent_payment_execute(request)
payment_id = response["payment_id"]
status = response["status"]

```

```go
request := plaid.NewPaymentInitiationConsentPaymentExecuteRequest(consentID, *plaid.NewPaymentAmount("GBP", 7.99), idempotencyKey)
request.SetReference("Payment1")

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

```

```bash
curl -X POST https://sandbox.plaid.com/payment_initiation/consent/payment/execute \
-H 'Content-Type: application/json' \
-d '{
  "client_id": "${PLAID_CLIENT_ID}",
  "secret": "${PLAID_SECRET}",
  "consent_id": String,
  "idempotency_key": String,
  "amount": {"currency": "GBP", "value": 7.99},
  "reference": "Payment1"
}'

```

```ruby
request = Plaid::PaymentInitiationConsentPaymentExecuteRequest.new(
  {
    consent_id: consent_id,
    amount: {currency: 'GBP', value: 7.99},
    idempotency_key: idempotency_key,
    reference: 'Payment1'
  }
)

response = client.payment_initiation_consent_payment_execute(request)
payment_id = response.payment_id
status = response.status

```

```java
PaymentInitiationConsentPaymentExecuteRequest request = new PaymentInitiationConsentPaymentExecuteRequest()
  .consentId(consentId)
  .amount(new PaymentAmount().currency(PaymentAmountCurrency.GBP).value(7.99))
  .reference("Payment1")
  .idempotencyKey(idempotencyKey);

Response response = client
  .paymentInitiationConsentPaymentExecute(request)
  .execute();

```

```node
const request: PaymentInitiationConsentPaymentExecuteRequest = {
  consent_id: consentID,
  amount: {
    currency: PaymentAmountCurrency.Gbp,
    value: 7.99,
  },
  reference: 'Payment1',
  idempotency_key: idempotencyKey,
};
try {
  const response = await plaidClient.paymentInitiationConsentPaymentExecute(
    request,
  );
  const paymentID = response.data.payment_id;
  const status = response.data.status;
} catch (error) {
  // handle error
}

```

This will complete the process of initiating the payment. An individual instance of a VRP series is treated the same as a single payment created via One-Time Payment Initiation and has the same possible statuses and transitions.

To learn about tracking payments, see [Payment Status](https://plaid.com/docs/payment-initiation/payment-status/index.html.md) .

#### Next steps 

Review the following sections for information about additional steps that may be required for your integration.

[Managing consent](https://plaid.com/docs/payment-initiation/variable-recurring-payments/managing-consent/index.html.md) : For building in-app functionality allowing users to terminate recurring payment consents, and to learn more about the consent lifecycle.

[Payment status](https://plaid.com/docs/payment-initiation/payment-status/index.html.md) : To learn more about the payment status lifecycle and how to track the status of an initiated payment.

[Handling failed payments](https://plaid.com/docs/payment-initiation/variable-recurring-payments/handling-failed-payments/index.html.md) : For details on error handling, including retryable versus non-retryable errors.

[Refunds](https://plaid.com/docs/payment-initiation/variable-recurring-payments/refunds/index.html.md) : For details on refund initiation.