# W-8 and W-9 additional verifications

Learn how to collect certified tax documentation from connected accounts.

> W-8 and W-9 collection is available in private preview for US businesses. To request access, contact your Stripe account team or [Stripe Sales](https://stripe.com/contact/sales).

This workflow isn’t available when using [Accounts v2](https://docs.stripe.com/api/v2/core/accounts.md).

If you prefer a no-code solution, Stripe also offers a Dashboard-based way to collect W-8 and W-9 forms from your connected accounts. To learn more, see [Connect W-8 and W-9 onboarding](https://docs.stripe.com/connect/connect-w8-w9-onboarding.md).

The `us_w8_or_w9` Additional Verifications API allows you to enforce the mandatory collection and certification of tax documentation requirements for a connected account. Stripe identifies these requirements as [currently_due](https://docs.stripe.com/api/persons/object.md#person_object-requirements-currently_due) or [past_due](https://docs.stripe.com/api/persons/object.md#person_object-requirements-past_due) until the user (connected account) satisfies the requirement.

## W-8 and W-9 tax documentation

W-8 and W-9 forms provide certified tax documentation for your connected accounts, including:

- **W-8 forms**: Allows non-US taxpayers to certify their name, address, foreign TIN (if applicable), and claim tax treaty benefits if eligible
- **W-9 forms** for US taxpayers to certify their name and Tax Identification Number (TIN)

Benefits of collecting W-8 and W-9 forms include:

- Protection against IRS fines (up to 340 USD per incorrect submission)
- Accurate tax reporting for 1099-K/1099-NEC forms
- Digital document collection without PDFs or wet signatures
- Pre-populated forms using existing account information
- Downloadable PDF tax forms

## Create an account with W-8 and W-9 Additional Verifications requirements

#### Typed Accounts

```curl
curl https://api.stripe.com/v1/accounts \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d type=express \
  -d country=US \
  -d business_type=individual \
  -d "capabilities[transfers][requested]=true" \
  -d "capabilities[card_payments][requested]=true" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=substitute" \
  -d "additional_verifications[us_w8_or_w9][upfront][0][disables]=payouts" \
  -d "additional_verifications[us_w8_or_w9][requested]=true"
```

#### Typeless Accounts

```curl
curl https://api.stripe.com/v1/accounts \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "controller[fees][payer]=application" \
  -d "controller[losses][payments]=application" \
  -d "controller[stripe_dashboard][type]=express" \
  -d "controller[requirement_collection]=stripe" \
  -d country=US \
  -d business_type=individual \
  -d "capabilities[transfers][requested]=true" \
  -d "capabilities[card_payments][requested]=true" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=substitute" \
  -d "additional_verifications[us_w8_or_w9][upfront][0][disables]=payouts" \
  -d "additional_verifications[us_w8_or_w9][requested]=true"
```

## Update an account to add or change W-8 and W-9 verification requirements

```curl
curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=substitute" \
  -d "additional_verifications[us_w8_or_w9][upfront][0][disables]=payouts" \
  -d "additional_verifications[us_w8_or_w9][requested]=true"
```

## Get the status of an account with W-8 and W-9 verification requirements

```curl
curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \
  -u "<<YOUR_SECRET_KEY>>:"
```

### Example response

#### Typed Accounts

```json
{
  "id": ""{{CONNECTED_ACCOUNT_ID}}"",
  "object": "account",
  "additional_verifications": {
    "us_w8_or_w9": {
      "requested": true,
      "requested_at": 1680302915,
      "requirements": {
        "alternatives": [],
        "current_deadline": null,
        "currently_due": [
          "tax_info.verification.document"
        ],
        "disabled_reason": "requirements.past_due",
        "errors": [],
        "eventually_due": [
          "tax_info.verification.document"
        ],
        "past_due": [
          "tax_info.verification.document"
        ],
        "pending_verification": []
      },
      "status": "unverified",
      "upfront": [
        {
          "disables": "payouts"
        }
      ],
      "w8": {
        "type": "substitute"
      }
    }
  },
  ...
  "requirements": {
    "alternatives": [],
    "current_deadline": null,
    "currently_due": [
      "tax_info.verification.document"
    ],
    "disabled_reason": "requirements.past_due",
    "errors": [],
    "eventually_due": [
      "tax_info.verification.document"
    ],
    "past_due": [
      "tax_info.verification.document"
    ],
    "pending_verification": []
  },
  ...
  "type": "express"
}
```

#### Typeless Accounts

```json
{
  "id": ""{{CONNECTED_ACCOUNT_ID}}"",
  "object": "account",
  "additional_verifications": {
    "us_w8_or_w9": {
      "requested": true,
      "requested_at": 1680302915,
      "requirements": {
        "alternatives": [],
        "current_deadline": null,
        "currently_due": [
          "tax_info.verification.document"
        ],
        "disabled_reason": "requirements.past_due",
        "errors": [],
        "eventually_due": [
          "tax_info.verification.document"
        ],
        "past_due": [
          "tax_info.verification.document"
        ],
        "pending_verification": []
      },
      "status": "unverified",
      "upfront": [
        {
          "disables": "payouts"
        }
      ],
      "w8": {
        "type": "substitute"
      }
    }
  },
  ...
  "requirements": {
    "alternatives": [],
    "current_deadline": null,
    "currently_due": [
      "tax_info.verification.document"
    ],
    "disabled_reason": "requirements.past_due",
    "errors": [],
    "eventually_due": [
      "tax_info.verification.document"
    ],
    "past_due": [
      "tax_info.verification.document"
    ],
    "pending_verification": []
  },
  ...
  "controller": {
    "fees": {
      "payer": "application"
    },
    "losses": {
      "payments": "application"
    },
    "stripe_dashboard": {
      "type": "express"
    },
    "requirement_collection": "stripe"
  }
}
```

## Remove W-8 and W-9 verification requirements

```curl
curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=substitute" \
  -d "additional_verifications[us_w8_or_w9][upfront][0][disables]=payouts" \
  -d "additional_verifications[us_w8_or_w9][requested]=false"
```

## W-8 form configuration

When configuring W-8 forms for non-US taxpayers, you can choose between different form types:

| **W-8 type** | **Description** |
| --- | --- |
| “standard” | Collects comprehensive W-8 details including Tax ID and tax treaty claims |
| “substitute” | Collects only basic W-8 details (recommended for most platforms) |

For standard W-8 forms, you can also specify the income types relevant to your platform:

```curl
curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=standard" \
  -d "additional_verifications[us_w8_or_w9][w8][income_types][0]=royalties_copyrights" \
  -d "additional_verifications[us_w8_or_w9][upfront][0][disables]=payouts" \
  -d "additional_verifications[us_w8_or_w9][requested]=true"
```

## Tax Identification Number (TIN) verification

For US taxpayers submitting W-9 forms, Stripe automatically verifies their TIN against the IRS database. If TIN verification fails, additional requirements become either [currently_due](https://docs.stripe.com/api/persons/object.md#person_object-requirements-currently_due) or [past_due](https://docs.stripe.com/api/persons/object.md#person_object-requirements-past_due):

| **Business type** | **Requirements** |
| --- | --- |
| Individual | [individual.id_number](https://docs.stripe.com/api/accounts/update.md#update_account-individual-id_number) (SSN/ITIN) |
| Company | [company.tax_id](https://docs.stripe.com/api/accounts/update.md#update_account-company-tax_id) (EIN) |

> To check TIN verification status, listen to the `account.updated` *webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests). Don’t call the [retrieve account](https://docs.stripe.com/api/docs/api/accounts/retrieve.md) API repeatedly, because it isn’t reliable and might cause rate limiting issues.

## Enforcement limits and actions 

Stripe has enforcement limits and enforcement actions that you can set to require connected accounts to provide tax documentation, and take action if they fail to do so.

### Enforce limits

An enforcement limit tells Stripe *when* to enforce compliance action on a connected account if they don’t provide their tax documentation. You can set the following enforcement limits on your connected accounts either separately or in combination. When you set a new limit, it replaces previous limits set on your connected account.

#### Upfront

Immediately satisfy applicable requirements.

Example: if the user of the connected account doesn’t have completed tax documentation on file when the requirement is set, then Stripe takes an enforcement action.

```curl
curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=substitute" \
  -d "additional_verifications[us_w8_or_w9][upfront][0][disables]=payouts" \
  -d "additional_verifications[us_w8_or_w9][requested]=true"
```

#### Time limit

Satisfy applicable requirements after a specific number of days.

Example: if the user of the connected account doesn’t have completed tax documentation within 60 days of the requirement being set on the account, then Stripe takes an enforcement action.

```curl
curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=substitute" \
  -d "additional_verifications[us_w8_or_w9][time_limits][0][at_days]=60" \
  -d "additional_verifications[us_w8_or_w9][time_limits][0][disables]=payouts" \
  -d "additional_verifications[us_w8_or_w9][requested]=true"
```

#### Volume limit

Satisfy requirements after they meet a specific dollar threshold.

Example: if the user of the connected account doesn’t have completed tax documentation by the time their processing volume reaches 300 USD, Stripe takes an enforcement action.

```curl
curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=substitute" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][0][at_volume]=30000" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][0][currency]=usd" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][0][disables]=payouts" \
  -d "additional_verifications[us_w8_or_w9][requested]=true"
```

#### Time & volume limit

Satisfy requirements after they meet a specific dollar threshold or a specific number of days, whichever limit triggers first.

Example: if the user of the connected account doesn’t have completed tax documentation by the time their processing volume reaches 300 USD or within 60 days of the requirement being set on the account, Stripe takes an enforcement action.

```curl
curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=substitute" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][0][at_volume]=30000" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][0][currency]=usd" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][0][disables]=payouts" \
  -d "additional_verifications[us_w8_or_w9][time_limits][0][at_days]=60" \
  -d "additional_verifications[us_w8_or_w9][time_limits][0][disables]=payouts" \
  -d "additional_verifications[us_w8_or_w9][requested]=true"
```

### Enforcement actions

Stripe executes an enforcement action when an enforcement limit meets a set threshold. An enforcement action tells Stripe *what* to do when the requirement isn’t fulfilled within the enforcement limit. For example, you can disable payouts or disable payouts *and* payments.

#### Disable payouts

Disable payouts until requirements are satisfied.

```curl
curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=substitute" \
  -d "additional_verifications[us_w8_or_w9][upfront][0][disables]=payouts" \
  -d "additional_verifications[us_w8_or_w9][requested]=true"
```

#### Disable payouts & payments

Disable both payouts and charges until requirements are satisfied.

```curl
curl https://api.stripe.com/v1/accounts/{{CONNECTEDACCOUNT_ID}} \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=substitute" \
  -d "additional_verifications[us_w8_or_w9][upfront][0][disables]=payouts_and_payments" \
  -d "additional_verifications[us_w8_or_w9][requested]=true"
```

You can combine enforcement limits and actions, see [More examples](https://docs.stripe.com/connect/additional-verifications/us-w8-w9.md#more-examples) below.

## More enforcement limit examples 

You can configure enforcement limits based on the following examples.

### Combining multiple enforcement limits

When adding multiple enforcement limits, each limit can trigger independently.

In this example, there are three independent triggers:

1. When the account reaches 600 USD in payment volume, the user must provide W-8 or W-9 documentation, otherwise payouts are disabled.

2. When the account reaches 3000 USD in payment volume, the user must provide W-8 or W-9 documentation, otherwise payments and payouts are disabled.

3. When the account reaches 60 days old, the user must provide W-8 or W-9 documentation, otherwise payments and payouts are disabled.

In this case, Stripe takes action on the limit that triggers first. Providing a form satisfies all existing and future triggers.

#### Typed Accounts

```curl
curl https://api.stripe.com/v1/accounts \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d type=express \
  -d country=US \
  -d business_type=individual \
  -d "capabilities[transfers][requested]=true" \
  -d "capabilities[card_payments][requested]=true" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=substitute" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][0][at_volume]=60000" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][0][currency]=usd" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][0][disables]=payouts" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][1][at_volume]=300000" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][1][currency]=usd" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][1][disables]=payouts_and_payments" \
  -d "additional_verifications[us_w8_or_w9][time_limits][0][at_days]=60" \
  -d "additional_verifications[us_w8_or_w9][time_limits][0][disables]=payouts_and_payments" \
  -d "additional_verifications[us_w8_or_w9][requested]=true"
```

#### Typeless Accounts

```curl
curl https://api.stripe.com/v1/accounts \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "controller[fees][payer]=application" \
  -d "controller[losses][payments]=application" \
  -d "controller[stripe_dashboard][type]=express" \
  -d "controller[requirement_collection]=stripe" \
  -d country=US \
  -d business_type=individual \
  -d "capabilities[transfers][requested]=true" \
  -d "capabilities[card_payments][requested]=true" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=substitute" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][0][at_volume]=60000" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][0][currency]=usd" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][0][disables]=payouts" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][1][at_volume]=300000" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][1][currency]=usd" \
  -d "additional_verifications[us_w8_or_w9][volume_limits][1][disables]=payouts_and_payments" \
  -d "additional_verifications[us_w8_or_w9][time_limits][0][at_days]=60" \
  -d "additional_verifications[us_w8_or_w9][time_limits][0][disables]=payouts_and_payments" \
  -d "additional_verifications[us_w8_or_w9][requested]=true"
```

### Standard W-8 form with income types

For platforms that need to collect more comprehensive tax information, you can request standard W-8 forms with specific income types:

#### Typed Accounts

```curl
curl https://api.stripe.com/v1/accounts \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d type=express \
  -d country=US \
  -d business_type=individual \
  -d "capabilities[transfers][requested]=true" \
  -d "capabilities[card_payments][requested]=true" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=standard" \
  -d "additional_verifications[us_w8_or_w9][w8][income_types][0]=royalties_copyrights" \
  -d "additional_verifications[us_w8_or_w9][w8][income_types][1]=services_compensation" \
  -d "additional_verifications[us_w8_or_w9][upfront][0][disables]=payouts_and_payments" \
  -d "additional_verifications[us_w8_or_w9][requested]=true"
```

#### Typeless Accounts

```curl
curl https://api.stripe.com/v1/accounts \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "controller[fees][payer]=application" \
  -d "controller[losses][payments]=application" \
  -d "controller[stripe_dashboard][type]=express" \
  -d "controller[requirement_collection]=stripe" \
  -d country=US \
  -d business_type=individual \
  -d "capabilities[transfers][requested]=true" \
  -d "capabilities[card_payments][requested]=true" \
  -d "additional_verifications[us_w8_or_w9][w8][type]=standard" \
  -d "additional_verifications[us_w8_or_w9][w8][income_types][0]=royalties_copyrights" \
  -d "additional_verifications[us_w8_or_w9][w8][income_types][1]=services_compensation" \
  -d "additional_verifications[us_w8_or_w9][upfront][0][disables]=payouts_and_payments" \
  -d "additional_verifications[us_w8_or_w9][requested]=true"
```

## Collect tax documentation

### Using the Express Dashboard (recommended)

For connected accounts with Express Dashboard access, Stripe will automatically send an email notification for W-8 or W-9 requirements. Users can complete their forms through the Express Dashboard with:

- Pre-populated information from existing account details
- Step-by-step guidance through form completion
- Digital signature capabilities
- Access to view and download completed forms

### Using Connect Onboarding

For accounts without Express Dashboard access, you can direct users to complete tax documentation through Connect Onboarding:

```curl
curl https://api.stripe.com/v1/account_links \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "account={{CONNECTEDACCOUNT_ID}}" \
  --data-urlencode "refresh_url=https://example.com/reauth" \
  --data-urlencode "return_url=https://example.com/return" \
  -d type=account_onboarding \
  -d "collection_options[fields]=eventually_due"
```

### Setting W-8 and W-9 requirements through the Dashboard

You can also configure W-8 and W-9 requirements through the Stripe Dashboard:

1. Go to your [Connect settings](https://dashboard.stripe.com/settings/connect/w8_w9_forms) in the Dashboard.
2. Click **Connect** > **W-8 and W-9 tax form settings**.
3. Enable the **Collect W-8 and W-9 tax information** option.
4. Choose to collect from **New accounts only**.
5. Select either the **Standard** or **Substitute** W-8 form type.
6. Click **Review and apply changes**.

## Handling webhooks 

For asynchronous handling of verification results, you can use [Connect webhooks](https://docs.stripe.com/connect/webhooks.md) to monitor the status of the connected account. For Additional Verifications, the `account.updated` event contains the updated account information.

## Testing

You can create test accounts with W-8 and W-9 Additional Verifications requirements.

To complete and test W-8 or W-9 forms:

1. Follow the form flow through Connect Onboarding or the Express Dashboard.
2. A testing environment accepts any valid-looking information.
3. For W-9 forms, you can use “000000000” as a TIN that will pass verification.

Visit [Testing Stripe Connect](https://docs.stripe.com/connect/testing.md) for a full guide on testing Stripe Connect.
