/link_account
Links a bank account to a verified entity with a Plaid processor token or an MX authorization code
This endpoint accepts an account ID and either an MX authorization code or a Plaid processor token.
Once an account is linked, transaction endpoints should continue to work unless the account is manually removed using /delete_account
.
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
.
Plaid vs MX in the Request
Once you have obtained a Plaid processor token or MX authorization code, you can link an end user's account.
Plaid
- Pass the Plaid
processor_token
in theprovider_token
parameter - Set the
provider
asplaid
- Set
provider_token_type
asprocessor
NOTE: Do not link the same account multiple times with a different processor_token. Doing so will create additional payment instruments, and Plaid with invalidate the previous processor_token.
MX
- Pass the MX
authorization_code
in theprovider_token
parameter - Set the
provider
asmx
- Set
provider_token_type
asprocessor
.
To verify: You can use the /get_account_balance endpoint and pass "account_name" to verify bank account link.
Request
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 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",
"reference": "<your unique id>"
},
"provider_token": "processor-xxx-xxx", //required
"provider": "plaid", //required
"account_name": "Custom Account Name",
"selected_account_id": "selected_account_id",
"account_type": "Checking",
"provider_token_type": "processor"
}
***Link Account with MX
{
"header": {
"created": 1234567890,
"app_handle": "handle.silamoney.eth",
"user_handle":"user.silamoney.eth",
"version": "0.2",
"reference": "<your unique id>"
},
"provider_token": "authorization_code-xxx-xxx", //required
"provider": "mx", //required
"account_name": "Custom Account Name",
"provider_token_type": "processor"
}
***
HTTP/1.1 200 OK
{
"success": true,
"message": "Bank account successfully linked with status \"processor_token\".",
"reference": "1727283525",
"account_name": "<account_name>",
"account_owner_name": "",
"payment_instrument_id": "<uuid string>",
"entity_name": "",
"match_score": 0.825,
"provider": "PLAID",
"web_debit_verified": true,
"capabilities": {
"aba_routing_number": "<routing_number>",
"fednow": {
"credit_enabled": false,
"debit_enabled": false
},
"rtp": {
"credit_enabled": true,
"debit_enabled": true
}
},
"status": "SUCCESS",
"response_time_ms": "1418"
}
***
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.
Request Attributes
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 | Required. 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 | Required. Plaid: plaid MX: mx |
account_name | String | Optional. Min length 1, Max length 40, default value if not sent in request is “default” NOTE- We 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. 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_type | String | Optional. "CHECKING" |
provider_token_type | String | Required. "processor" |
Linking multiple accounts at once
Currently, we do not link multiple accounts at once; you will need to send only one account ID.
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 - contact support 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."
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 about 2 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.