Instant Auth, Instant Match, and Instant Micro-deposits 
========================================================

#### Learn how to authenticate your users instantly 

#### Instant Auth 

Instant Auth supports more than 6,200 financial institutions with credential-based login. Instant Auth is the default Auth method and does not require extra configuration steps if Auth is already configured in your app. For clarity and completeness, the section below explains how to configure Instant Auth.

The user launches Link...

(An image of "The user launches Link...")

(An image of "...and selects the institution to link.")

(An image of "They are handed off to the institution...")

(An image of "...and log in.")

(An image of "Next, they select the account to link. (Single-account select is typically recommended for Auth.)")

(An image of "...and their account is linked!")

You can try out the Instant Auth flow in an [Interactive Demo](https://plaid.coastdemo.com/share/67d0ce0df465686c02cc4fd2?zoom=100&step=4) .

##### Configure & Create a link\_token 

Create a `link_token` with the following parameters:

*   `products` array containing `auth` – If you are using only `auth` and no other products, `auth` must be specified in the Products array. Other products (such as `identity`) may be specified as well. If you are using multiple products, `auth` is not required to be specified in the products array, but including it is recommended for the best user experience.

```node
app.post('/api/create_link_token', async function (request, response) {
  // Get the client_user_id by searching for the current user
  const user = await User.find(...);
  const clientUserId = user.id;
  const linkTokenRequest = {
    user: {
      // This should correspond to a unique id for the current user.
      client_user_id: clientUserId,
    },
    client_name: 'Plaid Test App',
    products: ['auth'],
    language: 'en',
    webhook: 'https://webhook.example.com',
    redirect_uri: 'https://domainname.com/oauth-page.html',
    country_codes: ['US'],
  };
  try {
    const createTokenResponse = await client.linkTokenCreate(linkTokenRequest);
    response.json(createTokenResponse.data);
  } catch (error) {
    // handle error
  }
});

```

```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}",
  "client_name": "Plaid Test App",
  "user": { "client_user_id": "${UNIQUE_USER_ID}" },
  "products": ["auth"],
  "country_codes": ["US"],
  "language": "en",
  "webhook": "https://webhook.example.com",
  "redirect_uri": "https://domainname.com/oauth-page.html"
}'

```

```ruby
post '/api/create_link_token' do
  # Get the client_user_id by searching for the current user
  current_user = User.find(...)
  client_user_id = current_user.id

  # Create a link_token for the given user
  request = Plaid::LinkTokenCreateRequest.new(
    {
      user: { client_user_id: client_user_id },
      client_name: 'Plaid Test App',
      products: ['auth'],
      country_codes: ['US'],
      language: "en",
      redirect_uri: nil_if_empty_envvar('PLAID_REDIRECT_URI'),
      webhook: 'https://webhook.example.com'
    }
  )
  response = client.link_token_create(request)
  content_type :json
  response.to_json
end

```

```java
import com.plaid.client.model.Products;
import com.plaid.client.model.CountryCode;
import com.plaid.client.model.LinkTokenCreateRequest;
import com.plaid.client.model.LinkTokenCreateRequestUser;
import com.plaid.client.model.LinkTokenCreateResponse;

public class PlaidExample {

  ...
  static class GetLinkToken implements HttpHandler {
    private static PlaidApi plaidClient;

    public void handle(HttpExchange t) throws IOException {
      // Create your Plaid client
      HashMap apiKeys = new HashMap();
      apiKeys.put("clientId", CLIENT_ID);
      apiKeys.put("secret", SECRET);
      ApiClient apiClient = new ApiClient(apiKeys);
      apiClient.setPlaidAdapter(ApiClient.Sandbox);

      plaidClient = apiClient.createService(PlaidApi.class);

      // Get the clientUserId by searching for the current user
      User userFromDB = db.find(...);
      String clientUserId = userFromDB.id;
      LinkTokenCreateRequestUser user = new LinkTokenCreateRequestUser()
        .clientUserId(clientUserId);

      // Create a link_token for the given user
      LinkTokenCreateRequest request = new LinkTokenCreateRequest()
        .user(user)
        .clientName("Plaid Test App")
        .products(Arrays.asList(Products.fromValue("auth")))
        .countryCodes(Arrays.asList(CountryCode.US))
        .language("en")
        .redirectUri("https://domainname.com/oauth-page.html")
        .webhook("https://webhook.example.com");

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

      // Send the data to the client
      return response.body();
    }
  }
}

```

```python
from plaid.model.link_token_create_request import LinkTokenCreateRequest
from plaid.model.link_token_create_request_user import LinkTokenCreateRequestUser
from plaid.model.products import Products
from plaid.model.country_code import CountryCode

@app.route("/create_link_token", methods=['POST'])
def create_link_token():
    # Get the client_user_id by searching for the current user
    user = User.find(...)
    client_user_id = user.id

    # Create a link_token for the given user
    request = LinkTokenCreateRequest(
            products=[Products("auth")],
            client_name="Plaid Test App",
            country_codes=[CountryCode('US')],
            redirect_uri='https://domainname.com/oauth-page.html',
            language='en',
            webhook='https://webhook.example.com',
            user=LinkTokenCreateRequestUser(
                client_user_id=client_user_id
            )
        )
    response = client.link_token_create(request)

    # Send the data to the client
    return jsonify(response.to_dict())


```

```go
func createLinkToken(c *gin.Context) {
  ctx := context.Background()

  // Get the client_user_id by searching for the current user
  user, _ := usermodels.Find(...)
  clientUserId := user.ID.String()

  // Create a link_token for the given user
  request := plaid.NewLinkTokenCreateRequest("Plaid Test App", "en", []plaid.CountryCode{plaid.COUNTRYCODE_US}, *plaid.NewLinkTokenCreateRequestUser(clientUserId))
  request.SetWebhook("https://webhook.sample.com")
  request.SetRedirectUri("https://domainname.com/oauth-page.html")
  request.SetProducts([]plaid.Products{plaid.PRODUCTS_AUTH})

  resp, _, err := testClient.PlaidApi.LinkTokenCreate(ctx).LinkTokenCreateRequest(*request).Execute()

  // Send the data to the client
  c.JSON(http.StatusOK, gin.H{
    "link_token": resp.GetLinkToken(),
  })
}


```

##### Initialize Link with a link\_token 

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

When the user inputs their username and password for the financial institution, the `onSuccess()` callback function will return a `public_token`.

App.js

```javascript
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 accounts to your app server
    $.post('/exchange_public_token', {
      publicToken: public_token,
      accounts: metadata.accounts,
    });
  },
});
```

##### Exchange the public\_token and fetch Auth data 

In your own backend server, call the [/item/public\_token/exchange](https://plaid.com/docs/api/items/index.html.md#itempublic_tokenexchange) endpoint with the Link `public_token` received in the `onSuccess` callback to obtain an `access_token`. Persist the returned `access_token` and `item_id` in your database in relation to the user. You will use the `access_token` when making requests to the [/auth/get](https://plaid.com/docs/api/products/auth/index.html.md#authget) endpoint.

```bash
curl -X POST https://sandbox.plaid.com/item/public_token/exchange \
  -H 'Content-Type: application/json' \
  -d '{
    "client_id": "${PLAID_CLIENT_ID}",
    "secret": "${PLAID_SECRET}",
    "public_token": "public-sandbox-b0e2c4ee-a763-4df5-bfe9-46a46bce993d"
  }'

curl -X POST https://sandbox.plaid.com/auth/get \
  -H 'Content-Type: application/json' \
  -d '{
    "client_id": "${PLAID_CLIENT_ID}",
    "secret": "${PLAID_SECRET}",
    "access_token": "${ACCESS_TOKEN}"
  }'

```

```node
const publicToken = 'public-sandbox-b0e2c4ee-a763-4df5-bfe9-46a46bce993d';

try {
  // Obtain an access_token from the Link public_token
  const tokenResponse = await client.itemPublicTokenExchange({
      public_token: publicToken});
  const accessToken = tokenResponse.access_token;

  // Instantly fetch Auth numbers
  const request: AuthGetRequest = {
    access_token: accessToken,
  };
  const response = await plaidClient.authGet(request);
  const numbers = response.data.numbers;
} catch (err) {
  // handle error
}

```

```python
publicToken = 'public-sandbox-b0e2c4ee-a763-4df5-bfe9-46a46bce993d'

# Obtain an access_token from the Link public_token
token_request = ItemPublicTokenExchangeRequest(
      public_token=publicToken)
token_response = client.item_public_token_exchange(token_request)
accessToken = token_response['access_token']

# Instantly fetch Auth numbers
auth_request = AuthGetRequest(access_token=accessToken)
auth_response = client.auth_get(auth_request)
numbers = auth_response['numbers']

```

```ruby
publicToken = 'public-sandbox-b0e2c4ee-a763-4df5-bfe9-46a46bce993d';

# Obtain an access_token from the Link public_token
item_public_token_exchange_request = Plaid::ItemPublicTokenExchangeRequest.new(
  {
    public_token: publicToken
  }
)
token_response = client.item_public_token_exchange(
  item_public_token_exchange_request
)
accessToken = token_response.access_token

# Instantly fetch Auth numbers
auth_get_request = Plaid::AuthGetRequest.new
auth_get_request.access_token = accessToken

auth_response = client.auth_get(auth_get_request)
numbers = auth_response.numbers

```

```java
String publicToken = "public-sandbox-b0e2c4ee-a763-4df5-bfe9-46a46bce993d";

// Obtain an access_token from the Link public_token
ItemPublicTokenExchangeRequest tokenRequest = new ItemPublicTokenExchangeRequest()
  .publicToken(publicToken);

Response tokenResponse = plaidClient
  .itemPublicTokenExchange(tokenRequest)
  .execute();
if (tokenResponse.isSuccessful()) {
  String accessToken = tokenResponse.body().getAccessToken();

  // Instantly fetch Auth numbers
  AuthGetRequest authGetRequest = new AuthGetRequest()
    .accessToken(accessToken);

  Response authResponse = client()
    .authGet(authGetRequest)
    .execute();

  if (authResponse.isSuccessful()) {
    AuthGetResponse.Numbers numbers = authResponse.body().getNumbers();
  }
}

```

```go
publicToken := "public-sandbox-b0e2c4ee-a763-4df5-bfe9-46a46bce993d"

// obtain an access_token from the Link public_token
exchangePublicTokenResp, _, err := client.PlaidApi.ItemPublicTokenExchange(ctx).ItemPublicTokenExchangeRequest(
  *plaid.NewItemPublicTokenExchangeRequest(publicToken),
).Execute()
accessToken := exchangePublicTokenResp.GetAccessToken()

// Instantly fetch Auth numbers
authGetResp, _, err := client.PlaidApi.AuthGet(ctx).AuthGetRequest(
  *plaid.NewAuthGetRequest(accessToken),
).Execute()

```

Check out the [/auth/get](https://plaid.com/docs/api/products/auth/index.html.md#authget) API reference documentation to see the full Auth request and response schema.

Auth response

```json
{
  "numbers": {
    "ach": [
      {
        "account_id": "vzeNDwK7KQIm4yEog683uElbp9GRLEFXGK98D",
        "account": "9900009606",
        "routing": "011401533",
        "wire_routing": "021000021"
      }
    ],
    "eft": [],
    "international": [],
    "bacs": []
  },
  "accounts": [{ Object }],
  "item": { Object },
  "request_id": "m8MDnv9okwxFNBV"
}
```

#### Instant Match 

Instant Match is available for approximately 800 additional U.S. financial institutions where Instant Auth is not available. Instant Match is enabled automatically for Auth customers and is automatically provided at supported institutions as a fallback experience when Instant Auth is not available. When using Instant Match, Plaid Link will prompt your user to enter their account number and routing number for a depository account. Plaid will then verify the last four digits of the user-provided account number against the account mask retrieved from the financial institution.

The user launches Link...

(An image of "The user launches Link...")

(An image of "...and selects the institution to link.")

(An image of "They find their institution...")

(An image of "...and log in.")

(An image of "Next, they select the account to link. (Single-account select is typically recommended for Auth.)")

(An image of "They verify their bank's routing and account numbers...")

(An image of "If those numbers match the account masks that Plaid has retrieved, the account is verified")

You can try out the Instant Match flow in an [Interactive Demo](https://plaid.coastdemo.com/share/67d0ce0df465686c02cc4fd2?zoom=100&step=4) . See more details in our [testing guide](https://plaid.com/docs/auth/coverage/testing/index.html.md#testing-instant-match) .

When using Instant Match, the user can verify only a single account. Even if the Account Select properties allow selecting all or multiple accounts, the ability to select multiple depository accounts for Auth will be disabled in Link if the institution is using the Instant Match flow.

##### Configuring in Link 

Instant Match will be enabled automatically if you configure the `link_token` with the following parameters:

*   add `"auth"` to `products` array
*   `country_codes` set to `['US']` (adding any other countries to the array will disable Instant Match)

Optionally, you can disable Instant Match on a per-session basis via the [/link/token/create](https://plaid.com/docs/api/link/index.html.md#linktokencreate) call, by setting `"auth.instant_match_enabled": false` in the request body. If you would like to disable Instant Match automatically for all Link sessions, contact your account manager or file a support ticket via the Dashboard.

```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}",
  "user": {"client_user_id": "${UNIQUE_USER_ID}"},
  "client_name": "Plaid App",
  "products": ["auth"],
  "country_codes": ["US"],
  "language": "en",
  "webhook": "https://sample-web-hook.com"
}'

```

```ruby
link_token_create_request = Plaid::LinkTokenCreateRequest.new(
  {
    user: {
      client_user_id: "user-id",
    },
    client_name: 'Plaid Test App',
    products: ['auth'],
    country_codes: ['US'],
    language: "en",
    webhook: 'https://webhook.sample.com',
    link_customization_name: "default",
  }
)
response = client.link_token_create(
  link_token_create_request
)
link_token = response.link_token

```

```node
const request: LinkTokenCreateRequest = {
  user: { client_user_id: new Date().getTime().toString() },
  client_name: 'Plaid App',
  products: [Products.Auth],
  country_codes: [CountryCode.Us],
  language: 'en',
};
try {
  const response = await plaidClient.linkTokenCreate(request);
  const linkToken = response.data.link_token;
} catch (error) {
  // handle error
}

```

```java
LinkTokenCreateRequest request = new LinkTokenCreateRequest()
    .user(user)
    .clientName("very nice client name")
    .products(Arrays.asList(Products.AUTH))
    .countryCodes(Arrays.asList(CountryCode.US))
    .language("en")
    .webhook("https://example.com/webhook")
    .linkCustomizationName("default")
    .accountFilters(accountFilters);

```

```python
request = LinkTokenCreateRequest(
    products=[Products('auth')],
    client_name="Plaid Test App",
    country_codes=[CountryCode('US')],
    language='en',
    webhook='https://sample-webhook-uri.com',
    link_customization_name='default',
    user=LinkTokenCreateRequestUser(
        client_user_id='user-id',
    )
)

response = client.link_token_create(request)

```

```go
user := plaid.LinkTokenCreateRequestUser{
  ClientUserId: "user-id",
}

request := plaid.NewLinkTokenCreateRequest(
  "Plaid Test",
  "en",
  []plaid.CountryCode{plaid.COUNTRYCODE_US},
)
request.SetUser(user)
request.SetProducts([]plaid.Products{plaid.PRODUCTS_AUTH})
request.SetLinkCustomizationName("default")
request.SetWebhook("https://webhook-uri.com")
var instantMatchEnabled bool = true
resp, _, err := client.PlaidApi.LinkTokenCreate(ctx).LinkTokenCreateRequest(*request).Execute()
if err != nil {
  panic(err)
}

linkToken := resp.GetLinkToken()

```

##### Handling Link events 

For a user who goes through the Instant Match flow, the `TRANSITION_VIEW (view_name = NUMBERS)` event will occur after `SUBMIT_CREDENTIALS`, and in the `onSuccess` callback the `verification_status` will be `null` because the user would have been verified instantly.

Sample Link events for Instant Match flow

```bash
OPEN (view_name = CONSENT)
TRANSITION_VIEW (view_name = SELECT_INSTITUTION)
SEARCH_INSTITUTION
SELECT_INSTITUTION
TRANSITION_VIEW (view_name = CREDENTIAL)
SUBMIT_CREDENTIALS
TRANSITION_VIEW (view_name = LOADING)
TRANSITION_VIEW (view_name = MFA, mfa_type = code)
SUBMIT_MFA (mfa_type = code)
TRANSITION_VIEW (view_name = LOADING)
TRANSITION_VIEW (view_name = SELECT_ACCOUNT)
TRANSITION_VIEW (view_name = NUMBERS)
TRANSITION_VIEW (view_name = LOADING)
TRANSITION_VIEW (view_name = CONNECTED)
HANDOFF
onSuccess (verification_status: null)
```

#### Instant Micro-deposits 

Instant Micro-deposits is the Plaid product term for our ability to authenticate any bank account in the US that is supported by RTP or FedNow. For over 80 Plaid-supported banks, Instant Micro-deposits is the fastest and highest-converting form of Auth support available. If both Instant Micro-deposits and Same-Day Micro-deposits are enabled, any user who attempts a micro-deposit with one of the over 400 eligible RTP or FedNow routing numbers will automatically experience the Instant Micro-deposits flow and be able to verify instantly.

##### Instant Micro-deposit flow 

The user launches Link...

(An image of "The user launches Link...")

(An image of "...and selects the institution to link.")

(An image of "They find their institution...")

(An image of "...enter their account info...")

(An image of "...their name...")

(An image of "...and their account type.")

(An image of "The user authorizes Plaid to make a deposit, and the deposit is made immediately.")

(An image of "The user is then prompted to enter the code associated with the deposit.")

(An image of "If the code matches the one that Plaid generated with the deposit description, the user's account is verified.")

1.  Starting on a page in your app, the user clicks an action that opens Plaid Link.
2.  Inside of Plaid Link, the user enters the micro-deposit initiation flow and provides their legal name, account and routing number.
3.  Plaid sends a micro-deposit to the user's account that will post within 5 seconds, and directs the user to log into their bank account to obtain the code from the micro-deposit description.
4.  The user enters the code from the micro-deposit description into Plaid Link.
5.  Upon success, Link closes with a `public_token` and a `metadata` account status of `manually_verified`.

Plaid will not reverse the $0.01 micro-deposit credit.

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

You can try out the Instant Micro-deposits flow in an [Interactive Demo](https://plaid.coastdemo.com/share/67d0ce0df465686c02cc4fd2?zoom=100&step=7) .

##### Configuring in Link 

Instant Micro-deposits will be enabled if you configure the `link_token` with the following parameters:

*   Set the `products` array to `["auth"]`. While in most cases additional products can be added to existing Plaid Items, Items created for micro-deposit verification cannot be used with any Plaid products other than Auth or Transfer, with the exception that approximately 30% of Items verified by Instant Micro-deposits can also be verified by [Identity Match](https://plaid.com/docs/identity/index.html.md#using-identity-match-with-micro-deposit-or-database-items) and evaluated for [Signal Transaction Scores](https://plaid.com/docs/signal/signal-rules/index.html.md#data-availability-limitations) .
*   `country_codes` set to `['US']` (adding any other countries to the array will disable Instant Micro-deposits)
*   `auth.instant_microdeposits_enabled` set to `true`. For Plaid teams created prior to November 2023 this setting is not required; for newer teams, it must be manually configured.

Optionally, you can disable Instant Micro-deposits on a per-session basis via the [/link/token/create](https://plaid.com/docs/api/link/index.html.md#linktokencreate) call, by setting `"auth.instant_microdeposits_enabled": false` in the request body. If you would like to disable Instant Micro-deposits automatically for all Link sessions, contact your account manager or file a support ticket via the Dashboard.

##### Entering the Instant Micro-deposit flow 

Your user will enter the Instant Micro-deposit flow in the following scenarios:

*   The user selects an eligible institution that is not enabled for Instant Auth, Instant Match, or Automated Micro-deposits.
*   The Link session has [Same-Day Micro-deposits](https://plaid.com/docs/auth/coverage/same-day/index.html.md) enabled and the user enters an eligible routing number during the Same-Day Micro-deposits flow. In this case, the session will be "upgraded" to use Instant Micro-deposits rather than Same-Day Micro-deposits.

###### Instant Micro-deposit events 

When a user goes through the Instant Micro-deposit flow, the session will have the `TRANSITION_VIEW` (`view_name = NUMBERS`) event and a `TRANSITION_VIEW` (`view_name = INSTANT_MICRODEPOSIT_AUTHORIZED`) event after the user authorizes Plaid to send a micro-deposit to the submitted account and routing number. In the `onSuccess` callback the `verification_status` will be `manually_verified` since, unlike Same-Day Micro-deposits, Instant Micro-deposits will resolve to either a success or fail state within a single Link session.

##### Testing the Instant Micro-deposit flow 

For credentials that can be used to test Instant Micro-deposits in Sandbox, see [Auth testing flows](https://plaid.com/docs/auth/coverage/testing/index.html.md#testing-instant-micro-deposits) .

#### Automated Micro-deposits 

Integrate the automated micro-deposit method

[View guide](https://plaid.com/docs/auth/coverage/automated/index.html.md)

#### Same-Day Micro-deposits 

Integrate the manual micro-deposit method

[View guide](https://plaid.com/docs/auth/coverage/same-day/index.html.md)

#### Testing in Sandbox 

Learn how to test each Auth method in the Sandbox

[View guide](https://plaid.com/docs/auth/coverage/testing/index.html.md)