W-9 Collection & Storage

Overview

A firm must generate a W-9 form anytime it engages in a business relationship with an independent contractor or pays another party in a non-employer manner. If a firm determines that it is in such a relationship, the first step is to issue Form W-9, Request for Taxpayer Identification Number and Certification, or a substitute form.

An individual or entity (Form W-9 requester, or UserUser - A single end-user of your application. Each user has a unique userId, which should be stored in your database and used to make API requests on behalf of this individual. within Abound) who is required to file an information return with the IRS must obtain the correct taxpayer identification number (TIN), which may be a social security number (SSN), an individual taxpayer identification number (ITIN), an adoption taxpayer identification number (ATIN), or an employer identification number (EIN), to report on an information return the amount paid, or other amounts reportable on an information return. Examples of information returns include, but are not limited to:

The W-9 should be kept in the payer's files for four years for future reference in case of any questions from the user or the IRS. Note that a PayerPayer - An entity that makes payments for: services performed by independent contractors (1099-NEC), interest on a business debt (1099-INT), and payment card transactions settled on behalf of merchants (1099-K). does NOT submit a W-9 to the IRS.

Creating a Form W-9

To create a Form W-9, use an existing userId and payerId and call the POST /users/{userId}/documents API endpoint. Make sure that the user's profile information is up to date before creating a Form W-9 document.

curl \
  --request POST \
  --url https://sandbox-api.withabound.com/v2/users/<<testUserId>>/documents \
  --header 'Authorization: Bearer <<apiKey>>' \
  --header 'Content-Type: application/json' \
  --data '{
    "documents": [
      {
        "type": "w9",
        "year": 2021,
        "payerId": "<<testPayerId>>",
        "taxClassification": "soleProprietor",
        "exemptPayeeCode": "7",
        "exemptFatcaCode": "H",
        "accountNumbers": [
          "1234567890",
          "1234567891"
        ],
        "hasCertified": true,
        "certificationTimestamp": 1618859959452
      }
    ]
  }'
const fetch = require('node-fetch');

const url = 'https://sandbox-api.withabound.com/v2/users/<<testUserId>>/documents';
const options = {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    Authorization: 'Bearer <<apiKey>>'
  },
  body: JSON.stringify({
    documents: [
      {
        type: 'w9',
        year: 2021,
        payerId: '<<testPayerId>>',
        taxClassification: 'soleProprietor',
        exemptPayeeCode: '7',
        exemptFatcaCode: 'H',
        accountNumbers: ['10000001', '10000002'],
        hasCertified: true,
        certificationTimestamp: 1618859959452
      }
    ]
  })
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error('error:' + err));
import requests

url = "https://sandbox-api.withabound.com/v2/users/<<testUserId>>/documents"

payload = {"documents": [
        {
            "type": "w0",
            "year": 2021,
            "payerId": "<<testPayerId>>",
            "taxClassification": "soleProprietor",
            "exemptPayeeCode": "7",
            "exemptFatcaCode": "H",
            "accountNumbers": ["1234567890", "1234567891"],
            "hasCertified": True,
            "certificationTimestamp": 1618859959452
        }
    ]}
headers = {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Authorization": "Bearer <<apiKey>>"
}

response = requests.request("POST", url, json=payload, headers=headers)

print(response.text)
// import com.squareup.okhttp.*;
// import com.google.gson.JsonObject;
// import com.google.gson.JsonArray;

OkHttpClient client = new OkHttpClient();

JsonObject requestBody = new JsonObject();
JsonArray documents = new JsonArray();
JsonObject w9 = new JsonObject();
JsonArray w9AccountNumbers = new JsonArray();

w9.addProperty("type", "w9");
w9.addProperty("year", 2021);
w9.addProperty("payerId", "<<testPayerId>>");
w9.addProperty("taxClassification", "soleProprietor");
w9.addProperty("exemptPayeeCode", "7");
w9.addProperty("exemptFatcaCode", "H");
w9.addProperty("hasCertified", true);
w9.addProperty("certificationTimestamp", 1618859959452);

w9AccountNumbers.add("1234567890");
w9AccountNumbers.add("1234567891");

w9.add("accountNumbers", w9AccountNumbers);

documents.add(w9);

requestBody.add("documents", documents);

MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, requestBody.toString());
Request request = new Request.Builder()
  .url("https://sandbox-api.withabound.com/v2/users/<<testUserId>>/documents")
  .post(body)
  .addHeader("Accept", "application/json")
  .addHeader("Content-Type", "application/json")
  .addHeader("Authorization", "Bearer <<apiKey>>")
  .build();

Response response = client.newCall(request).execute();
package main

import (
    "bytes"
    "fmt"
    "net/http"
    "io/ioutil"
)

