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 solid 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 Subscriptions

Here's the recommended workflow if you are using Stripe Subscriptions to manage your billing:

  1. Calculate taxes using Avalara's pre-built subscription integration, "Avatax for Stripe".
  2. SuiteSync pushes 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 Avalara for managing detailed tax reporting and/or remittance

Note that if you are using another tax system aside from 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

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 not associated with any invoice record in NetSuite, there's no line-level detail about what the net amount

Available Tools for Calculating Tax

Assuming that you need to use Stripe to help calculate, or pass the tax amount calculated to Stripe, you have two main options:

  1. Use a tax calculation tool like Avalara or another supported calculation system
  2. Calculate taxes on your server and send the amount to Stripe

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.

Tax Management in NetSuite

Here are the main ways of representing taxes in NetSuite:

  1. A tax rate and/or tax code is set on the header level of the invoice (or CashSale, SalesOrder, etc)
  2. A tax rate and/or tax code is set on the line-item level of the invoice
  3. An additional line item posting to a liability account is added to the invoice.
  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 Avalara, or another tax integration, to automatically calculate taxes based on the NetSuite invoice information.

Line-item Tax Codes & Percent

  • It's possible to configure NetSuite so tax rates are not editable on the line item level. If this is the case, it's possible for the integration to ether:
  1. Search for a matching tax code with a matching rate or
  2. Override the default tax percent despite the fact that NetSuite does not allow this to be changed via the UI.

Taxes Specified using Header-level Tax Codes & Percents

  • In this case, the tax amount (via a tax code, percent, etc) is calculated on the header level of the NetSuite invoice, sales order, etc. The "taxable" checkbox determines which items are included in the tax percent calculation. This checkbox is checked for all line items on the invoice.
  • To inspect tax fields available on the column level: custom form > screen fields > columns

Tax with NetSuite Line-items Items

If items in NetSuite represent tax paid, instead of the NetSuite tax engine or Avalara integration, SuiteSync can help match taxes to the proper custom item in NetSuite. Even if you are using NetSuite's tax engine, you may want to specify taxes as a separate line item if you can't easily match tax calculations in Stripe to the correct tax codes in Netsuite.

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 flow 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.

In any of these cases, the tax percent and source are specified on the description of the line item. For instance, if you are using Avalara you'll see 6.00% Tax by Avalara and if you are specifying tax manually in Stripe you'll see 6% Tax by Stripe.

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

If you plan to use the tax_percent parameter on the Stripe invoice contact us to review your tax configuration in detail. If you have a "Gross Amount" invoice line item column enables (common in non-US countries), you cannot use the tax_percent option in Stripe.

Integrating Avalara with Stripe Subscriptions

Using Avalara's pre-built Stripe integration can be confusing. We've written a set of instructions that make this process a bit easier.

First, here's a high-level overview of how the connector works:

  1. In the "Avatax for Stripe" connector, you specify which Stripe price levels and line item types are taxable.

  2. When you create a customer in Stripe, you'll add specific address data to the Stripe customer which Avalara will use to determine the correct taxes for the given customer.

  3. Right before a customer is charged for a subscription period, Stripe asks Avalara what the taxes should be for the invoice.

  4. Avalara sends the net tax amount back to Stripe as an additional line item on the invoice. This means that tax is represented at the "header level" in Stripe, the individual tax rate for each item on the invoie is not specified, only the net amount charged based on Avalara's calculation.

For Avalara to properly calculate the total tax amount, location information needs to be added to the Stripe customer using Stripe metadata. You can either include a zip code or the full customer address (obviously, contact your tax advisor for requirements in your specific business).

Here's an example:

address1 = '3180 18th St'
address2 = nil
address3 = nil
city = 'San Francisco'
state = 'CA'
postal_code = '94110'
country = 'US'

Stripe::Customer.create(
  email: 'customer@example.com',
  metadata: {
    'Address_Line1' => address1,
    'Address_Line2' => address2,
    'Address_Line3' => address3,
    'Address_City' => city,
    'Address_State' => state,

    # NOTE these two parameters are mandatory
    'Address_PostalCode' => postal_code,
    'Address_Country' => country
  }
)

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:

customer.subscriptions.create(
  plan: plan.id,
  pay_immediately: false
)

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. 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.