Plaid Processor Token

Already using Plaid? Generate a processor token with your existing integration and hand it to Paynote to instantly create a verified bank funding source — no micro-deposits required.

Recent Requests
Log in to see full request history
TimeStatusUser Agent
Retrieving recent requests…
LoadingLoading…

Add a Funding Source via Plaid Processor Token

Already using Plaid? Generate a processor token with your existing integration and pass it to Paynote to instantly add a verified bank account as a funding source.

📘

Who is this for?

Merchants who already have an active Plaid integration and want to connect their customers' bank accounts to Paynote without starting a separate bank verification flow.


How It Works

The flow spans three parties: your server, Plaid, and the Paynote API. Your customer authenticates their bank through Plaid Link, you exchange the resulting tokens on your server, then pass a single processor_token to Paynote.

StepWhoWhat happens
1Your serverCreate a link_token via Plaid
2Customer's browserLaunch Plaid Link → customer picks their bank account → returns public_token + account_id
3Your serverExchange public_token for access_token via Plaid
4Your serverCall Plaid /processor/token/create with processor: "paynote" → get processor_token
5Your serverPOST processor_token + user_id to Paynote → funding source created instantly as Verified

Before You Start

Make sure all of the following are in place before writing any code:

⚠️

Paynote must be enabled in your Plaid Dashboard

If Paynote is not enabled under Plaid's Integrations page, the /processor/token/create call will fail. This is the most common setup mistake — check this first if you get an error.


Step 1 — Create a link_token (your server)

Generate a short-lived link_token from your backend. This authenticates Plaid Link for your user's session. Call this every time a user opens the Link flow — tokens are one-time use.

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

const plaidClient = new PlaidApi(new Configuration({
  basePath: PlaidEnvironments[process.env.PLAID_ENV], // 'sandbox' or 'production'
  baseOptions: {
    headers: {
      'PLAID-CLIENT-ID': process.env.PLAID_CLIENT_ID,
      'PLAID-SECRET':    process.env.PLAID_SECRET,
      'Plaid-Version':   '2020-09-14',
    },
  },
}));

const response = await plaidClient.linkTokenCreate({
  user:          { client_user_id: 'your-internal-user-id' },
  client_name:   'Your App Name',
  products:      ['auth'],
  country_codes: ['US'],
  language:      'en',
});

const linkToken = response.data.link_token;
// Send linkToken to your frontend to launch Plaid Link

💡

Tip: Force single account selection

Set Account Select to "enabled for one account" in your Plaid Dashboard. This forces customers to select a single bank account so metadata.accounts in the onSuccess callback always has exactly one entry — no ambiguity about which account to use.


Step 2 — Launch Plaid Link (customer's browser)

Use the link_token from Step 1 to open the Plaid Link UI. When the customer authenticates and selects their account, onSuccess fires with a public_token and the selected account_id. Send both to your server.

<!-- Include the Plaid Link script -->
<script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js"></script>

<button id="connectBtn">Connect Bank Account</button>

<script>
  (async function () {
    // Fetch the link_token your server created in Step 1
    const { link_token } = await fetch('/create_link_token').then(r => r.json());

    const handler = Plaid.create({
      token: link_token,

      onSuccess: function(public_token, metadata) {
        const account_id = metadata.accounts[0].id;

        // Send both to your server to complete Steps 3 & 4
        fetch('/exchange_token', {
          method:  'POST',
          headers: { 'Content-Type': 'application/json' },
          body:    JSON.stringify({ public_token, account_id }),
        });
      },

      onExit: function(err, metadata) {
        if (err) console.error('Plaid Link error:', err);
      },
    });

    document.getElementById('connectBtn').onclick = () => handler.open();
  })();
</script>

Step 3 — Exchange tokens & create a processor_token (your server)

Receive the public_token and account_id from your frontend. Exchange the public_token for an access_token, then use both to generate a Paynote processor_token. Both API calls happen on your server — never expose your Plaid secret on the client.

async function createPaynoteProcessorToken(publicToken, accountId) {

  // 3a — Exchange public_token → access_token
  const tokenRes = await plaidClient.itemPublicTokenExchange({
    public_token: publicToken,
  });
  const accessToken = tokenRes.data.access_token;

  // 3b — Create a processor token scoped specifically to Paynote
  const processorRes = await plaidClient.processorTokenCreate({
    access_token: accessToken,
    account_id:   accountId,
    processor:    'paynote', // ← must be exactly "paynote" (lowercase)
  });

  return processorRes.data.processor_token;
  // → "processor-sandbox-0asd1-a92nc"
}

The processor value must be exactly "paynote"

The string must be "paynote" — all lowercase, no spaces. Any other value will cause Plaid to return an error and no token will be issued.


Step 4 — Send the processor_token to Paynote (your server)

POST the processor_token from Step 3 and the customer's Paynote user_id to the Paynote API. Paynote securely retrieves the bank account details from Plaid and creates a Verified funding source — no additional verification steps needed.

Endpoint

POST https://{env}-paynote.seamlesschex.com/v2/funding-source/processor/plaid

Environments

EnvironmentBase URL
Sandboxhttps://sandbox-paynote.seamlesschex.com
Productionhttps://paynote.seamlesschex.com

Request Body Parameters

ParameterTypeRequiredDescription
user_idstringRequiredThe Paynote customer ID to attach the bank account to
processor_tokenstringRequiredThe processor_token received from Plaid in Step 3

Example Request

curl -X POST https://sandbox-paynote.seamlesschex.com/v2/funding-source/processor/plaid \
  -H "Authorization: Bearer YOUR_PAYNOTE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id":         "usr_abc123",
    "processor_token": "processor-sandbox-0asd1-a92nc"
  }'