func main() {

    url := "https://sandbox-api.withabound.com/v2/users/<<testUserId>>/documents"

    var requestBody = []byte(`{
        "documents": [
            {
                "type": "w9",
                "year": 2021,
                "payerId": "<<testPayerId>>",
                "taxClassification": "soleProprietor",
                "exemptPayeeCode": "7",
                "exemptFatcaCode": "H",
                "accountNumbers": [
                    "1234567890",
                    "1234567891"
                ],
                "hasCertified": true,
                "certificationTimestamp": 1618859959452
            }
        ]
    }`)

    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))

    req.Header.Add("Accept", "application/json")
    req.Header.Add("Content-Type", "application/json")
    req.Header.Add("Authorization", "Bearer <<apiKey>>")

    res, _ := http.DefaultClient.Do(req)

    defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)

    fmt.Println(res)
    fmt.Println(string(body))

}
// using RestSharp;

var client = new RestClient("https://sandbox-api.withabound.com/v2/users/<<testUserId>>/documents");
var request = new RestRequest(Method.POST);
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", "Bearer <<apiKey>>");
request.AddJsonBody(new {
  documents = new[] {
    new {
      type = "w9",
      year = 2021,
      payerId = "<<testPayerId>>",
      taxClassification = "soleProprietor",
      exemptPayeeCode = "7",
      exemptFatcaCode = "H",
      accountNumbers = new[] {"10000001", "10000002"},
      hasCertified = true,
      certificationTimestamp = 1618859959452
    }
  }
});
IRestResponse response = client.Execute(request);
require 'uri'
require 'net/http'
require 'openssl'
require 'json'

url = URI("https://sandbox-api.withabound.com/v2/users/<<testUserId>>/documents")
requestBody = {
  documents: [
    {
      type: 'w9',
      year: 2021,
      payerId: '<<testPayerId>>',
      taxClassification: 'soleProprietor',
      exemptPayeeCode: '7',
      exemptFatcaCode: 'H',
      accountNumbers: ['10000001', '10000002'],
      hasCertified: true,
      certificationTimestamp: 1618859959452
    }
  ]
}

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Accept"] = 'application/json'
request["Content-Type"] = 'application/json'
request["Authorization"] = 'Bearer <<apiKey>>'
request.body = requestBody.to_json

response = http.request(request)
puts response.read_body
{
  "data": [
    {
      "documentId": "documentId_testefbd5d3d9ee9526ef9ff89a7c6b879174170",
      "documentURL": "https://tax-documents-sandbox.s3.us-west-2.amazonaws.com/test62ae93bafa6310aa9952e8b3bf5796443111/2021_Form_W-9.pdf?AWSAccessKeyId=AKIA6C6AUYYBZMXK74XQ&Expires=1630083012&Signature=K4WEkWIWQZMQe6WRHQnCjAI27HI%3D",
      "documentName": "2021 Form W-9",
      "type": "w9",
      "year": "2021",
      "createdTimestamp": 1629474064577
    }
  ]
}

Using Abound to Create a Custom W-9 Substitute

A PayerPayer - An entity that makes payments for: services performed by independent contractors (1099-NEC), interest on a business debt (1099-INT), and payment card transactions settled on behalf of merchants (1099-K). may create its own substitute Form W-9 using the Abound API if its content is substantially similar to the official IRS Form W-9 and it satisfies certain certification requirements, set forth below. Using Abound's API, a PayerPayer - An entity that makes payments for: services performed by independent contractors (1099-NEC), interest on a business debt (1099-INT), and payment card transactions settled on behalf of merchants (1099-K). may collect Form W-9 data as part of its onboarding or account setup UX. What the IRS requires on any custom substitute Form W-9 is that, similar to what's shown on the official Form W-9, under penalties of perjury the:

  • payee's (user's) TIN is correct,
  • user is not subject to backup withholding due to failure to report interest and dividend income,
  • user is a U.S. person, and
  • FATCA code entered on this form (if any) indicating that the user is exempt from FATCA reporting is correct

Disclosure Statements

It is important to note that you must receive authorization for Abound to generate Form W-9 documents. This can be done by including the following disclosures in your application and requiring the user to acknowledge and agree to the terms through the use of a checkbox or similar UI.

W-9 Certification

By using [Company's] services you agree that the information provided for Form W-9 is accurate and that you certify the provided information as follows:

"I certify, under penalty of perjury that:

  • Taxpayer Identification Number or Social Security Number I provided is correct;
  • I am not subject to backup withholding because: (a) I am exempt from backup withholding, or (b) I have not been notified by the Internal Revenue Service (IRS) that I am subject to backup withholding as a result of a failure to report all interest or dividends, or (c) the IRS has notified me that I am no longer subject to backup withholding; and
  • I am a U.S. citizen or other U.S. person; and
  • The FATCA code(s) entered (if any) indicating that I am exempt from FATCA reporting is correct.

The Internal Revenue Service does not require your consent to any provision of this document other than the certifications required to avoid backup withholding."

Electronic 1099 Consent

By using [Company's] services you agree to and understand the following:

  • You are opting in to receiving an electronic copy of your 1099-[X] form.
  • This consent to receive an electronic 1099 will remain in place so long as you do not opt out.
  • Any electronic 1099s made available to you will remain available indefinitely until you request that your,[Company] account be closed and/or deleted.

Did this page help you?