How do I use the linkExternalAccount (Plaid) Method for my web application?

Using Transact API's integration with Plaid, you can easily facilitate connecting your investor’s bank account for making investments.

Using Transact API's integration with Plaid, you can easily facilitate connecting your investor’s bank account for making investments. This article discusses the way to do this on a web application.

The following is a diagram that explains how the connectivity is established on portals powered by TransactAPI:

Once you invoke a call to /LinkExternalAccount. This call will give you a response with a URL. The URL should be used in the div section so your investor user sees the Plaid widget loaded for them. They interact within the widget by authenticating the desired bank account, selecting the specific account etc.

There may be 2 actions at this point. The user may prematurely exit the widget, in which case, the callback URL processes the OnExit(). If the user completes the process within the widget, then the onSuccess() collects the data (i.e. Routing number and Account number) and makes the necessary updates into your account.

NOTE: If the investor needs to change the connected account, you may invoke /updateLinkExternalAccount

Below are some examples, The first is code using HTML, CSS, Javascript and Axios. The second is using PHP

<div id="link_button">Link Credit Card</div>
<div id="iframe_container">
<div id="close_button">Close</div>
<iframe id="tapi_iframe"></iframe>
document.getElementById('link_button').onclick = function(){
const options = {
method: 'POST',
url: '',
header: {'content-type': 'application/json'},
data: {
clientID: 'yourClientID',
developerAPIKey: 'yourDeveloperAPIKey',
accountId: 'theAccountID'
window.addEventListener('message', function(event) {
let response = JSON.parse(;
if(response.statusCode == 101) { closeStripeIframe(); }
else if(response.errorCode) {} //Handle error case (not required)
.then(function (response) {
document.getElementById('iframe_container').style.display = 'block';
document.getElementById('tapi_iframe').src =;
.catch(function (error) {
document.getElementById('close_button').onclick = function () {

function closeStripeIframe() {
   document.getElementById('iframe_container').style.display = 'none';
#link_button {
text-align: center;
padding: 10px;
border-radius: 5px;
background-color: black;
color: white;
width: 150px;
cursor: pointer;
margin: 20px;

#tapi_iframe {
width: 600px;
height: 720px;
border: none;

#iframe_container {
display: none;
padding: 10px;
border-radius: 5px;
-webkit-box-shadow: 0010px rgb(122, 122, 122);
box-shadow: 0010px rgb(122, 122, 122);

#close_button {
text-align: right;
float: right;
text-decoration: underline;
cursor: pointer;
width: fit-content;

Below is an example code for this method:

if (isset($_POST['reg_submit'])) {

//set POST variables
$url = '';
$fields = array(
'developerAPIKey' => $_POST['developerAPIKey'],
'clientID' => $_POST['clientID'],
'accountId' => $_POST['accountId'],
// 'ExtAccountfullname' => $_POST['ExtAccountfullname'],
// 'Extnickname' => $_POST['Extnickname'],
echo 'Request' . "<br>";
echo '=======';
echo '<pre>';
echo '</pre>';

//url-ify the data for the POST
foreach ($fields as $key => $value) {
$fields_string .= $key . '=' . $value . '&';
rtrim($fields_string, '&');

//open connection
$ch = curl_init();

//set the url, number of POST vars, POST data
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERPWD, 'nc_admin_rest_basic:nc_admin_basic_pwd');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POST, count($fields));
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
//execute post
$result = curl_exec($ch);
$res = json_decode($result);
echo "<br>" . 'Response' . "<br>";
echo '========';
echo '<pre>';
$arrContextOptions = array(
"ssl" => array(
"verify_peer" => false,
"verify_peer_name" => false,
if ($res->statusCode == 101) {
$result = file_get_contents($res->accountDetails, false, stream_context_create($arrContextOptions));
// print_r("<script>$(document).ready(function () {;});</script>");
} else {
// echo '<div id="plaidAccounts"></div>';
echo '</pre>';

//close connection
<section id="wufoo_form_container" style=" min-height:500px;">
<h2>Link External Account</h2>
<div class="form-container">
<div class="container-list">
<form action="" method="post" id="investor_form_reg" class="cmxform" enctype="multipart/form-data">
<div class="field-tabs">
<div class="account-details">clientID * </div>
<div class="field-sets">
<input name="clientID" id="clientID" value="<?php echo $_POST['clientID']; ?>" type="text" placeholder="clientID" class="input-text-box required"/>
<div class="field-tabs">
<div class="account-details">developerAPIKey *</div>
<div class="field-sets">
<input name="developerAPIKey" id="developerAPIKey" value="<?php echo $_POST['developerAPIKey']; ?>" type="text" placeholder="developerAPIKey" class="input-text-box required"/>
<div class="field-tabs">
<div class="account-details">Account ID * </div>
<div class="field-sets">
<input name="accountId" id="accountId" value="<?php echo $_POST['accountId']; ?>" type="text" placeholder="Account ID" class="input-text-box required"/>
<div class="clear"></div>
<div class="clear">&nbsp;</div>
<div class="field-tabs">
<div class="account-details"></div>
<div class="field-sets">
<input name="reg_submit" type="submit" value="Submit" class="register_btn" style="display:inline">
<div class="clear"></div>