App guides
The Avalara AvaTax app makes Avalara AvaTax the tax service for your Swell store. Once you turn it on, Swell asks AvaTax for the taxes on carts, orders and subscriptions instead of using its own tax rules. AvaTax works out the tax for each item and for shipping from the customer's address, your store locations and the tax codes you use.
The app also records paid orders and invoices in AvaTax as committed sales, so they appear in your AvaTax reports and returns. Changes and returns update the AvaTax document, and canceling the order voids it. Customers can be marked tax-exempt on their customer page.
| When | What the app does |
| A cart, order or subscription changes in a way that affects tax | Asks AvaTax for the tax of each item and of shipping, and saves it on the record. Items, quantities, coupons, promotions, the country, state or zip code of an address, and the shipping charge all count. |
| An order is submitted | Calculates the taxes again. |
| An order is paid in full | Records it in AvaTax as a committed sales invoice, with the order number as the document code, if Record paid orders in AvaTax is on. |
| An invoice is paid | Records it the same way, with I- in front of the invoice number. An invoice created from an order isn't recorded, because the order already records that sale. |
| A recorded order or invoice changes, or items are returned | Sends it again, and AvaTax updates the document with the same code. |
| An order is canceled or an invoice is voided | Voids the AvaTax document. |
| AvaTax can't calculate the taxes | Rejects the change with an error, or continues without tax, depending on Reject when AvaTax fails. |
All of this runs only while Avalara AvaTax is turned on in Settings > Taxes. Until then, Swell doesn't ask the app for taxes, and the app records nothing.
- An AvaTax account. Sandbox and production accounts are separate, each with its own account ID and license key.
- An AvaTax license key, generated under Settings > License and API keys in AvaTax.
- The company code of the AvaTax company your store sells under. The company has to be active.
- That company set up in AvaTax for the places you collect tax, under Settings > Where you collect tax. The app sends no nexus information, so what gets taxed depends on this setup.
- A sandbox account for your Swell test environment. The app records paid test orders in whichever account you connect, so a production account in the test environment records them as real sales.
- An address for your store location, under Settings > Products. It's the ship-from address for taxes, and it's used when a paid order has no customer address.
- Customer addresses with a zip code, or a street, city and state. Without one, no tax is calculated.
Install Avalara AvaTax from the Swell App Store, and set it up in your test environment before the live one.
If Swell's built-in Avalara AvaTax integration is on when you install the app, Swell shows Avalara AvaTax may have conflicts. Click Disable conflicting integration to turn off the built-in integration and install the app. Ignore conflict installs the app and leaves the built-in integration on. Cancel stops the install.
The app doesn't read the built-in integration's credentials, so you enter them again in step 2. Disable conflicting integration takes effect right away: until you turn AvaTax on in step 4, the store uses Swell's own tax rules. To change over without that gap, click Ignore conflict, finish step 4, then go to Integrations, open Avalara AvaTax and click Deactivate. Don't leave both on. See Documents are overwritten or recorded twice under Troubleshooting.
Get your AvaTax credentials
Sign in to AvaTax, with your sandbox account at sandbox.admin.avalara.com for the test environment. Go to Settings > License and API keys and copy your account ID. If you don't have your license key, click Generate license key and copy the key. Generating a new key stops the old one, along with anything that still uses it.
Go to Settings > Manage companies and copy the Company code of your company.
Add them to the app
In Swell, go to Apps > Avalara AvaTax > Settings. Set Environment to Sandbox, and enter the Account ID, License key and Company code. On the Tax calculation tab, check Reject when AvaTax fails, Default product tax code and Shipping tax code. On the Recording sales tab, check Record paid orders in AvaTax. Click Save settings.
Test the connection
Choose Actions > Test connection. It checks the account ID and license key, and that the company code belongs to an active company, then shows a message such as "Connected to AvaTax (Sandbox), company Acme." If Swell's built-in Avalara AvaTax integration is still connected, the message also asks you to disconnect it, so sales aren't overwritten or recorded twice. It works before AvaTax is turned on and sends no store data. If the message reports an error, see Troubleshooting below.
Turn on AvaTax
Go to Settings > Taxes. While AvaTax is on, the Rules and Calculation options on this page move under System settings and can't be changed, so first set the three options AvaTax uses: Product prices include tax, Shipping prices include tax and, under Show advanced options, Taxable location.
Turn on Avalara AvaTax and click Save changes. Swell asks AvaTax for taxes from then on. Edit settings on the same row opens the app's settings.
Place a test order
Add an item to a cart and enter a shipping address. The cart shows one tax line, such as Sales tax. Choose a shipping service, then place and pay the order.
A paid test order is recorded like any other. With Record paid orders in AvaTax on, it's saved as a committed sales invoice in the AvaTax account you connected. In AvaTax, go to Transactions > Transactions and look for the order number as the document code. An unpaid order leaves nothing in AvaTax.
Go live
Settings are saved separately for each environment. In the live environment, repeat steps 2 to 4 with Environment set to Production, and with the account ID, license key and company code of your production account. Environment starts on Sandbox there too, and sandbox and production credentials each work only with their own environment.
While AvaTax is on, Swell asks the app for taxes when a cart, order or subscription is saved with a change that can affect them: items or quantities, a coupon or promotion, the country, state or zip code of an address, or the shipping charge. For carts and orders, it asks again when the order is submitted. AvaTax calculates the taxes and keeps no document of the calculation.
AvaTax needs an address: a shipping or billing address with a zip code, or with a street, city and state. Until a record has one, the app returns no tax and doesn't call AvaTax, so a cart shows no tax until the customer enters an address. AvaTax gets:
- Ship to: the shipping address, or the billing address when Taxable location in Settings > Taxes is Billing address. If that address isn't usable, the other one.
- Ship from: the item's shipment location, or your store's default location. Shipping uses the location all the items share, or the default location when they ship from more than one. If the location has no zip code, and no street, city and state, AvaTax gets only the customer's address.
- Items: the quantity and the price after discounts, with the product's SKU, name and tax code.
- Shipping: the shipping charge after discounts, once a shipping service is chosen.
- Tax-inclusive prices: items and shipping are sent as tax-included when Product prices include tax or Shipping prices include tax is on in Settings > Taxes.
Each item and the shipping get their own tax. The record shows one tax line named after AvaTax's tax type, such as Sales tax.
For a subscription, the plan product is sent as one more line, except during a trial. Swell calculates a subscription's taxes when the subscription changes, not at each renewal, and its invoices and renewal orders take the taxes saved on the subscription.
Each line goes to AvaTax with a tax code. To look up codes, use Avalara's tax code search.
| Line | Tax code |
| A product | The product's tax code. Without one, PG050000 for physical gift cards, DG020000 for digital gift cards, and Default product tax code for everything else. |
| Shipping | The shipping service's tax code, or Shipping tax code. |
| A restocking fee | OR040000. |
The Tax code field shows on the product page only while Swell's built-in AvaTax or TaxJar integration is connected, and on shipping services in Settings > Shipping only while the built-in AvaTax integration is connected. With the app alone, those fields are hidden. Codes already saved on products and shipping services stay there, and the app uses them.
- To set product codes while the field is hidden, go to Products, select the products, choose Edit Products and set Tax code. You can also import products with a Tax code column, or set tax_code on the product with the API.
- To set a shipping service's code while the field is hidden, set tax_code on the service in /settings/shipments with the API. Otherwise, Shipping tax code applies to every service.
When AvaTax refuses a calculation, can't be reached or doesn't answer in time, or a call to Swell fails or takes too long, the app logs AvaTax: taxes not calculated: … with the reason. Reject when AvaTax fails, on the Tax calculation tab, decides what happens next:
- On, the default: the cart or order change is rejected with a 422 error, "Taxes could not be calculated." followed by the reason, and nothing is saved. A customer at checkout can't continue until AvaTax answers. The same goes for an address AvaTax refuses.
- Off: the change is saved without tax, and the customer can place the order. The taxes are calculated again at the next change, or when the order is submitted.
Swell waits 10 seconds for the app, and the app gives itself 8 seconds from when it starts. If loading your store locations, the customer and the products from Swell uses up the 8 seconds, the calculation fails with "Calculating took too long." AvaTax then gets 6 seconds, or the time left if that's less, and a slower answer fails with "AvaTax didn't answer in time." The setting applies to both. If the function itself fails, or doesn't answer within 10 seconds, Swell saves the change without tax, whether the setting is on or off. If the account ID, license key or company code is empty, the app logs AvaTax: missing … in app settings and returns no tax, without an error.
An order placed without tax is still recorded when it's paid. AvaTax calculates its tax at that point, so the document shows tax you didn't charge.
With Record paid orders in AvaTax on, each order paid in full and each paid invoice is saved in AvaTax as a committed sales invoice, which AvaTax needs for its returns and reports. Unpaid orders aren't sent, and neither are invoices created from an order, because the order already records that sale. Each document has:
- Document code: the order number, or I- and the number for invoices. It's also sent as the purchase order number.
- Date: the day the order or invoice was created, in UTC.
- Customer code: the customer's email in lowercase, or the account ID if there's no email.
- Addresses: the same as for a calculation. An invoice without addresses uses its subscription's. A paid record with no usable customer address is recorded from your store's default location.
AvaTax calculates the tax again when it records the sale. The recorded tax can differ from what the customer paid, for example if a rate changed in between.
Turn the setting off if another system records your sales. Taxes are still calculated, and nothing is recorded, updated or voided in AvaTax.
Orders paid before you turned AvaTax on aren't sent, unless one of them changes later.
- Changes: when the items, addresses, shipping charge or shipping service of a paid order or invoice change, the app sends it again, and AvaTax updates the document with the same code. A repeated event doesn't create a second document.
- Returns: returned units with a return price are added to the document as negative lines, so the tax on them comes off. A restocking fee kept from a return is added as a negative line with the code OR040000.
- Refunds without a return: these don't change the document. To remove a refunded order from AvaTax, cancel the order, which is possible until something has been fulfilled. Otherwise, create a return or adjust the document in AvaTax.
- Cancellations: canceling an order or voiding an invoice voids its document. If AvaTax never had the document, nothing happens.
AvaTax can refuse to change a document, for example when it's locked after filing. The app logs the error and doesn't try again, so make the change in AvaTax.
To mark a customer as tax-exempt, open the customer in Customers, open the AvaTax tab, set Entity use code and Exemption number, and click Save changes. Customers who check out as guests have a customer record too, so the same tab works for them.
- Entity use code is the customer's exempt reason, from A – Federal government to R – Non-resident, or None (taxable). AvaTax exempts the customer where that reason applies.
- Exemption number is the number of the customer's certificate. Avalara treats any sale with an exemption number as exempt and doesn't check the number, so the app sends it only with an entity use code. Without one, the number isn't sent and doesn't exempt the customer.
- Both are sent with every calculation and recorded sale of that customer. A change reaches a cart or subscription the next time its taxes are calculated, and a recorded order the next time it's sent.
- Exemption certificates saved in Avalara apply when their customer ID matches the customer code the app sends, which is the customer's email in lowercase. AvaTax matches it exactly.
| Where | What it's for |
| Apps > Avalara AvaTax > Settings | The environment, account ID, license key and company code, and the Tax calculation and Recording sales tabs. |
| Apps > Avalara AvaTax > Actions | Test connection. Save the settings first: the action is unavailable while there are unsaved changes. |
| Settings > Taxes | Turns AvaTax on or off as the store's tax service. Edit settings opens the app's settings. |
| A customer's AvaTax tab | The customer's Entity use code and Exemption number. |
| Products, Edit Products | Sets Tax code on selected products, also while the field is hidden on the product page. |
| Integrations | Swell's built-in Avalara AvaTax integration, which should be off while you use the app. |
| Developer > Console > Logs | The app's errors, and sales it couldn't record. |
Settings are in Apps > Avalara AvaTax > Settings and are saved separately for each environment.
Environment, Account ID, License key and Company code are at the top. The other settings are on the Tax calculation and Recording sales tabs.
| Setting | Description | Default |
| Environment | Sandbox or Production. Sandbox accounts work only with Sandbox, and production accounts only with Production. | Sandbox |
| Account ID | From AvaTax > Settings > License and API keys. Required. | None |
| License key | Generated on the same page in AvaTax. Masked on the settings page. Required. | None |
| Company code | From AvaTax > Settings > Manage companies. Required. | None |
| Tax calculation > Reject when AvaTax fails | When AvaTax can't calculate taxes, rejects the cart or order change with an error instead of continuing without tax. | On |
| Tax calculation > Default product tax code | Used for products without a tax code. P0000000 is taxable tangible goods. When empty, the default is used. | P0000000 |
| Tax calculation > Shipping tax code | Used for shipping services without a tax code of their own. When empty, the default is used. | FR030000 |
| Recording sales > Record paid orders in AvaTax | Saves paid orders and invoices in AvaTax as committed sales, updates them when they change, and voids them when they're canceled. Turn it off if another system records the sales. | On |
- Swell shows one tax line for each record. AvaTax's breakdown by state, county and city stays in AvaTax.
- Only one tax service can be on at a time.
- The recorded tax is AvaTax's calculation when the sale is recorded, so it can differ from the tax the customer paid.
- Subscription renewals use the taxes saved on the subscription. A new rate reaches them only after the subscription's taxes are calculated again, such as when its address or quantity changes.
- Refunds without a return don't change the AvaTax document. After a partial refund without a return, Swell no longer counts the order as paid, so later changes to it aren't sent.
- An order is sent once it's paid in full. Orders that were paid before you turned AvaTax on aren't sent, unless they change later.
- Records with taxes_fixed set through the API are skipped: taxes aren't calculated, the sale isn't recorded, and it isn't voided when canceled.
- The document code is the order number. If two Swell environments or stores record in the same AvaTax company, an order with the same number replaces the other's document.
- After AvaTax is turned off in Settings > Taxes, changes and cancellations no longer reach AvaTax. Void those documents in AvaTax.
- Reject when AvaTax fails doesn't cover a function that fails or takes longer than 10 seconds, or an app with missing settings. In these cases, the change is saved without tax.
- If AvaTax can't be reached or doesn't answer within 6 seconds, rate-limits the app or has a server error while recording a sale, Swell runs the function again later, at growing intervals. If it keeps failing for about 4 days, Swell turns off the function and emails the store's admins. Reinstall the app to turn it back on. Other errors are logged, and the sale isn't sent again until it changes.
Test connection shows its result in a message, and a rejected change returns its error to whoever made it. The app also logs its errors. In the Swell dashboard, the logs are under Developer > Console > Logs.
Swell's built-in Avalara AvaTax integration is on, and Swell lists it when you install or enable the app. Disable conflicting integration turns it off and keeps its settings, so you can turn it on again from Integrations. Ignore conflict leaves it on. Turning on the integration while the app is installed shows Avalara AvaTax may conflict with apps you already use.
The built-in integration and the app are both on. While Avalara AvaTax is on in Settings > Taxes, Swell skips the integration's calculation, so the app sets the taxes. The integration still records: on order and invoice changes, payments and refunds, it sends the sale to AvaTax with its own credentials and the same document code.
In the same AvaTax company, each write replaces the other, and the integration's version has no entity use code or exemption number, so an exempt sale can come back taxable. In another company or account, the sale is recorded in both. To stop this, go to Integrations, open Avalara AvaTax and click Deactivate, which also clears the integration's settings.
While the app isn't turned on in Settings > Taxes, the integration does everything and the app records nothing.
Check that Avalara AvaTax is on in Settings > Taxes and that you clicked Save changes. Until then, Swell's own tax rules apply. Then check that the Account ID, License key and Company code are saved, because the app returns no tax while one is missing, and that the address has a zip code, or a street, city and state.
If the app is calling AvaTax and the tax is still zero, check the company's Settings > Where you collect tax in AvaTax, the tax codes, and the customer's Entity use code. If Reject when AvaTax fails is off, look for AvaTax: taxes not calculated: … in the logs.
The field shows only while a built-in tax integration is connected. See Product and shipping tax codes above. To set codes on products, use Edit Products on the Products page.
The calculation failed while Reject when AvaTax fails is on, and the reason follows the message. "Calculating took too long. …" means the app's 8 seconds ran out while it loaded the record from Swell, before it asked AvaTax. The log line AvaTax: taxes not calculated: … adds AvaTax's error code and the refused call, such as POST /transactions/createoradjust.
A required setting is empty, and the message names it. Fill it in, click Save settings, and test again.
This log line means the store is using the app with a required setting empty, so no tax is calculated and nothing is recorded. Fill in the setting and click Save settings.
Copy the account ID again from Settings > License and API keys in AvaTax, and check the license key, including whether a newer key has replaced it. Check that Environment matches the account: sandbox accounts work only with Sandbox, and production accounts only with Production.
The credentials work, but the Company code doesn't match a company in this AvaTax account. Copy it from Settings > Manage companies in AvaTax. Sandbox and production accounts have their own companies.
Activate the company in AvaTax, or enter the code of an active one.
AvaTax answered 403. Check that the account has access to this company and to AvaTax.
The app couldn't connect to AvaTax. "AvaTax didn't answer in time. …", "AvaTax is limiting requests right now. …" and "AvaTax is not responding right now. …" are the same kind of error, for a slow AvaTax, rate limits and AvaTax server errors. Try again in a few minutes. Swell runs the function again for sales it couldn't record.
Something other than an AvaTax response failed, such as a call to Swell, and the reason follows. Try again. If it keeps happening, send the reason to support@swell.is.
AvaTax refused the transaction, and the message gives its status, error code and reason, such as InvalidAddress. Correct what it names, such as the address or a tax code.
Check that the order is paid in full, that Record paid orders in AvaTax is on, that Avalara AvaTax is on in Settings > Taxes, and that you're looking in the AvaTax account and company the app is connected to. Search Transactions > Transactions for the order number, or I- and the number for an invoice. If it still isn't there, look for a log line below.
AvaTax refused the sale, and the reason follows. For invoices, the line starts with AvaTax: invoices. This error isn't tried again. Fix the cause, then change the order or record it in AvaTax yourself.
The paid order has no usable customer address, and your store location has none either. Add an address to the order, or add your store location under Settings > Products.
Check that the customer's AvaTax tab was saved with an entity use code, because an exemption number alone isn't sent. Then change the cart so its taxes are calculated again. AvaTax applies an entity use code only where the reason applies. For a certificate saved in Avalara, check that its customer ID is the customer's email in lowercase.
Swell turned off the function after about 4 days of failures. Fix the cause, such as an AvaTax outage or changed credentials, and reinstall the app to turn it back on.
Uninstalling the app removes its functions and its settings, including the license key, the AvaTax tab on customers and the Test connection action, and removes Avalara AvaTax from Settings > Taxes. Uninstalling applies to the environment you are in, so remove the app from the test and live environments separately.
Swell clears the app as the tax service, and the store falls back to its own tax rules in Settings > Taxes. If no rule applies to an order, it's charged no tax. If the built-in integration is on, it calculates the taxes again. So in a live store, add your rules or connect another tax service first.
Documents, companies and certificates stay in AvaTax. The taxes already on your orders, subscriptions and invoices stay as they are, and customers keep their entity use codes and exemption numbers, which come back if you reinstall the app. After uninstalling, changes and cancellations no longer reach AvaTax, so void or adjust those documents in AvaTax.
To stop tax calculation without uninstalling, turn off Avalara AvaTax in Settings > Taxes and click Save changes. This also stops recording. To stop only recording, turn off Record paid orders in AvaTax. Disable app also clears the app as the tax service, so after Enable app, turn it on again in Settings > Taxes.
| Function | Runs on | What it does |
| calculate-taxes | before:order.taxes, for the avatax tax extension | Asks AvaTax for the taxes of a cart, order or subscription and returns them to Swell. |
| record-order | order.created, order.updated, order.paid, order.canceled, order.refunded, invoice.created, invoice.updated, invoice.payment_succeeded and invoice.refunded | Records a paid order or invoice in AvaTax, or voids it when it's canceled. |
| test-connection | The Test connection action | Checks the credentials and the company code, and warns when Swell's built-in AvaTax integration is enabled (services.avatax.enabled in /settings/integrations). |
The app stores entity_use_code and exemption_number on accounts under $app.avatax. Calls go to the AvaTax REST API v2 at https://sandbox-rest.avatax.com/api/v2 or https://rest.avatax.com/api/v2, with basic auth and X-Avalara-Client: Swell; 1.0.0; REST; v2; Swell. A 2xx response with an error object is treated as status 400.
Swell runs the hook only for the extension selected in /settings/taxes, through extension_app_id and extension_config_id. Invoices don't run the hook: they copy the taxes of their subscription or order. The hook gets the change with the saved record in $record and merges them. It skips records with taxes_fixed, no usable address, or no items, plan and shipping service. Otherwise it reads /settings/shipments/locations, /settings/taxes, the account and the products, and sends POST /transactions/createoradjust with type: SalesOrder, commit: false, no code and today's date. AvaTax doesn't save SalesOrder documents, so carts and unpaid orders leave nothing in AvaTax.
The hook returns items[].taxes, shipment_tax, one taxes entry with the id avatax, and product_taxes for a subscription's plan. The name is summary[0].taxType plus tax, and the amount is the tax of the items and shipping. On failure it throws req.reject('avatax_failed', …, { status: 422 }) if block_on_failure is on. The hook has a deadline 8 seconds after it starts. It stops waiting for the locations, tax settings, account and products at the deadline, and aborts the AvaTax call after 6 seconds or at the deadline, whichever comes first. Both count as failures. Other AvaTax calls are aborted after 6 seconds. A hook that gives no answer fails open, and hooks get Swell's default 10 seconds.
Each item is a line with quantity_total, or quantity, and price_total minus discount_total, the SKU as itemCode (50 characters) and the name as description (2096 characters). Returned units are a second line with quantity_returned and the negative of return_price_total minus return_discount_total. The shipping line has the amount shipment_total, and an itemCode of the service ID in capitals, with _ as -, ending in -SHIPPING. A restocking fee is a line with the amount of return_credit_total as a negative, itemCode Restock fee and taxCode OR040000. Lines get taxIncluded from item_tax_included, tax_included or shipment_tax_included.
Lines use shipFrom and shipTo, or singleLocation with the customer's address when there's no usable ship-from address, or with the ship-from location when a paid record has no customer address. customerCode is the lowercased email, else the account ID, else guest. entityUseCode is sent when it's set, and exemptionNo only together with it.
*.updated events are handled only when $event.data has paid, canceled, void, items, shipping, billing, shipment_total, shipment_rating, return_credit_total, account_id, currency or taxes_fixed. The function also returns early when record_sales is off, a credential is missing, or the app isn't the selected tax service. It then reloads the record with items.product and account, plus subscription for invoices, and skips invoices created from an order.
A paid record is sent to the same endpoint with type: SalesInvoice, commit: true, code and purchaseOrderNo set to the document code, and date set to date_created. createoradjust updates the document when the code exists, so repeated events and retries are idempotent. Canceled orders and voided invoices call POST /companies/{company}/transactions/{code}/void?documentType=SalesInvoice with { "code": "DocVoided" }, and EntityNotFoundError and TransactionAlreadyCancelled count as done.
Network errors, timeouts, 429 and 5xx responses are rethrown so the platform retries the model event. Other AvaTax errors are logged with console.error and the function succeeds. Test connection calls GET /utilities/ping, checks authenticated, then calls GET /companies?$filter=companyCode eq '<code>' and checks isActive. Its errors are SwellErrors with status 400.
Swell builds and maintains the Avalara AvaTax app. For help with the app, email support@swell.is. For questions about your AvaTax account, nexus or filing, contact Avalara.