/link_account
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 Plaidprocessor_token
before you can link an account to anentity
.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
.
Plaid
- Pass the Plaid
processor_token
in theprovider_token
parameter, set theprovider
asPlaid
, and setprovider_token_type
asprocessor
.
MX
- Pass the MX
authorization_code
in theprovider_token
parameter, set theprovider
asmx
, and setprovider_token_type
asprocessor
.
NOTE: 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:
- The account is manually removed using
/delete_account
. - 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.
Instant ACH
If you are authorized to use the Instant ACH product - you will need to call
/check_instant_ach
before you can/issue_sila
with theprocessing_type: INSTANT_ACH
Requests
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
sandbox.silamoney.com
Content-Type: application/json
// if using OAuth2
Authorization: Bearer [GENERATED JWT TOKEN HERE]
// if using ECDSA
authsignature: [GENERATED AUTHSIGNATURE HEX STRING HERE]
usersignature: [GENERATED USERSIGNATURE HEX STRING HERE]
***Link Account with Plaid
{
"header": {
"created": 1234567890,
"app_handle": "handle.silamoney.eth",
"user_handle":"user.silamoney.eth",
"version": "0.2",
"crypto": "ETH",
"reference": "<your unique id>"
},
"provider_token": "processor-xxx-xxx",
"provider": "Plaid",
"account_name": "Custom Account Name",
"selected_account_id": "selected_account_id",
"provider_token_type": "processor"
}
***Link Account with MX
{
"header": {
"created": 1234567890,
"app_handle": "handle.silamoney.eth",
"user_handle":"user.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",
"web_debit_verified":true
}
***
Request - /link_account
// Plaid verification flow
const res = await Sila.linkAccount(
userHandle,
walletPrivateKey,
token,
accountName, // Account Name is not required
accountId, // Account Id parameters is required,
plaidTokenType, // Required.'processor,'
);
// MX verification flow
const res = await sila.linkAccountMX(
handle,
walletPrivateKey,
providerTokenType,
providerToken,
accountName,
selected_account_id
);
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(
userHandle,
walletPrivateKey,
accountNumber,
routingNumber,
accountName,
accountType
);
// 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.success);
console.log(res.data.message); // Bank account successfully linked
console.log(res.data.account_name);
console.log(res.data.match_score);
console.log(res.data.account_owner_name);
console.log(res.data.entity_name);
console.log(res.data.provider);
console.log(res.data.web_debit_verified); // true/false
### Link Account with MX
payload = {
"user_handle": user_handle,
"provider": "mx",
"provider_token_type": “processor”,
"provider_token":"<token_id>",
"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
payload={
"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"),
}
User.linkAccount(silaApp,payload,user_private_key)
### 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,
userPrivateKey,providerToken,provider,providerTokenType);
// 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.getAccountOwnerName());
System.out.println(parsedResponse.getEntityName());
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(
$handle,
$privateKey,
$provider,
$providerToken,
$providerTokenType,
$accountName
);
/**
* 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
Key | Type | Description |
---|---|---|
header | JSON object | Required. 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_token | String | Plaid + 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 |
provider | String | Plaid + Sila Integration: pass "plaid" as the provider MX + Sila Integration: pass mx as the provider. |
account_name | String | Optional. 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_id | String | Applicable 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. |
account_type | String | Optional. Must match either "CHECKING" or "SAVINGS". |
provider_token_type | String | Required. Must match "processor" |
selected_account_id
selected_account_id
The selected_account_id
is not required with a Plaid processor token as it is packaged inside the processor token.
- If provided, it should be an account ID in the array of selected accounts returned in the metadata object from Plaid Link.
- This ID can identify either a checking account or a savings account to link.
Linking multiple accounts at once
Currently, we do not link multiple accounts at once; you will need to send only one account ID (see selected_account_id above). If no account ID is provided, we will link the first checking account we encounter from the array of accounts the customer has at their chosen bank.
Responses
Status Code | success Attribute | Description |
---|---|---|
200 | true | Bank account successfully linked. |
200 | false | Bank account not successfully linked (public token may have expired; tokens expire in 30 minutes after creation). |
202 | false | Bank account linked, but in a frozen state. Requires manual review - email [email protected] for steps to unfreeze this bank account. |
400 | false | Check validation_details for more information. PRODUCT_NOT_READY indicates the account is waiting to be linked (with microdeposit verification, for instance). |
401 | false | authsignature 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.
Updated 5 months ago
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.