W-9 Implementation Guide - API

Guide to providing relevant W-9 details during user onboarding

📘

Fewer W-9 fields for individuals

For 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_name and last_name
  • the address: address_one, city, jurisdiction_code and zip
  • date_of_birth
  • citizenship_code
  • tax_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_withholding
    • true: 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_withholding without the other W-9 fields.
FieldWhat zerohash sets
signatureThe participant's first and last name
signature_timestampThe time that zerohash saves the record. Through the API, you can send your own value.
w_form_certificationThe same time as signature_timestamp
is_w_form_certifiedtrue
payee_exemption and fatca_reporting_exemptionNONE

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:

  • signature
  • w_form_certification
  • is_w_form_certified
  • b_notice_receipt
  • payee_exemption
  • fatca_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.

FieldWhat zerohash sets (Onboarding SDK and API)
signatureThe participant's first and last name
signature_timestampThe time it saves the record, unless you send a time
w_form_certificationThe same time as signature_timestamp
is_w_form_certifiedtrue
payee_exemptionNONE
fatca_reporting_exemptionNONE
b_notice_receiptNot 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:

  1. Upload each form with POST /participants/documents and the correct document type.
  2. Send is_not_subject_backup_withholding with the answer on the form.
  3. Send signature_timestamp with 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_withholding now.
  • 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 approved automatically.
  • 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_id now.
  • From January 1, 2027, send name, address and tax_id for 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:

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) and entity_type
  • dba_name, if the entity has one
  • payee_exemption and fatca_reporting_exemption, or NONE if no exemption applies
  • is_not_subject_backup_withholding and b_notice_receipt
  • is_w_form_certified with w_form_certification, and signature with signature_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)

The customer's SSN or ITIN, or the entity's EIN. Send 9 digits.

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: 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: 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)

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: the payee exemption code, 1 to 13, or NONE.
  • fatca_reporting_exemption: the FATCA exemption code, A to M, or NONE.

Most customers use NONE. For individuals, zerohash sets NONE.


Did this page help you?