Same Day Micro-deposits

Learn how to authenticate your users with traditional, manually verified micro-deposits

Overview

Same Day Micro-deposits can be used to authenticate any bank account in the US, but especially for the ~2,000 institutions that don't support Instant Auth, Instant Match, or Automated Micro-deposit verification. Plaid will make two deposits that post within one business day (using Same Day ACH, which is roughly two days faster than the standard micro-deposit experience of two to three days). Users are instructed to manually verify the deposited amounts within one business day.

Not all Plaid Developer accounts are enabled for Instant Match, Automated Micro-deposits, or Same Day Micro-deposits by default. To enable these features or check your status, contact your account manager or submit a product access Support ticket.

The Same Day Micro-deposit flow

A user connects their financial institution using the following connection flow:

  1. Starting on a page in your app, the user clicks an action that opens Plaid Link with the correct Auth configuration.
  2. Inside of Plaid Link, the user enters the micro-deposit initiation flow and provides their legal name, account and routing number.
  3. Upon successful authentication, Link closes with a public_token and a metadata account status of pending_manual_verification.
  4. Behind the scenes, Plaid sends two micro-deposits to the user's account that will post within one to two business days.
  5. After one to two days, the user is prompted to verify the two deposit amounts in their account, by opening Link with a generated public_token.
  6. Finally, Plaid will reverse the two micro-deposits to pull back the deposit amounts from the user's bank account.

When these steps are done, your user's Auth data is verified and ready to fetch.

Configure & Create a link_token

Create a link_token with the following parameters:

  • products array should include only auth as a product when using same-day manual micro-deposit verification. While in most cases additional products can be added to existing Plaid Items, Items created for same-day manual micro-deposit verification are an exception and cannot be used with any Plaid products other than Auth. To use another product with the same bank account, your user will need to re-link their account.
  • country_codes set to ['US'] – Micro-deposit verification is currently only available in the United States.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// Using Express
const express = require('express');
const app = express();
app.use(express.json());
const plaid = require('plaid');
const client = new plaid.Client({
clientID: process.env.PLAID_CLIENT_ID,
secret: process.env.PLAID_SECRET,
env: plaid.environments.sandbox,
});
app.post('/create_link_token', async (request, response) => {
try {
// Get the client_user_id by searching for the current user
const user = await User.find(...);
const clientUserId = user.id;
// Create the link_token with all of your configurations
const tokenResponse = await client.createLinkToken({
user: {
client_user_id: clientUserId,
},
client_name: 'Plaid Test App',
products: ["auth"],
country_codes: ['US'],
language: 'en',
webhook: 'https://webhook.sample.com',
});
response.json(tokenResponse);
} catch (e) {
// Display error on client
return response.send({ error: e.message });
}
});

Initialize Link with a link_token

After creating a link_token for the auth product, use it to initialize Plaid Link.

When the user successfully inputs their account and routing numbers, the onSuccess() callback function will return a public_token, with verification_status equal to 'pending_manual_verification'.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const linkHandler = Plaid.create({
// Fetch a link_token configured for 'auth' from your app server
token: (await $.post('/create_link_token')).link_token,
onSuccess: (public_token, metadata) => {
// Send the public_token and connected accounts to your app server
$.post('/exchange_public_token', {
publicToken: public_token,
accounts: metadata.accounts,
});
metadata = {
...,
link_session_id: String,
institution: {
name: null, // name is always null for same day micro-deposits
institution_id: null // institution_id is always null for same day micro-deposits
},
accounts: [{
id: 'vzeNDwK7KQIm4yEog683uElbp9GRLEFXGK98D',
mask: '1234',
name: null,
type: 'depository',
subtype: 'checking' | 'savings',
verification_status: 'pending_manual_verification'
}]
}
},
// ...
});
// Open Link on user-action
linkHandler.open();
Display a "pending" status in your app

Because Same Day verification usually takes one business day to complete, we recommend displaying a UI in your app that communicates to a user that verification is currently pending.

You can use the verification_status key returned in the onSuccess metadata.accounts object once Plaid Link closes successfully.

1
verification_status: 'pending_manual_verification';

You can also fetch the verification_status for an Item's account via the Plaid API, to obtain the latest account status.

User entry points in Link

The following table describes the primary entry points into the manual micro-deposit flow:

ExitErrorInstitution SearchInstitution Search
When user clicks X action buttonWhen user encounters any errorWhen no results are foundWhen user scrolls to end of results

Exchange the public token

In your own backend server, call the /item/public_token/exchange endpoint with the Link public_token received in the onSuccess callback to obtain an access_token. Persist the returned access_token, account_id, and item_id in your database in relation to the user.

Note that micro-deposits will only be delivered to the ACH network in the Production environment, and not in Development. To test your integration outside of Production, see Testing same day micro-deposits in Sandbox.

1
2
3
4
5
6
7
8
9
10
11
// publicToken and accountID are sent from your app to your backend-server
const accountID = 'vzeNDwK7KQIm4yEog683uElbp9GRLEFXGK98D';
const publicToken = 'public-sandbox-b0e2c4ee-a763-4df5-bfe9-46a46bce993d';
try {
// Obtain an access_token from the Link public_token
const response = await plaidClient.exchangePublicToken(publicToken);
const accessToken = response.access_token;
} catch (err) {
// handle err
}
1
2
3
4
5
{
"access_token": "access-sandbox-5cd6e1b1-1b5b-459d-9284-366e2da89755",
"item_id": "M5eVJqLnv3tbzdngLDp9FL5OlDNxlNhlE55op",
"request_id": "m8MDnv9okwxFNBV"
}

