Add Variable Recurring Payments to your app
Learn how to use Variable Recurring Payments to power automated bill pay
Variable Recurring Payments (VRP) allows you to obtain bank account details and end-user consent for payments within a set of limits. You can then use VRP to automatically initiate payments from your customer's bank account, without requiring additional end user interaction for each transfer, as long as the payment is within the limits the customer consented to.
VRP is ideal for creating automated recurring bank payments when the payment amount can change from payment to payment, such as for usage-based subscription services, utility payments, or credit card payments.
In this guide, we start from scratch and walk through how to set up a VRP flow for making regular payments.
To use Variable Recurring Payments, you must also use Payment Initiation, and your end users must be located in the UK (although your company can be based elsewhere). To request access, contact your Account Manager. If you are not yet a Plaid customer, contact sales.
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 aname
and abacs
oriban
, to create therecipient_id
of the funds. You can re-use thisrecipient_id
for other payment consents in the future. - Call
/payment_initiation/consent/create
, specifying therecipient_id
of 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, since you will need it when making a payment. - Call
/link/token/create
, passing in theconsent_id
. This creates alink_token
containing all the information needed to display the correct details in Link to your end user. - Pass the
link_token
to your client and launch Link on the client side, according to the specific instructions for your client platform. - 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
call 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 theconsent_id
. - Plaid will fire
PAYMENT_STATUS_UPDATE
webhooks as the payment is processed, to allow you to track the status of the payment. You can also track the status using/payment_initiation/payment/get
.
Revoking consent (optional)
- End users can revoke consent via either their bank or Plaid; 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.
You can use our official server-side client libraries to connect to the Plaid API from your application:
1// Install via npm2npm install --save plaid
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.
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.
/payment_initiation/consent/create
will return a consent_id
, which you should store with your payment metadata (i.e. the internal id of the end user in your system), 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: '2024-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 Initiation 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 initialization, 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 Payment Initiation</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 other products, for payment_initiation
it is not necessary to exchange the public_token
for an access_token
.
Making payments using the consent
Once a user has completed the consent flow, the consent state will be AUTHORISED
. 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}
Tracking payment status
Once the payment execution is accepted by Plaid, you should listen for webhook updates with the PAYMENT_STATUS_UPDATE
code. Webhooks will be sent to the webhook listener endpoint that you specified during the /link/token/create
call. For more details on working with Plaid webhooks, see the Webhook documentation.
1{2 "webhook_type": "PAYMENT_INITIATION",3 "webhook_code": "PAYMENT_STATUS_UPDATE",4 "payment_id": "payment-id-production-2ba30780-d549-4335-b1fe-c2a938aa39d2",5 "new_payment_status": "PAYMENT_STATUS_AUTHORISING",6 "old_payment_status": "PAYMENT_STATUS_INPUT_NEEDED",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 "environment": "production"13}
Alternatively, the status of a payment can also be retrieved using the /payment_initiation/payment/get
endpoint; see the API Reference for details.
Use new_payment_status
field (if using the webhook) or the status
field (if using /payment_initiation/payment/get
) to decide what action needs to be taken.
For example, you may decide to fund the account once the payment status is PAYMENT_STATUS_EXECUTED
, or notify the user that their payment got rejected if the status is PAYMENT_STATUS_REJECTED
.
It is recommended to either confirm the payment status using /payment_initiation/payment/get
(recommended, easier approach) or to implement webhook verification (a more technically challenging approach) before funding an account or providing goods or services based on the payment status webhook.
For most payments in the UK, the terminal status (if not using Virtual Accounts) is PAYMENT_STATUS_EXECUTED
, which indicates that funds have left the payer's account. PAYMENT_STATUS_INITIATED
is the terminal state for payments at some smaller UK banks.
Funds typically settle (i.e., arrive in the payee's account) within a few seconds of the payment execution, although settlement of an executed payment is not guaranteed. To gain access to the PAYMENT_STATUS_SETTLED
terminal status and track whether a payment has settled, use Virtual Accounts.
Revoking consent
The end user may decide to revoke their consent, which can be done via their bank, the Plaid Portal, or via your app. After consent has been revoked, the consent status will be updated to REVOKED
, and the consent_id
can no longer be used to make payments. There is no way to restore a revoked consent_id
; you will need to create a new consent_id
and send the user back through Link to grant consent.
To allow end users to revoke consent via your app, implement the /payment_initiation/consent/revoke
endpoint and create an entry point for it in your UI.
1const request: PaymentInitiationConsentRevokeRequest = {2 consent_id: consentID,3};4try {5 const response = await plaidClient.paymentInitiationConsentRevoke(request);6} catch (error) {7 // handle error8}