W-9 Implementation Guide - API
Guide to providing relevant W-9 details during user onboarding
Fewer W-9 fields for individualsFor U.S. individuals, one certification field replaces the W-9 field set:
is_not_subject_backup_withholding. zerohash creates the signature and certification fields. It does this for customers who onboard through the zerohash Onboarding SDK, and for API requests that send the field without the other W-9 fields. zerohash still accepts all current fields, so your integration keeps working without changes. Entity requirements do not change.
What is a W-9?
A W-9 is the IRS form that U.S. persons use to certify their U.S. tax status and give their taxpayer identification number (TIN). U.S. persons are U.S. citizens, green card holders, U.S. tax residents and entities formed in the U.S. Individuals give an SSN or ITIN. Entities give an EIN. A valid W-9 on file exempts the participant from 24% backup withholding on U.S.-source income.
zerohash creates certified W-9 forms from the data that you send through the API. The W-9 has no variants. Every U.S. person uses the same form, for individuals and for every entity type. For non-U.S. persons, see the W-8 Implementation Guide.
If you are not sure which requirements apply to your customers, contact your zerohash account team.
When to send W-9 information
Send W-9 information when you onboard a U.S. person through the zerohash U.S. flow. Participants onboarded through zerohash EU or other non-U.S. entities follow local tax rules and do not need a W-form.
- Individuals. Send W-9 information when the participant is a U.S. citizen, a green card holder or a U.S. tax resident. A U.S. citizen who lives abroad and has a U.S. tax ID also needs a W-9.
- Entities. Send W-9 information when the entity is formed or organized under U.S. law. Examples are U.S. corporations, partnerships, LLCs, trusts and estates.
zerohash treats a participant as a U.S. person if citizenship_code is US or jurisdiction_code is a U.S. jurisdiction when you create the participant.
What you send for U.S. individuals
The products and services that you use at zerohash set what you send. Your account team can confirm which case applies to you.
Case 1: name, address and tax ID
For some integrations, zerohash needs only the data that you already send for KYC:
first_nameandlast_name- the address:
address_one,city,jurisdiction_codeandzip date_of_birthcitizenship_codetax_id: the customer's SSN or ITIN, 9 digits
This is the full requirement for Case 1, through the API and the Onboarding SDK. Do not send is_not_subject_backup_withholding or other W-9 fields.
Case 2: name, address, tax ID and the backup withholding certification
Send everything in Case 1. Also send the backup withholding certification:
is_not_subject_backup_withholdingtrue: the customer certifies that they are not subject to backup withholding.false: the customer is subject to backup withholding. zerohash still onboards the customer. Backup withholding applies to their taxable proceeds.
Through the API, send this field alone or with the full W-9 field set. See API: send the field alone or the full set.
Do not send is_exempt_foreign_person for a U.S. person. Send one certification field only.
Show the certification to the customer
For Case 2, collect the certification from the customer in your UI. Show the certification statement next to the checkbox. Use the Part II certification language of IRS Form W-9 as your reference.
The zerohash Onboarding SDK shows this text, with the checkbox selected by default:
Keep checked if you have not been notified by the IRS that you are subject to backup withholding.
I am not subject to backup withholding and this serves as a formal signature certifying W-9 requirements.
To see how the SDK collects this data, see Tax Data Collection - KYCaaS.
What zerohash creates for you
zerohash fills in the other W-9 fields when it saves the record. It does this when:
- a customer certifies in the Onboarding SDK, or
- your API request sends
is_not_subject_backup_withholdingwithout the other W-9 fields.
| Field | What zerohash sets |
|---|---|
signature | The participant's first and last name |
signature_timestamp | The time that zerohash saves the record. Through the API, you can send your own value. |
w_form_certification | The same time as signature_timestamp |
is_w_form_certified | true |
payee_exemption and fatca_reporting_exemption | NONE |
zerohash creates these values for true and for false. A customer who is subject to backup withholding still has a certified W-9.
API: send the field alone or the full set
Through the API, zerohash creates the W-9 fields only when your request has is_not_subject_backup_withholding and none of these fields:
signaturew_form_certificationis_w_form_certifiedb_notice_receiptpayee_exemptionfatca_reporting_exemption
If your request has one of these fields, zerohash does not create the others. It checks your request against the full W-9 field set, as before. Send all of these fields or none of them. If you send only some of them, zerohash can reject the request.
Use the actual certification time
You can send signature_timestamp with is_not_subject_backup_withholding. zerohash still creates the other fields and uses your time for w_form_certification. Send the time that the customer certified when it is earlier than your API call, for example in a backfill. Use milliseconds since the Unix epoch.
Request examples
Create a U.S. individual (Case 2, API)
Example POST /participants/customers/new request:
{
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]",
"address_one": "123 Main St.",
"address_two": "Suite 1000",
"city": "Chicago",
"zip": "12345",
"jurisdiction_code": "US-IL",
"phone_number": "15557778888",
"date_of_birth": "1985-09-02",
"id_number_type": "us_passport",
"id_number": "123456789",
"citizenship_code": "US",
"tax_id": "000-00-0000",
"signed_timestamp": 1603378501286,
"kyc": "pass",
"kyc_timestamp": 1603378501286,
"sanction_screening": "pass",
"sanction_screening_timestamp": 1603378501286,
"signed_agreements": [
{
"type": "user_agreement",
"region": "us",
"signed_timestamp": 1603378501286
}
],
"is_not_subject_backup_withholding": true
}For Case 1, send the same request without is_not_subject_backup_withholding.
Update an existing U.S. individual (Case 2, API)
Example PATCH /participants/customers/{participant_code} request:
{
"is_not_subject_backup_withholding": true,
"signature_timestamp": 1667504636159
}signature_timestamp is optional. Send it when the customer certified before your API call. To add a missing SSN or ITIN, include tax_id.
Fields you no longer need to send for individuals
zerohash still accepts all of these fields. Existing integrations keep working without changes. There is no migration deadline. If you send a field, zerohash uses your value.
| Field | What zerohash sets (Onboarding SDK and API) |
|---|---|
signature | The participant's first and last name |
signature_timestamp | The time it saves the record, unless you send a time |
w_form_certification | The same time as signature_timestamp |
is_w_form_certified | true |
payee_exemption | NONE |
fatca_reporting_exemption | NONE |
b_notice_receipt | Not set. zerohash no longer collects it |
Through the API, zerohash sets these values only when your request has no W-9 field other than is_not_subject_backup_withholding and signature_timestamp. See API: send the field alone or the full set.
Do you already collect certified W-9 forms?
If you collect signed W-9 forms yourself:
- Upload each form with
POST /participants/documentsand the correct document type. - Send
is_not_subject_backup_withholdingwith the answer on the form. - Send
signature_timestampwith the date that the customer signed the form.
Do this for existing customers, and for each new customer. If the customer's W-9 data changes, upload a new W-9.
Deadlines for existing participants
For Case 2:
- You can send
is_not_subject_backup_withholdingnow. - Send it for each U.S. individual onboarded on or after January 1, 2026. The deadline is 7:00 PM UTC on December 31, 2026.
- If zerohash does not have the field by then, zerohash locks the participant on January 1, 2027. When zerohash gets the field, it changes the status back to
approvedautomatically. - Participants onboarded before January 1, 2026 have until December 31, 2027. zerohash does not lock them on January 1, 2027.
For Case 1:
- You can send a missing
tax_idnow. - From January 1, 2027, send name, address and
tax_idfor every new participant at onboarding. - zerohash does not restrict existing participants who have no
tax_id. Missing data makes year-end tax reports incomplete. zerohash shares reconciliation reports that list the participants with missing data.
To check a participant's status, use GET /participant/{participant_code}/basic_info. For status definitions, see Participant and Account Statuses and Locking.
Backfill existing participants
You can send the missing data in these ways:
- Send
PATCH /participants/customers/{participant_code}for each participant. For Case 2, includeis_not_subject_backup_withholding. See API: send the field alone or the full set. - Send a CSV file to your account team.
- If you use the zerohash Onboarding SDK, open it with
onboardingFlow: "tax_only". See Tax Data Collection - KYCaaS.
The API rate limit is 2,000 requests per rolling 10 seconds per IP address. The limit applies across all endpoints and includes your live traffic. Plan your backfill to stay under it. To retry safely, see Request IDs and idempotency.
Entity participants
Entity W-9 requirements do not change. For each U.S. entity, send the full W-9 data:
- legal name, address,
tax_id(EIN) andentity_type dba_name, if the entity has onepayee_exemptionandfatca_reporting_exemption, orNONEif no exemption appliesis_not_subject_backup_withholdingandb_notice_receiptis_w_form_certifiedwithw_form_certification, andsignaturewithsignature_timestamp
Collect these entity data points in your UI:
- The entity's DBA (doing business as) name, if it is different from its legal name.
- The entity type. Use one of these values to create a certified W-9:
- C_CORPORATION
- S_CORPORATION
- PARTNERSHIP
- TRUST_ESTATE
- LLC_C (an LLC taxed as a C corporation)
- LLC_P (an LLC taxed as a partnership)
- LLC_S (an LLC taxed as an S corporation)
- SOLE_PROPRIETOR
- OTHER
Create an entity
Example POST /participants/entity/new request:
{
"platform_code": "PLAT01",
"entity_name": "Entity Name",
"legal_name": "Legal Name",
"contact_number": "15557778888",
"website": "company.com",
"date_established": "1985-09-02",
"entity_type": "llc_s",
"address_one": "123 Main St.",
"address_two": "Suite 1000",
"city": "Chicago",
"postal_code": "12345",
"tax_id": "000-00-0000",
"id_issuing_authority": null,
"risk_rating": null,
"sanction_screening": "pass",
"sanction_screening_timestamp": 1603378501286,
"self_certification_timestamp": 1667504636159,
"signed_timestamp": 1603378501286,
"signed_agreements": [
{
"type": "user_agreement",
"region": "us",
"signed_timestamp": 1603378501286
}
],
"submitter_email": "[email protected]",
"submitter_first_name": "Jon",
"submitter_last_name": "Doe",
"submitter_title": "Mr.",
"control_persons": [
{
"name": "John Smith",
"email": "[email protected]",
"address_one": "123 Main St.",
"address_two": "Suite 1000",
"city": "Chicago",
"postal_code": "12345",
"jurisdiction_code": "US-IL",
"date_of_birth": "1985-09-02",
"phone_number": "15557778888",
"citizenship_code": "US",
"tax_id": "000-00-0000",
"id_number_type": "us_passport",
"id_number": "123456789",
"id_issuing_authority": null,
"sanction_screening": "pass",
"sanction_screening_timestamp": 1603378501286,
"kyc": "pass",
"kyc_timestamp": 1603378501286,
"control_person": 1
}
],
"beneficial_owners": [
{
"name": "John Smith",
"email": "[email protected]",
"address_one": "123 Main St.",
"address_two": "Suite 1000",
"city": "Chicago",
"postal_code": "12345",
"jurisdiction_code": "US-IL",
"date_of_birth": "1985-09-02",
"phone_number": "15557778888",
"citizenship_code": "US",
"tax_id": "000-00-0000",
"id_number_type": "us_passport",
"id_number": "123456789",
"id_issuing_authority": null,
"sanction_screening": "pass",
"sanction_screening_timestamp": 1603378501286,
"kyc": "pass",
"kyc_timestamp": 1603378501286,
"beneficial_owner": 1,
"role": ""
}
],
"incorporation_address": {
"address_one": "string",
"address_two": "string",
"city": "string",
"jurisdiction_code": "IT-25",
"postal_code": "string"
},
"b_notice_receipt": false,
"is_w_form_certified": true,
"w_form_certification": 1667504636159,
"signature": "signature_data",
"signature_timestamp": 1667504636159,
"payee_exemption": "NONE",
"fatca_reporting_exemption": "NONE",
"is_not_subject_backup_withholding": true,
"dba_name": "ABC Trading Co",
"other_entity_type": "Trust",
"jurisdiction_code": "US-IL"
}Update an existing entity
Example PATCH /participants/entity/{participant_code} request:
{
"b_notice_receipt": false,
"is_w_form_certified": true,
"w_form_certification": 1667504636159,
"signature": "signature_data",
"signature_timestamp": 1667504636159,
"payee_exemption": "NONE",
"fatca_reporting_exemption": "NONE",
"is_not_subject_backup_withholding": true,
"dba_name": "ABC Trading Co",
"other_entity_type": "Trust"
}For entities, always send is_w_form_certified with w_form_certification, and signature with signature_timestamp.
Send updates as you do today
If a customer's tax information changes, PATCH the same endpoint with the new values. Examples are a name change, an address change, a new certification or a resolved B-Notice. zerohash certifies the record again.
Tax glossary
Tax identification number (tax_id)
tax_id)The customer's SSN or ITIN, or the entity's EIN. Send 9 digits.
Backup withholding (is_not_subject_backup_withholding)
is_not_subject_backup_withholding)The customer's backup withholding certification.
true: the customer certifies that they are not subject to backup withholding.false: the customer is subject to backup withholding.
Signature and signature time (signature, signature_timestamp)
signature, signature_timestamp)signature: the first and last name that the customer signs with.signature_timestamp: the time that the customer signed.
For individuals, zerohash sets both fields. See What zerohash creates for you.
W-form certification (is_w_form_certified, w_form_certification)
is_w_form_certified, w_form_certification)is_w_form_certified: shows that the W-form is certified.w_form_certification: the time of the certification.
Send both fields together. For individuals, zerohash sets both fields.
B-Notice (b_notice_receipt)
b_notice_receipt)A B-Notice is an IRS letter. It tells a payer, such as zerohash, that a customer's name and TIN do not match IRS records. Send true if the customer has a B-Notice. The customer is then subject to backup withholding until they certify again.
Tax exemptions (payee_exemption, fatca_reporting_exemption)
payee_exemption, fatca_reporting_exemption)payee_exemption: the payee exemption code,1to13, orNONE.fatca_reporting_exemption: the FATCA exemption code,AtoM, orNONE.
Most customers use NONE. For individuals, zerohash sets NONE.
Updated 8 days ago