/link_account
Links an end user's bank account to the verified entity in Sila.
This doc has been updated for Priority specifications.
Use either a Plaid processor token or MX authorization code to link an end user's external, personal bank account.
- We do not currently support linking multiple accounts with a single request.
- Both checking and savings accounts can be linked.
- External accounts can be linked to both individual and business entities.
- The same external account cannot be linked to the same entity more than once.
- We recommend waiting until KYC or KYB has been fully passed before linking any external bank accounts.
All external accounts will be frozen upon successful linking
External bank accounts will always be frozen upon linking for at least one of two reasons:
- The end user has not passed KYC/KYB yet. The account will be unfrozen when they pass.
- If passed, there is a small wait time for Priority to verify the account on their end.
We recommend subscribing to the Bank Account Frozen/Unfrozen Webhook to know when the account has been unfrozen. You can expect this webhook to arrive between 5-15 minutes after the account linking is done for end users that have already passed KYC.
Prerequisites to using /link_account
A separate contract with either Plaid or MX is required to use the Sila integrations with either provider. See below docs for more:
Plaid vs MX in the Request
PLAID
Do not re-use processor tokens
Processor tokens are meant for one, single use for linking one, single bank account. You should never be re-using processor tokens, regardless of what environment you are in.
- Pass the Plaid
processor_token
in theprovider_token
parameter - Set the
provider
asplaid
- Set
provider_token_type
asprocessor
MX
- Pass the MX
authorization_code
in theprovider_token
parameter - Set the
provider
asmx
- Set
provider_token_type
asprocessor
.
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": "app_handle",
"user_handle":"user_handle",
"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": "app_handle",
"user_handle":"user_handle",
"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" //required
}
***
HTTP/1.1 200 OK
{
"success": true,
"message": "Bank account successfully linked with status \"processor_token\".",
"reference": "1727283525",
"sila_reference_id": "sila_assigned_id",
"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_handle", # 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_handle", # 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_handle';
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_handle";
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_handle';
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_handle';
$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_handle';
$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" or "SAVINGS" |
provider_token_type | String | Required. "processor" |
Responses
Status Code | success | 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). |
Fuzzy Name Match Algorithm
Within the response body of /link_account
you may see an error message indicating a possible fuzzy name match failure.
The fuzzy name match algorithm validates that the person linking the account owns that account.
For next steps, and more information about the fuzzy name algorithm, see this doc 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.
Updated 5 days 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.