Handling Taxes with Stripe & NetSuite


Any advice or suggestions provided in this document is not meant to be official tax or legal advice. Any information supplied by SuiteSync is strictly related to the configuration options available within SuiteSync to handle taxes.

There are many options available for how you configure taxes with Stripe & NetSuite. It's best to review your tax situation in detail during the onboarding process so SuiteSync can provide advice around technical best-practices for handling taxes.

That said, this document attempts to outline some of the options that are available as well as generalized recommended flows.

Here are key factors to consider in regards in taxes:

  1. What system is creating the payment? Is this an eCommerce payment from an eCommerce shop such as Shopify, Magento, etc. Or is this an automated subscription payment generated by Stripe.
  2. Do you only need to charge a flat tax if a customer is in a specific state/providence, or do you need to charge tax based on a customers exact location?
  3. Is your price inclusive of tax (typical in the EU) or is tax a separate line item on the invoice/order?
  4. Are you managing tax remittance in NetSuite, or leveraging a 3rd party tool like Avalara?
  5. In NetSuite, are you using line-level taxes, header-level taxes, multi-component taxes, or representing taxes as a unique liability item?

You'll want to have answers to these questions on hand before reading through the rest of this document.

Recommended Workflows

eCommerce

If you are running an eCommerce store using an application like Shopify, WooCommerce, Magento, etc those applications will help handle tax calculation and you'll use an application like Celigo or In8 to pull order data over to NetSuite. Stripe and/or SuiteSync is not involved in the tax calculation process.

Billing Managed in NetSuite

If you are managing your invoicing process in NetSuite, Stripe and SuiteSync are not involved in the tax calculation process or recording process at all.

Stripe Billing (Subscriptions)

Here's the recommended workflow if you are using Stripe Billing:

  1. Calculate taxes automatically in Stripe using Stripe Tax
  2. After the Stripe invoice is billed, SuiteSync records the Stripe-calculated tax amounts to NetSuite.
  3. Use NetSuite as a ledger of taxes owed/paid (SuiteSync handles bringing in net taxes owed from Stripe to NetSuite). Don't use NetSuite for detailed reporting on taxes owed on a state, local, etc basis.
  4. Use Stripe tax reports for managing detailed tax reporting and/or remittance

Learn more about setting up Stripe Subscriptions with Stripe Tax.

Note that if you are using another tax system aside from Stripe Tax or Avalara, you may need to build a custom integration into Stripe. Check out tax systems that work with Stripe for more details.

One-time Invoices Using Stripe Billing

One-time, or "manual" non-subscription, invoices in Stripe are managed in an identical way to the "Stripe Subscriptions" setup described above.

One-time or Standalone Payments in Stripe

If you are creating payments without an invoice (either an invoice in NetSuite or Stripe), there's no line-level detail about exactly what was purchased and how much tax was paid. In other words, by looking at Stripe you can't determine how much tax was paid and how much was paid for the product. Here's more information about how standalone payments work in SuiteSync.

If you are creating charges without an invoice, we can't help record taxes properly in NetSuite.

Available Tools for Calculating Tax

Here's some ways to calculate and/or record taxes in Stripe:

  1. Automatically calculate taxes using Stripe Tax.
  2. Create and maintain your own tax rates and apply them to products using Stripe Tax Rates.
  3. Calculate taxes outside of Stripe and record the amount using a invoice item added to the Stripe invoice.
  4. Use a tax calculation plugin like Avalara AvaTax or another supported calculation system.

You can't use the NetSuite tax tables to calculate tax through Stripe. The trick here is your payment front end needs to calculate tax before the invoice, payment, etc makes its way to NetSuite. NetSuite doesn't have a way to pull tax information out of their system without creating an order, invoice, etc. In other words, the NetSuite tax tables are useless from the perspective of online orders. You need to calculate taxes before the order, payment, etc is submitted to Stripe.

How Taxes Work in NetSuite

Tax Management in NetSuite

Here are the main ways of representing taxes in NetSuite:

  1. An additional line item posting to a liability account is added to the invoice.
  2. A tax rate and/or tax code is set on the line-item level of the invoice
  3. A tax rate and/or tax code is set on the header level of the invoice (or SalesOrder)
  4. If you are an international company, the price may be inclusive of tax and you may specify the gross amount on the line item level and let NetSuite calculate the correct tax owed based on the address of the customer.
  5. You leverage another tax integration bundle in NetSuite, like TaxJar, to automatically calculate taxes based on the NetSuite invoice information.

Recording Tax Using a NetSuite Line Item

When representing taxes as a line item, an additional line item is added to the invoice to record taxes calculated in Stripe. If this option is used, taxes are not recorded on the line-item or header-level of the NetSuite record. Even if you are using NetSuite's tax engine, you may want to specify taxes as a separate line item. For instance, Stripe may have more detailed address data or product tax codes compared to NetSuite and it may be hard to calculate taxes in the exact same way.