Check the account verification status (optional)

In some cases you may want to implement logic in your app to display the verification_status of an Item that is pending manual verification. The /accounts/get API endpoint allows you to query this information.

1
2
3
4
5
6
7
8
9
// Fetch the accountID and accessToken from your database
const accountID = 'vzeNDwK7KQIm4yEog683uElbp9GRLEFXGK98D';
const accessToken = 'access-sandbox-5cd6e1b1-1b5b-459d-9284-366e2da89755';
const response = await client.getAccounts(accessToken).catch((err) => {
// handle error
});
const account = response.accounts.find((a) => a.account_id === accountID);
const verificationStatus = account.verification_status;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"accounts": [
{
"account_id": "vzeNDwK7KQIm4yEog683uElbp9GRLEFXGK98D",
"balances": { Object },
"mask": "0000",
"name": null,
"official_name": null,
"type": "depository"
"subtype": "checking" | "savings",
"verification_status":
"pending_manual_verification" |
"manually_verified" |
"verification_expired",
},
...
],
"item": { Object },
"request_id": String
}

Prompt user to verify micro-deposits in Link

After one to two business days, the two micro-deposits sent to the user's account are expected to have posted. To securely verify a Same Day Micro-deposits account, your user needs to come back into Link to verify the two amounts manually.

We recommend sending your user a notification (e.g. email, SMS, push notification) prompting them to come back into your app and verify the two posted micro-deposit amounts.

Verification of Same Day Micro-deposits is performed in two steps:

  1. In your backend server, create a new link_token from the associated access_token for the given user.
  2. Pass the generated link_token into your client-side app, using the token parameter in the Link configuration. This will automatically trigger the micro-deposit verification flow in Link.
Create a new link_token from a persistent access_token

Generate a link_token for verifying micro-deposits by passing the user's associated access_token to the /link/token/create API endpoint. Note that the products field should not be set because the micro-deposits verification flow does not change the products associated with the given access_token.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// Using Express
const express = require('express');
const app = express();
app.use(express.json());
const plaid = require('plaid');
const client = new plaid.Client({
clientID: process.env.PLAID_CLIENT_ID,
secret: process.env.PLAID_SECRET,
env: plaid.environments.sandbox,
});
app.post('/create_link_token', async (request, response) => {
try {
// Get the client_user_id by searching for the current user
const user = await User.find(...);
const clientUserId = user.id;
// Create the link_token with all of your configurations
const tokenResponse = await client.createLinkToken({
user: {
client_user_id: clientUserId,
},
client_name: 'Plaid Test App',
country_codes: ['US'],
language: 'en',
webhook: 'https://webhook.sample.com',
access_token: 'ENTER_YOUR_ACCESS_TOKEN',
});
response.on({ link_token: tokenResponse.link_token });
} catch (e) {
// Display error on client
return response.send({ error: e.message });
}
});
Initialize Link with the generated link_token

In your client-side app, pass the generated link_token into the Link token parameter. Link will automatically detect that Same Day verification is required for the Item and will open directly into the verification flow (see the image above).

In Link, the user will be prompted to log in to their personal banking portal to confirm the two deposit amounts. Upon successful entry of the two amounts, the onSuccess callback will be fired, with an updated verification_status: 'manually_verified'.

A user has three attempts to enter their deposit amounts correctly, after which the Item will be permanently locked for security reasons. See Micro-deposit errors and Product Not Ready errors for errors that may occur during the micro-deposit initiation and verification flow.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const linkHandler = Plaid.create({
token: await fetchLinkTokenForMicrodepositsVerification(),
onSuccess: (public_token, metadata) => {
metadata = {
accounts: [{
...,
verification_status: 'manually_verified',
}],
};
},
// ...
});
// Open Link to verify micro-deposit amounts
linkHandler.open();

An Item's access_token does not change when verifying micro-deposits, so there is no need to repeat the exchange token process.

Fetch Auth data

Finally, we can retrieve Auth data once the user has manually verified their account through Same Day Micro-deposits:

1
2
3
4
5
6
7
const accessToken = 'access-sandbox-5cd6e1b1-1b5b-459d-9284-366e2da89755';
// Instantly fetch Auth numbers
const response = await client.getAuth(accessToken, {}).catch((err) => {
// handle error
});
const numbers = response.numbers;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"numbers": {
"ach": [
{
"account_id": "vzeNDwK7KQIm4yEog683uElbp9GRLEFXGK98D",
"account": "9900009606",
"routing": "011401533",
"wire_routing": "021000021"
}
],
"eft": [],
"international": [],
"bacs": []
},
"accounts": [
{
"account_id": "vzeNDwK7KQIm4yEog683uElbp9GRLEFXGK98D",
"balances": { Object },
"mask": "0000",
"name": null,
"official_name": null,
"verification_status": "manually_verified",
"subtype": "checking" | "savings",
"type": "depository"
}
],
"item": { Object },
"request_id": "m8MDnv9okwxFNBV"
}

Check out the /auth/get API reference documentation to see the full Auth request and response schema.

Micro-deposit transaction description

When the micro-deposits post to your end user's bank account, the transaction description will be written with the format:

1
<clientName> deposit {1,2}

Plaid will reverse the micro-deposits at the same time they are sent — the transaction description will be written with the format:

1
<clientName> reverse {1, 2}

The <clientName> is defined by the following:

  1. The value of the client_name parameter that was used to create the link_token that initialized Link.
  2. The <CLIENT> value in the Title field of the Consent pane within your Plaid Dashboard. If both fields are configured differently, the value set in (1) will take precedence over the value set in (2).