const response = await fetch(
  'https://sandbox-paynote.seamlesschex.com/v2/funding-source/processor/plaid',
  {
    method:  'POST',
    headers: {
      'Authorization': 'Bearer YOUR_PAYNOTE_API_KEY',
      'Content-Type':  'application/json',
    },
    body: JSON.stringify({
      user_id:         'usr_abc123',
      processor_token: 'processor-sandbox-0asd1-a92nc',
    }),
  }
);

const data = await response.json();
// data.funding_source_id → use this for future payments
import requests

response = requests.post(
    'https://sandbox-paynote.seamlesschex.com/v2/funding-source/processor/plaid',
    headers={
        'Authorization': 'Bearer YOUR_PAYNOTE_API_KEY',
        'Content-Type':  'application/json',
    },
    json={
        'user_id':         'usr_abc123',
        'processor_token': 'processor-sandbox-0asd1-a92nc',
    }
)

data = response.json()
# data['funding_source_id'] → use this for future payments

Success Response

{
  "success":           true,
  "funding_source_id": "fs_123abc",
  "status":            "Verified",
  "bank_name":         "Bank of America",
  "last_four":         "4321"
}

👍

The funding source is immediately ready

A status: "Verified" response means the bank account is instantly ready for ACH debits and credits. No micro-deposit confirmation or additional steps required. Save the funding_source_id — you'll use it on all future payment requests for this customer.


Testing in Sandbox

Use Plaid's Sandbox test credentials when launching Link with a link_token created against PlaidEnvironments.sandbox, and use https://sandbox-paynote.seamlesschex.com as your Paynote base URL.

Shortcut — bypass the Link UI during testing:
Instead of running the full Link flow, call Plaid's /sandbox/public_token/create endpoint directly to get a public_token. Note: when using this shortcut, the accounts array won't be populated. Call /accounts/get to retrieve a checking or savings account ID to use in Step 3.

Log in to the Paynote Sandbox Dashboard to inspect test funding sources and verify results end-to-end.


Going to Production

  1. Request Production access in your Plaid Dashboard
  2. Obtain your Paynote Production API key — contact [email protected] if you don't have one
  3. Switch Plaid's basePath from PlaidEnvironments.sandboxPlaidEnvironments.production
  4. Switch your Paynote base URL from sandbox-paynote.seamlesschex.compaynote.seamlesschex.com

Error Reference

ErrorLikely CauseResolution
invalid_processor_tokenToken already used, expired, or malformedRe-run the Plaid Link flow to generate a new token
customer_not_founduser_id does not exist in PaynoteCreate the customer first
unauthorizedMissing or invalid Paynote API keyCheck the Authorization: Bearer header
processor_not_enabledPaynote not enabled in Plaid DashboardEnable Paynote under Plaid Dashboard → Developers → Integrations

For errors from Plaid during token creation, see the Plaid error codes reference.


Important Notes

Processor tokens are single-use and account-scoped.
Each processor_token is tied to one Plaid item and one bank account. Once submitted to Paynote it cannot be reused. If you need to re-link an account, initiate a new Plaid Link flow.

Tokens can become invalid.
A processor token stops working if the customer revokes their Plaid connection, the Plaid item requires re-authentication, or the financial institution is disabled. If Paynote returns an invalid_processor_token error after a previously working integration, prompt the customer to reconnect via Plaid Link.

Set up webhooks.
Configure a webhook listener to receive real-time funding source status events. See Funding Source Webhooks for the full event reference.


Resources

Body Params
string
required
string
required
Language
Credentials
Header
URL
LoadingLoading…
Response
Click Try It! to start a request and see the response here!