Links a checking or savings bank account to a verified entity with a Plaid or MX processor token.

This endpoint accepts an account ID and either an MX authorization code or a Plaid processor token.


Required: MX auth code or Plaid processor token

You will need a MX authorization_code or Plaid processor_token before you can link an account to an entity.

Sila will need access to the following for Plaid or MX to work with /link_account:

  • Plaid: Balance, Identity, and Auth products
  • MX: Verification and Identity jobs

Link Account

Once you have obtained a Plaid processor token or MX authorization code, you will link an end user's account by calling /link_account.


  • Pass the Plaid processor_token in the provider_token parameter
  • Set the provider as plaid
  • Set provider_token_type as processor.


  • Pass the MX authorization_code in the provider_token parameter
  • Set the provider as mx
  • Set provider_token_type as processor.

To verify: You can use the /get_account_balance endpoint and pass "account_name" to verify bank account link.

Account Linking Expiration

Once an account is linked, our /issue_sila and /redeem_sila endpoints should continue to work unless:

  1. The account is manually removed using /delete_account.
  2. The login session expires.

    Each individual banking institution controls how long a login session lasts, so there is no way to predict how long this will be. 30 days is a safe bet, though it may be shorter or longer.


The account_name key is not required, but can be used to set a custom name to identify the linked checking account. If not provided, the linked account's name will be "default". We highly recommend specifying a custom name.

Note: user handles cannot have two linked accounts with the same name.

Authorization / Authentication

Apps using Access Token Authorization

Use a valid access token in an Authorization: Bearer request header.

See Authenticating with an Access Token for more details.

Apps using ECDSA Authentication

Both authsignature and usersignature headers are required for this request. The usersignature header should be generated with a keypair registered to the user (either registered from the /register endpoint or the /register_wallet endpoint).

See the section on ECDSA Authentication for more detail about ECDSA signature generation.

POST /0.2/link_account HTTP/1.1
Content-Type: application/json
// if using OAuth2
Authorization: Bearer [GENERATED JWT TOKEN HERE]
// if using ECDSA

