Authentication and Setup
TaxBandits offers a Drop-in UI for Form W-9 that can be seamlessly incorporated into your current systems with minimal setup.
Here are the steps to set up Drop-in UI in your application:
1. Authentication
To begin, you must construct a JWS using your API credentials. See how
Once JWS is constructed, you must pass it in the "Authentication: {JWS Value}" HTTP Header.
2. Get Transient Token
Once the JWS is created, send a request to obtain the Transient Token. The request body must include the allowable origins (domains). Only requests originating from these domains will be permitted to render the W-9 form.This helps prevent token reuse from unauthorized sources. This token will be valid for 15 minutes. You can get a new token if it expires.
We have enabled the Content Security policy with the Frame Ancestor directive in our drop-in UI. This allows only the domains specified when generating a transient token, ensuring each request is validated.
POST v2/transienttoken
Request Body
| Field | Type | Description |
|---|---|---|
| Origins | object[] | List your domains where you want to load the W-9 |
Request JSON:
{
"Origins": [
"https://developer.taxbandits.com/",
"https://{yourdomain.com}/"
]
}
Response Body
| Field | Type | Description |
|---|---|---|
| StatusCode | number | Returns the HTTP status codes like 200,300 etc. |
| StatusName | string | Name of the status code |
| StatusMessage | string | Detailed status message |
| TransientToken | string | A short-term token that lasts 15 minutes |
| TokenType | string | Type of the token provided |
| ExpiresIn | number | The expiry time of the token |
| Errors | object[] | Shows detailed error information |
| ID | string | Returns the validation error Id |
| Name | string | Name of the validation error |
| Message | string | Description of the validation error |
Response JSON:
{
"StatusCode": 200,
"StatusName": "OK",
"StatusMessage": "Successful API call",
"TransientToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiI1ODYxYTIwMzY5MWI0NDAwODk1OWU2NTBjYWNlN2ViZiIsImRyb3B1aWQiOiIzOGI5ZTllZS0wMGE1LTQ3N2MtYTExMS00NDM0YTIyYTg2ZWMiLCJleHAiOjE3MjE2MzI1NzcsImlhdCI6MTcyMTYzMTY3NywiaXNzIjoiaHR0cHM6Ly9vYXV0aC5zcGFuc3ByaW50LmNvbS92Mi8iLCJzdWIiOiI4NWY2OTJkN2RhYTEwNmJiIn0.L1YWjLpur2IWvE-0et9PlApBxqXpypG_bPYM0DEpmVg",
"TokenType": "Bearer",
"ExpiresIn": 900,
"Errors": null
}
Curl:
curl --location "https://testoauth.expressauth.net/v2/transienttoken" --header "authentication: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI4NWY2OTJkN2RhYTEwNmJiIiwic3ViIjoiODVmNjkyZDdkYWExMDZiYiIsImF1ZCI6IjU4NjFhMjAzNjkxYjQ0MDA4OTU5ZTY1MGNhY2U3ZWJmIiwiaWF0IjoxNzIwNTE5MzgwfQ.GzHXe7-qgrbMYIrHz783uPkHDh3P_1kwtXADwGsZjF0" --header "Content-Type: application/json" --data "{\"Origins\": [\"https://developer.taxbandits.com/\"]}"
3. Customize W-9 Form UI
Call the LoadFormW9() method using the transient token, which must include:
- Business details – BusinessId, PayerRef, or TIN
- Recipient details – PayeeRef, Name, Address
- TIN Matching preference – Set IsTINMatching to TRUE if you want to enable TIN Matching
- Customization elements — Theme and redirection URLs. Click here to see what you can customize .
Before making this call, ensure that the corresponding business (payer) has been added to the TaxBandits API. If not, the W-9s collected will be associated with the default business in your account. Learn More
- HTML
- CSS
- JS
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drop-in UI</title>
<!--
This JavaScript file loads the prebuilt W-9 form drop-in component
from the TaxBandits sandbox server for testing and development. -->
<script src="https://js.taxbandits.io/SB/Web/Dropin/v1.0.0/dropinW9.js"></script>
<!--
For Production, REPLACE the above sandbox script URL
with the production script below. -->
<!-- <script src="https://js.taxbandits.io/Web/Dropin/v1.0.0/dropinW9.js"></script> -->
</head>
<body>
<div class="container">
<div id="request-container" class="drpHide">
<!-- load the input fields inside the container -->
</div>
<button id="submit-button" class="btn btn-primary drpHide" onclick="getFormW9()">
Load Form W9
</button>
<div id="formLoad" class="mt-10">
<!-- Load the W9 form -->
</div>
</div>
</body>
</html>
*
{
box-sizing: border-box;
}
body
{
font-size: 16px;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
.p-4 {
padding: 1.5rem !important;
}
.text-error
{
color:#E82A21;
}
.fw-500
{
font-weight: 500;
}
.fs-12px
{
font-size: 12px;
}
.fs-14px
{
font-size: 14px;
}
.mt-4 {
margin-top: 1.5rem !important;
}
.mt-5 {
margin-top: 3rem !important;
}
.mb-3
{
margin-bottom: 0.75rem !important;
}
.shadow {
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;
}
.container {
max-width: 500px;
box-shadow: 0px 0px 5px #e7e7e7;
padding: 15px;
border-radius: 4px;
}
.form-control {
display: block;
width: 100%;
padding: .375rem .75rem;
font-size: 1rem;
font-weight: 400;
outline: none;
line-height: 1.5;
margin-top: 0.25rem !important;
color: #212529;
border: 1px solid #dee2e6;
border-radius: 4px;
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.text-grey
{
color:#4C6177
}
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
-webkit-box-shadow: 0 0 0 40px white inset !important;
}
.btn {
display: inline-block;
font-weight: 400;
text-align: center;
white-space: nowrap;
vertical-align: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border: 1px solid transparent;
padding: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: .25rem;
transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.btn-primary {
color: #fff;
background-color: #007bff;
border-color: #007bff;
}
async function getFormW9() {
const transientToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiI4NGFkODQ3MjY3MTY0OTk3YTdkOWM3ZGIyNzcyNzBjOSIsImRyb3B1aWQiOiJjNjk0NGE5MS0wNzI0LTQ3ZWEtYjlmZC01MDYwZDg5MjAxNWYiLCJleHAiOjE3MjQ0MTE5MTQsImlhdCI6MTcyNDQxMTAxNCwiaXNzIjoiaHR0cHM6Ly90ZXN0b2F1dGguZXhwcmVzc2F1dGgubmV0L3YyLyIsInN1YiI6ImE0ZDUxZjZlMzVlNTk3ODgifQ.vJlLQ0rwUDKj_T6-DqI9OxAvDwM4xu-TfKx4jxaZJCo';
const payLoad = {
"Requester": {
"PayerRef": null,
"BusinessId": null,
"TIN": null,
"DBAId": null,
"DBARef": null
},
"Recipient": {
"PayeeRef": "4646D",
"Name": "Michal",
"Address": {
"Address1": "2603 Kinsey Road",
"Address2": "Main Street",
"City": "Dothan",
"State": "AL",
"ZipCd": "36303"
},
"IsTINMatching": true
},
"Customization": {
"Theme": {
"TextboxDropdown": {
"FontColor": "#000000",
"Border": "#0851BF",
"BorderFocus": "#0851BF",
"BorderRadius": "4rem"
},
"Button": {
"PrimaryColor": "#f26c20",
"SecondaryColor": "#0d6efd",
"FontColor": "#000000"
},
"Label": {
"Color": "#0d6efd"
},
"Link": {
"Color": "#0d6efd"
},
"Text": {
"Heading": "#0d6efd",
"SubHeading": "#f26c20",
"Para": "#000000",
"HelpText": "#000000"
}
}
},
"RedirectUrls": {
"ReturnUrl": "https://example.com",
"CancelUrl": "https://example.com"
}
};
await loadFormW9(transientToken, payLoad);
}
4. Load W-9
Once LoadFormW9() is called, the script uses the transient token to securely communicate with the TaxBandits server.
The server validates the token and returns a secure, encrypted W-9 form URL. This URL is then embedded as an iframe in your application.
All sensitive configurations (like TIN Matching, payeeRef, and theme) are encrypted and bound to the token on the server side. Even though the form is rendered in the browser, the actual payload is never exposed in the network tab or browser console, protecting against client-side tampering or inspection.
5. Recipient Submits W-9
Recipients fill out and submit the W-9 form inside the iframe. The data is securely stored by TaxBandits and never exposed to your system.
You’ll receive submission status through:
- A webhook (if configured), or
- A message sent from the iframe to your frontend