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.

Taxes 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 you are using individual items in NetSuite to represent tax paid, instead of the NetSuite tax engine or the NetSuite Avalara integration, SuiteSync can help match taxes to the proper custom item in NetSuite.

If you are using the Stripe Subscriptions Avalara integration:

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

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.

How Taxes are Represented in NetSuite

Taxes in Stripe which are calculated by Avalara are represented by an additional line item on the NetSuite invoice called "Stripe Tax" (you can rename the item, edit the GL account, etc; this is just the default name).

Note that the AVATAX sales tax item in NetSuite cannot be used to represent tax. This special tax item triggers a call to Avalara which would cause taxes for that order to be recorded again. Our tax integration with Avalara assumes that you've already handled posting taxes to Avalara within your web front end or using the pre-built Avalara integration.

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.

Here's where the Avalara item mapping is stored:

https://admin-avatax.avalara.net/AvaTax/Item/ItemList.aspx