***Link Account with Plaid 
  "header": {
    "created": 1234567890, 
    "app_handle": "handle.silamoney.eth", 
    "version": "0.2", 
    "crypto": "ETH", 
    "reference": "<your unique id>"
  "provider_token": "processor-xxx-xxx",
  "provider": "plaid",
  "account_name": "Custom Account Name", //optional but recommended
  "selected_account_id": "selected_account_id", //optional
  "account_type": "Checking or Savings", //optional
  "provider_token_type": "processor"

***Link Account with MX
  "header": {
    "created": 1234567890, 
    "app_handle": "handle.silamoney.eth", 
    "version": "0.2", 
    "crypto": "ETH", 
    "reference": "<your unique id>"
  "provider_token": "authorization_code-xxx-xxx",
  "provider": "mx",
  "account_name": "Custom Account Name",
  "provider_token_type": "processor"


HTTP/1.1  200 OK

  "success": true,
  "status": "SUCCESS",
  "reference": "<your unique id>",
  "response_time_ms": "1171",
  "message": "Bank account successfully linked.",
  "account_name": "Custom Account Name",
  "match_score": 0.825,
  "account_owner_name": "Sally Smith",
  "entity_name": "Sally Smith",

Request - /link_account

// Plaid verification flow
const res = await Sila.linkAccount(
  accountName, // Account Name is not required
  accountId, // Account Id parameters is required,
  plaidTokenType, // Required.'processor,'

// MX verification flow
const res = await sila.linkAccountMX(

Success Response

console.log(res.statusCode); // 200
console.log(res.data.reference); // Random reference number
console.log(res.data.status); // SUCCESS

// Direct account-linking flow (restricted by use-case, contact Sila for approval)
const res = await Sila.linkAccountDirect(
// Account Type and Account Name parameters are not required
// The only permitted account type is "CHECKING"

console.log(res.statusCode); // 200
console.log(res.data.reference); // Random reference number
console.log(res.data.status); // SUCCESS
console.log(res.data.message); // Bank account successfully linked
console.log(res.data.web_debit_verified); // true/false
### Link Account with MX
payload = {
"user_handle": user_handle,
"provider": "mx",
"provider_token_type": “processor”,
"account_name": 'default_mx',
"selected_account_id": "<account_id>"

response = silasdk.User.linkAccount(
app, payload, eth_private_key, False,True)

### Link Account with Plaid
payload = {
"public_token": "public-development-0dc5f214-56a2-4b69-8968-f27202477d3f",  # Required token from plaid
"user_handle": "user.silamoney.eth",                             # Required
    "account_name": "Custom Account Name",                                       # Optional (default value is "default")
    "selected_account_id": "account id",                                        # Optional
    "plaid_token_type": "plaid token type"                                      # Optional}                                         

User.linkAccount(silaApp, payload, user_private_key, plaid=True)

### Link Account with Direct Account Linking
            "user_handle": "user.silamoney.eth",    # Required
            "account_number": "123456789012",       # Required
            "routing_number": "123456780",          # Required
            "account_type": "CHECKING",             # Optional (default value is CHECKING)
            "account_name": "Custom Account Name"   # Optional (default value is "default"),


### Success Response Object
    "success": true,
    "account_name": "Gringotts Savings",
    "account_owner_name": "",
    "entity_name": "Postman User",
    "match_score": 0.9
    "message": "Bank account successfully linked.",
    "provider": "MX",
    "reference": "2910ca97-9cb6-4d36-a6fe-591159c61865",
    "response_time_ms": "1262",
    "status": "SUCCESS",
    "web_debit_verified": true
// Link account with Plaid
String userHandle = 'user.silamoney.eth';
String accountName = 'plaid'; // Your desired account name
String publicToken = 'public-sandbox-xxx' // Your Plaid token
String userPrivateKey = 'some private key';
String accountId = 'plaid account id'; // Required
String plaidTokenType = "Processor";

ApiResponse response = api.linkAccountPlaidToken(userHandle, userPrivateKey, accountName, publicToken, accountId, plaidTokenType);

// Link account with MX
String provider ="mx";
String providerTokenType ="processor";
String userHandle = "user.silamoney.eth";
String userPrivateKey = "user private key";
String providerToken = "provider token";

ApiResponse response = api.linkAccountMX(userHandle,

// Link Account directly (restricted by use-case, contact Sila for approval)
String userHandle = 'user.silamoney.eth';
String accountName = 'direct'; // Your desired account name
String accountNumber = '123456789012';
String routingNumber = '123456780';
String accountType = 'CHECKING'; // Currently the only allowed value
String userPrivateKey = 'some private key';

ApiResponse response = api.linkAccount(userHandle, userPrivateKey, accountName, accountNumber, routingNumber, accountType);

// Success Response
System.out.println(response.getStatusCode()); // 200
LinkAccountResponse parsedResponse = (LinkAccountResponse) response.getData();
System.out.println(parsedResponse.getStatus()); // SUCCESS
System.out.println(parsedResponse.getSuccess()); // true
System.out.println(parsedResponse.getReference()); // Reference number
System.out.println(parsedResponse.getMessage()); // Successfully linked
System.out.println(parsedResponse.getAccountName()); // Your desired account name
System.out.println(parsedResponse.getMatchScore()); // Match score
System.out.println(parsedResponse.getWebDebitVerified()); // true/false
System.out.println(parsedResponse.getProvider()); // 'plaid' | 'mx'
API Endpoint - /link_account

 * Link with Plaid
 * IMPORTANT! If you do not specify an `$account_id` in `linkAccount()`, the first 
 * account returned by Plaid will be linked by default.
use Silamoney\Client\Domain\PlaidTokenType;

$userHandle = 'user.silamoney.eth';
$accountName = 'Custom Account Name'; // Defaults to 'default'
$plaidToken = 'public-xxx-xxx'; // A temporary token returned from the Plaid Link plugin. See above for testing.
$accountId = 'string'; // Recommended but not required. See note above.
$userPrivateKey = 'some private key'; // The private key used to register the specified user
$plaidTokenType = PlaidTokenType::Processor(); // Optional.  PROCESSOR

$response = $client->linkAccount($userHandle, $userPrivateKey, $plaidToken, $accountName, $accountId, $plaidTokenType);

 * Link with MX

$accountName = "defaultMx";
$accountId = "123456780";
$provider = "mx";
$providerTokenType = "processor";

// Making call to API
$response = $client->linkAccountMx(

 * Link with Direct Account information
 * (Restricted by use-case, contact Sila for approval)

$userHandle = 'user.silamoney.eth';
$accountName = 'Custom Account Name'; // Defaults to 'default' if not provided. (not required)
$routingNumber = '123456789'; // The routing number. 
$accountNumber = '123456789012'; // The bank account number
$userPrivateKey = 'some private key'; // The private key used to register the specified user
$accountType = 'CHECKING'; // The account type (not required). Only available value is CHECKING

$response = $client->linkAccountDirect($userHandle, $userPrivateKey, $accountNumber, $routingNumber, $accountName, $accountType);

 * Response structure (200 Success)
echo $response->getStatusCode(); // 200
echo $response->getData()->getStatus(); // SUCCESS
echo $response->getData()->getReference();
echo $response->getData()->getMessage();
echo $response->getData()->getAccountName();
echo $response->getData()->getAccountOwnerName();
echo $response->getData()->getEntityName();
echo $response->getData()->getMatchScore();
echo $response->getData()->getWebDebitVerified();
// Link Account with Plaid
ApiResponse<object> response = api.LinkAccount(userHandle, publicToken, walletPrivateKey, accountName, accountId, plaidTokenType);
// Account Name is not required 
// Account Id is required
// plaidTokenType is not required

// Link Account with MX
ApiResponse<object> response = api.LinkAccountMx(userHandle, userPrivateKey, provider, providerTokenType, providerToken);
// Account Name is not required 
// Account Id is not required 

// Link Account with Direct Account information
ApiResponse<object> response = api.LinkAccountDirect(userHandle, walletPrivateKey, accountNumber, routingNumber, accountType, accountName);
// Account Name is not required 
// Account Type is not required  

// Success Response Object

Console.WriteLine(response.StatusCode); // 200
var parsedResponse = (LinkAccountResponse)response.Data;

Console.WriteLine(parsedResponse.Success); // true
Console.WriteLine(parsedResponse.Status); // SUCCESS
Console.WriteLine(parsedResponse.Reference); // Random reference number
Console.WriteLine(parsedResponse.ResponseTimeMs); // 2345
Console.WriteLine(parsedResponse.Message); // Bank account successfully linked.
Console.WriteLine(parsedResponse.AccountName); // Custom Account Name.
Console.WriteLine(parsedResponse.MatchScore); // 0.825           
Console.WriteLine(parsedResponse.AccountOwnerName); //Sally Smith
Console.WriteLine(parsedResponse.EntityName); //Sally Smith
Console.WriteLine(parsedResponse.WebDebitVerified); //true
Console.WriteLine(parsedResponse.Provider); //'mx' | 'plaid'

The plaid_token and plaid_token_type parameters have been deprecated and are only used prior to SDK version 0.2.49; however, they are still supported for backwards compatibility.

Item Details for /link_account

headerJSON objectRequired. Requires these keys in JSON format: created, app_handle, user_handle. See the /check_handle endpoint for the complete list of fields in this object.
provider_tokenStringPlaid + Sila Integration:
Pass a processor token obtained from Plaid.
Example: processor-xxx-xxx.
This value shall match the required regex pattern: ^[-a-zA-Z0-9_]+$

MX + Sila Integration:
Pass an authorization_code from MX.
The MX authorization code is a 32 byte string
providerStringPlaid + Sila Integration:
pass "plaid" as the provider

MX + Sila Integration:
pass mx as the provider.
account_nameStringOptional. Min length 1, Max length 40, default value if not sent in request is “default”
Example: Custom Account Name
NOTE- We highly recommend specifying a custom name here as this is how an account is identified for /issue_sila, /redeem_sila, and /get_transactions.
selected_account_idStringApplicable to Plaid Only

Not required with a Plaid processor token or if the selected_account_id is packaged inside the processor token.

This is the Plaid account ID from list of selected account IDs returned from Plaid Link flow.

If not provided, we will link the first checking account we encounter from the array of selected accounts returned in the metadata object from Plaid Link.
account_typeStringOptional. Must match either "CHECKING" or "SAVINGS".
provider_token_typeStringRequired. Must match "processor"

Linking multiple accounts at once

Currently, we do not link multiple accounts at once; you will need to send only one account ID.


Status Codesuccess AttributeDescription
200trueBank account successfully linked.
200falseBank account not successfully linked (public token may have expired; tokens expire in 30 minutes after creation).
202falseBank account linked, but in a frozen state. Requires manual review - email [email protected] for steps to unfreeze this bank account.
400falseCheck validation_details for more information. PRODUCT_NOT_READY indicates the account is waiting to be linked (with microdeposit verification, for instance).
401falseauthsignature or usersignature header was absent or incorrect.

Fuzzy Name Match Algorithm


Fuzzy Name Match Algorithm

Within the response body of /link_account you may see the error message: "Bank account linked, but in a frozen state. Requires manual review - contact support to unfreeze this bank account."

Read more about the Fuzzy Name Match Algorithm HERE

It is recommended that you wait until an end user passes KYC before you allow them to link an account.

If a user fails KYC, there is a risk that the account that they linked will be frozen and you will get the following error message: "Bank account linked, but in a frozen state. Requires manual review - contact support to unfreeze this bank account."

Steps to unfreezing a linked account can be found HERE

Legacy Plaid Integration - Link Token & Plaid Public Key


DEPRECATED: Legacy Plaid Integration - Link Token & Plaid Public Key

If you integrated Plaid through the Sila API before July 2021, you may have a legacy integration.

Per Plaid's request, the Plaid Link token integration was deprecated on May 2022.

Please establish a direct relationship with Plaid, https://plaid.com/docs/auth/partnerships/sila-money/ and begin integration with the Plaid processor token as soon as possible.

Direct Accounts or Manual Account Linking


Direct Account (manual) linking and Receive Only Entities have been prohibited due to a more restrictive regulatory environment.

  • As of July 2022 direct (manual) account linking was discontinued.
  • As of January 2023 the receive only kyc level was discontinued.

What’s Next

The following are secondary endpoint that can not be used until the primary /link_account endpoint has been successfully called as well as supporting documentation.