Which NetSuite item is used to represent taxes can be changed based on metadata attached to the tax information in Stripe. For example, if you are using the Stripe Subscriptions Avalara integration here's an example of how we can choose the correct tax item in NetSuite:

  • Attempt to find a NetSuite item with a TaxCode-State in the searchKeywords field. Ex: SW053000-PA. The TaxCode is specified on the invoice level, the state is specified on the customer metadata Address_State.
  • Attempt to find a NetSuite item with TaxCode in searchKeywords
  • If no match is found, a Stripe Unallocated Taxes is used.

If using Stripe Tax or Stripe Tax Rates then the tax amount, source, and tax percent for each tax rate is specified on the description of the line item. For instance, if you are using Stripe Tax you'll see 8.88 of Sales Tax - New York at 8.875% generated by Stripe Tax and multiple tax rates will look like .38 of Tax - Seattle at 3.75%, .65 of Sales Tax - WA at 6.5%. If you are using Avalara only a calculated tax rate is specified and you'll see 6.00% Tax by Avalara.

Inclusive Line-level Tax

If your company is based in the Eurozone, most likely the amount shown to the customer is inclusive of tax. To support this, the amount charged to the customer is passed over to the "gross amount" transaction column in NetSuite. This approach relies on NetSuite (either the NetSuite tax engine or the Avalara NetSuite integration) for tax calculation.

Here's an example of where to find the "Gross Amount" column:

Invoice Line Item Gross Amount

Integrating Stripe Tax and Stripe Tax Rates

Stripe's native tax support is the prefered method for calculating tax in Stripe. There is support for integrating the generated tax amounts and tax rates into NetSuite.

Reporting Taxes as a Line Item in NetSuite

This is the prefered representation of taxes in NetSuite. The best way to see tax the complete breakdown for taxes generated in Stripe is through Stripe's tax reporting. This information is not easily accessible to be transfered into NetSuite. The tax line item provides a simple way to see the total amount of taxes paid in NetSuite while working around limitations and complex NetSuite set up required for complete tax reporting.

Taxes on the Line Item in NetSuite

This is an approach to report taxes directly in NetSuite. Due to the differences in features between Stripe and NetSuite, there are some limitations that may lead to incorrect tax percentages. The integration gaurentees that the total amount of tax calculated in NetSuite on each line will match the total amount of taxes on each line in Stripe.

Multiple Tax Rates on a Line Item

Stripe supports multiple tax rates on a line item while NetSuite only supports 2 tax rates. To handle this difference, the tax rates from Stripe are combined into a single percentage that is set on the tax_rate1 property of each NetSuite line item. In most cases, the total tax rate can be generated by adding all of the tax rates together.

In some rare cases the combined tax rate cannot be generated by adding the tax rates and will be calculated based on the total tax amount instead. The total tax amount for the line is produced by applying each tax rate to the pre-tax amount. It's possible that the total tax amount from a summed percentage is different than the total tax amount from separate tax percentages due to compounding rounded tax amounts when the tax rates are separate. For example, if a line item has a value of $1.00 and tax rates of 9.5% and 9.6% then both tax rates will generate a tax amount of $0.10 totaling $.020 of tax for the line. However, we if we add the tax rates we get a total tax rate of 19.1% which would only generate $0.19 of tax instead of the total $.020. The integratation ensures the tax amounts on each line in NetSuite will match the line amounts for each line in Stripe so in this case the integration will calculate a tax rate of 20.0% to ensure that a total tax of $.020 is generated on the line in NetSuite.

Tax Rates with Discounts on Line Items

The integration currently only supports a single discount which means the line amounts are unaware of the discount and the actual tax percentage can't be used to calculate the correct amount of taxes on a line. When discounts are applied, the tax rate will be calculated to ensure the proper tax amount is used. The integration will create an invoice with lines using the pre-discount amounts and an additional separate line item for the total discounts on an invoice. This means that each line is unaware of the discount and applying the actual tax amount will not produce the correct amount of tax. For example, if an invoice has an item worth $100 with a $20 discount and a 10% tax rate then the total taxes generated will be $8 because the taxes are a applied to the post-discount amount of $80. Given that the line item has an amount of $100 and tax amount of $8, the integration will generate a tax rate of 8.0% on the line in NetSuite.

Once there is support for discounts per line then the integration can support accurate tax rates with discounts.

Tax on Credit Note Line Items

Representing taxes on the line in NetSuite cannot be used with the credit note integration. There are limitations in NetSuite that prevent setting the tax rate on credit memo line items in NetSuite.

Integrating a Custom Tax System with Stripe Billing

If you choose to calculate taxes using a custom system, you may want to push the exact amount into Stripe using a standalone Stripe invoice item. However, in order for the integration to correctly categorize this line item as tax, you'll need to add a netsuite_tax metadata key set to true.

Here's an example:

Stripe::InvoiceItem.create(
  customer: 'cus_123',
  description: 'A custom description',
  amount: 87,
  currency: 'usd',
  metadata: {
    "netsuite_tax": "true"
  }
)

