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 Plaid's European payment offerings, see Introduction to Payments (Europe).
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
- If you haven't already done so, call /payment_initiation/recipient/create, specifying at least anameand abacsoriban, to create therecipient_idof the funds. You can re-use thisrecipient_idfor other payment consents in the future.
- Call /payment_initiation/consent/create, specifying therecipient_idof the payment and the type and limitations of the consent, including the maximum amount and frequency, and when the consent expires. This endpoint will return aconsent_id, which you should store associated with the end user who created it. You will need this value when making a payment.
- Call /link/token/create, passing in theconsent_id. This creates alink_tokencontaining all the information needed to display the correct details in Link to your end user.
- Pass the link_tokento your client and launch Link on the client side.
- The end user goes through the Link flow. During this flow, they will consent to the terms as specified in the /payment_initiation/consent/createcall in step 2.
Making payments using the consent
Call /payment_initiation/consent/payment/execute, 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 my.plaid.com  Portal. You can also allow them to revoke consent within your app via /payment_initiation/consent/revoke.
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. After creating your account, you can find your API keys under the Team Settings menu on the Plaid Dashboard.
You will also need to complete your application profile and 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, 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.
Install and initialize Plaid libraries
You can use our official server-side client libraries to connect to the Plaid API from your application:
1// Install via npm2npm install --save plaidAfter 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.
1// Using Express2const express = require('express');3const app = express();4app.use(express.json());5
6const { Configuration, PlaidApi, PlaidEnvironments } = require('plaid');7
8const configuration = new Configuration({9  basePath: PlaidEnvironments.sandbox,10  baseOptions: {11    headers: {12      'PLAID-CLIENT-ID': process.env.PLAID_CLIENT_ID,13      'PLAID-SECRET': process.env.PLAID_SECRET,14    },15  },16});17
18const client = new PlaidApi(configuration);Setting up the payment
Creating a recipient
To create a recipient, call /payment_initiation/recipient/create. 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.
1// Using BACS, without IBAN or address2const request: PaymentInitiationRecipientCreateRequest = {3  name: 'John Doe',4  bacs: {5    account: '26207729',6    sort_code: '560029',7  },8};9try {10  const response = await plaidClient.paymentInitiationRecipientCreate(request);11  const recipientID = response.data.recipient_id;12} catch (error) {13  // handle error14}Creating a consent
Create a consent by calling /payment_initiation/consent/create. 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 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 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. 
1const request: PaymentInitiationConsentCreateRequest = {2  recipient_id: recipientID,3  reference: 'TestPaymentConsent',4  type: PaymentInitiationConsentType.Commercial,5  constraints: {6    valid_date_time: {7      to: '2026-12-31T23:59:59Z',8    },9    max_payment_amount: {10      currency: PaymentAmountCurrency.Gbp,11      value: 15,12    },13    periodic_amounts: [14      {15        amount: {16          currency: PaymentAmountCurrency.Gbp,17          value: 40,18        },19        alignment: PaymentConsentPeriodicAlignment.Calendar,20        interval: PaymentConsentPeriodicInterval.Month,21      },22    ],23  },24};25
26try {27  const response = await plaidClient.paymentInitiationConsentCreate(request);28  const consentID = response.data.consent_id;29  const status = response.data.status;30} catch (error) {31  // handle error32}Create a Link token
From your backend, call /link/token/create, passing in the consent_id, to create a link_token.
1const request: LinkTokenCreateRequest = {2  loading_sample: true3};4try {5  const response = await plaidClient.linkTokenCreate(request);6  const linkToken = response.data.link_token;7} catch (error) {8  // handle error9}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. If you want to customize Link's look and feel, you can do so from the Dashboard.
Install Link dependency
1<head>2  <title>Link for VRP</title>3  <script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js"></script>4</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:
1const linkHandler = Plaid.create({2  // Use the link_token created in the previous step to initialize Link3  token: (await $.post('/create_link_token')).link_token,4  onSuccess: (public_token, metadata) => {5    // Show a success page to your user confirming that the6    // payment consent and bank account details were received.7    //8    // The 'metadata' object contains info about the institution9    // the user selected.10    // For example:11    //  metadata  = {12    //    link_session_id: "123-abc",13    //    institution: {14    //      institution_id: "ins_117243",15    //      name:"Monzo"16    //    }17    //  }18  },19  onExit: (err, metadata) => {20    // The user exited the Link flow.21    if (err != null) {22      // The user encountered a Plaid API error prior to exiting.23    }24    // 'metadata' contains information about the institution25    // that the user selected and the most recent API request IDs.26    // Storing this information can be helpful for support.27  },28  onEvent: (eventName, metadata) => {29    // Optionally capture Link flow events, streamed through30    // this callback as your users connect with Plaid.31    // For example:32    //  eventName = "TRANSITION_VIEW",33    //  metadata  = {34    //    link_session_id: "123-abc",35    //    mfa_type:        "questions",36    //    timestamp:       "2017-09-14T14:42:19.350Z",37    //    view_name:       "MFA",38    //  }39  },40});41
42linkHandler.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 webhook to the webhook listener endpoint that you specified during the /link/token/create 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. 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.   
1const request: PaymentInitiationConsentPaymentExecuteRequest = {2  consent_id: consentID,3  amount: {4    currency: PaymentAmountCurrency.Gbp,5    value: 7.99,6  },7  reference: 'Payment1',8  idempotency_key: idempotencyKey,9};10try {11  const response = await plaidClient.paymentInitiationConsentPaymentExecute(12    request,13  );14  const paymentID = response.data.payment_id;15  const status = response.data.status;16} catch (error) {17  // handle error18}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.
Next steps
Review the following sections for information about additional steps that may be required for your integration.
Managing consent: For building in-app functionality allowing users to terminate recurring payment consents, and to learn more about the consent lifecycle.
Payment status: To learn more about the payment status lifecycle and how to track the status of an initiated payment.
Handling failed payments: For details on error handling, including retryable versus non-retryable errors.
Refunds: For details on refund initiation.