Automating Calculating Avalara with Stripe Billing

Avalara's Stripe integration calculates tax and pushes the total amount to the Stripe invoice as a standalone invoice item. However, this means that Stripe invoices must remain "open" for a period of time to give Avalara time to push the calculated tax amount into Stripe. Avalara pushes the tax amount as a "Sales Tax" line item (aka a Stripe InvoiceItem).

Here's what the invoice will look like:

NetSuite Invoice Partially Paid with Customer Balance

And here's what the corresponding customer metadata should look like:

NetSuite Invoice Partially Paid with Customer Balance

Note that it is possible to calculate tax with just a zip code. You'll want to consult your tax professional about the best approach for your business.

This is done automatically after the first billing cycle. You'll need to do this on the first billing cycle manually using the pay_immediately flag.

Here's a full example.

Note that the pay_immediately parameter needs to be enabled on your account. Contact Stripe's support to enable this in your account. If you run into trouble, contact SuiteSync support and they can work with Stripe to ensure this is enabled on your account.

Ensuring Taxes Aren't Recorded Twice

If you've installed AvaTax in NetSuite, by default Avalara will calculate and record taxes due on any invoices created in NetSuite. However, for Stripe Billing invoices, Avalara will calculate and record the tax amount before the invoice gets to NetSuite. For these invoices, we want to ensure that Avalara does not calculate taxes in NetSuite.

In order to do this SuiteSync sets the "tax code" on the invoice and line item level to "Not Taxable". In most cases, this will work just fine. However, if a Stripe plan (also know as product or price level) is linked to a item in NetSuite which has an explicit "Avatax Tax Code" set, the NetSuite Avalara tax system will override the SuiteSync defaults and cause tax to be calculated twice.

Ensure that all NetSuite items linked to Stripe plans do not have a "Avatax Tax Code".

How Taxes are Represented in NetSuite

Taxes in Stripe, calculated by Avalara, are represented by an additional line item on the NetSuite invoice called "Stripe Tax". You can rename the item, edit the liability account, or edit any other aspects of the item once it is created. Once this item is setup in NetSuite you'll want to customize the name and account to align with how to manage taxes in NetSuite.

Taxes calculated by Avalara outside of NetSuite are not represented by tax codes or groups.

Note that the AVATAX sales tax item in NetSuite cannot be used to represent tax in NetSuite when Avalara is used outside of the NetSuite environment to calculate tax. This special tax item in NetSuite triggers a call to Avalara which would cause taxes for that order to be recorded again.

Our integration with Avalara's Stripe integration assumes that you've already handled posting taxes to Avalara within your web front end or using the pre-built Avalara integration with Stripe. SuiteSync has logic which ensures that the AVATAX item is not used, which eliminates the possibility of double-recording tax liability in NetSuite.

Race Condition with Usage Based Billing

There is a race condition with the Stripe<>Avalara integration to be aware of. If you are using the invoice.created webhook in your systems to add usage-based billing via Stripe's standalone invoice items there is no way to guarantee that Avalara calculates taxes after you add any billing "add-ons" from your application.

Webhook Setup

Avalara has a separate product which integrates directly into Stripe Subscriptions. It's called "Avatax for Stripe" and has a separate site where you can set it up: https://avataxforstripe.com.

Here's the full AvaTax for Stripe guide.

Avalara does not automatically receive webhooks from your Stripe account when your Stripe account is connected to Avalara. You need to manually add the Avalara webhook URL to each environment you'd like to test Avalara with.

You need to go to "AvaTax Setup" and copy the Avalara webhook endpoint and then to the Stripe webhooks admin (API > Webhooks) to add the Avalara webhook as a endpoint that Stripe should send webhooks to.

You can only connect to one Avalara environment at a time. If you are processing test webhooks, you'll want to connect to Avalara's sandbox system. You can configure which Avalara environment you are connected to using the https://avataxforstripe.com admin.

Setup Cheatsheet

You'll need to make sure both recurring and normal invoices are configured to be taxable by Avalara.

Avatax Stripe Configuration

Avalara does not support processing Stripe live mode and test mode transactions at the same time. You'll want to configure the "Avalara Environment" configuration to match the environment you are currently testing in Stripe.

Note that if you do not have an Avalara sandbox, you cannot test the Stripe integration with Avalara in Stripe test mode. You need an Avalara test environment to do a full end-to-end test of the Stripe > Avalara > NetSuite integration.

Here's where the Avalara item mapping is stored. You'll need to set up the item mapping to determine what items in Stripe should be taxed by Avalara.

When you've successfully integrated Avalara with Stripe, here's what you should see:

  1. Address information added to Avalara-specific Stripe customer metadata fields
  2. When a subscription is initiated in Stripe, immediate payment should be delayed by using the pay_immediately: false parameter in Stripe to ensure that tax is added.
  3. When an invoice is generated by Stripe for the next subscription billing period, an Avalara line item should be added automatically to the Stripe invoice.