Taxes
Saleor offers two ways of calculating taxes:
- flat rates (simple, static rates)
- dynamic taxes (real-time calculations from external providers).
You can configure the tax calculation method per sales channel and override it for specific countries.
Tax Configuration​
Tax configuration controls how taxes are calculated and displayed in your store. Each sales channel has its own tax configuration that determines:
- Whether taxes are charged in a channel
- Which calculation method to use (flat rates or tax app)
- Whether prices include taxes
- How prices are displayed in your storefront
Where to Configure Taxes​
You can configure taxes in two ways:
In Saleor Dashboard:
- Go to Configuration → Taxes
- Select the channel you want to configure
- Adjust the tax settings for that channel
Via API:
Use the taxConfigurationUpdate mutation to update tax settings programmatically.
Key Configuration Settings​
- Charge taxes - When enabled, customers pay prices including tax. When disabled, taxes are still calculated and available for display, but customers pay the net prices.
- Tax calculation method - Choose between flat rates (default) or dynamic taxes (tax apps).
- Display gross prices - Controls whether your storefront shows prices with tax included. This only affects display, not calculations.
- Prices entered with tax - Indicates whether your product prices include tax (common in EU B2C) or exclude tax (common in US and B2B).
- Use weighted tax for shipping - When enabled, shipping tax is calculated as a weighted average of product tax rates. Available only when using the
FLAT_RATEStax calculation strategy (from Saleor 3.21).
Tax classes​
The Tax Class is the most critical configuration setting for accurate tax calculation. They allow you to:
- For Flat Rates: Override default country rates for specific items (e.g., reduced rates for books).
- For Dynamic Taxes: Map products or shipping methods to specific provider tax codes (e.g., AvaTax Tax Codes).
How to create tax classes:​
In Dashboard:
- Go to Configuration → Taxes
- Click on Tax Classes tab
- Click Add tax class or edit an existing one
- Enter a name for the tax class (e.g., "Healthcare products")
- Add tax rates for each country where you sell
- Save the tax class
- Assign the tax class to products, product types or shipping method:
- For individual products: Go to Catalog → Products, select a product, and assign the tax class
- For product types: Go to Configuration → Product Types, select a product type, and assign the tax class
- For shipping methods: Go to Configuration -> Shipping Methods, select shipping zone, select rate, and assign the tax class
Via API:
Create a tax class:
- Mutation
- Variables
mutation TaxClassCreate($input: TaxClassCreateInput!) {
taxClassCreate(input: $input) {
errors {
field
message
}
taxClass {
id
name
countries {
rate
}
}
}
}
{
"input": {
"name": "Healthcare products",
"createCountryRates": [
{
"countryCode": "PL",
"rate": 8
}
]
}
}
Assign the tax class to a product:
- Mutation
- Variables
mutation ProductUpdate($id: ID, $input: ProductInput!) {
productUpdate(id: $id, input: $input) {
errors {
field
message
}
product {
taxClass {
name
}
}
}
}
{
"id": "UHJvZHVjdDox",
"input": {
"taxClass": "VGF4Q2xhc3M6Mg=="
}
}
Assign the tax class to a product type:
- Mutation
- Variables
mutation ProductTypeUpdate($id: ID!, $input: ProductTypeInput!) {
productTypeUpdate(id: $id, input: $input) {
errors {
field
message
}
productType {
taxClass {
name
}
}
}
}
{
"id": "UHJvZHVjdFR5cGU6MQ==",
"input": {
"taxClass": "VGF4Q2xhc3M6Mg=="
}
}
Assign the tax class to a shipping method:
- Mutation
- Variables
mutation UpdateShippingRate($id: ID!, $input: ShippingPriceInput!) {
shippingPriceUpdate(id: $id, input: $input) {
errors {
field
code
message
}
shippingMethod {
taxClass{
name
}
}
}
}
{
"id": "U2hpcHBpbmdNZXRob2RUeXBlOjM=",
"input": {
"taxClass": "VGF4Q2xhc3M6Mg=="
}
}
Fetching Tax Configurations​
To view your current tax configuration use query:
- Query
query TaxConfigurations {
taxConfigurations(first: 10) {
edges {
node {
id
channel {
slug
}
chargeTaxes
displayGrossPrices
pricesEnteredWithTax
taxCalculationStrategy
taxAppId
}
}
}
}
Which Address is Used for Tax Calculation?​
Saleor determines which address to use for tax calculation in this order of priority:
- Shipping address (if available)
- Billing address (if shipping address is not available)
- Channel's default country (if neither address is available)
This means:
- For shippable products, taxes are calculated based on where the product is being shipped
- For digital products, taxes are calculated based on the billing address
- If no address is provided, taxes use the channel's default country
Example scenarios:
sShippable products:*
- Customer adds items to cart → No address yet → Uses channel default country
- Customer enters billing address → Uses billing address for tax calculation
- Customer enters shipping address → Now uses shipping address for tax calculation
Digital products:
- Customer adds digital items → No address yet → Uses channel default country
- Customer enters billing address → Uses billing address for tax calculation
Click and collect:
- Customer adds items to cart → No address yet → Uses channel default country
- Customer enters billing address → Uses billing address for tax calculation
- Customer enters shipping address → Now uses shipping address for tax calculation
- Customer selects a collection point, the warehouse address becomes the shipping address and is used for tax calculation
Flat Rates​
Flat rates are the default tax calculation method in Saleor. They use static, manually configured tax rates that you set up for each country. This method is ideal for stores that:
- Operate in a limited number of countries
- Have straightforward tax requirements
- Want full control over tax rates
- Don't need real-time tax rate updates
Business Use Cases​
Flat rates work well for:
- Stores with simple tax structures (e.g., single VAT rate per country)
- Stores operating in regions with stable tax rates
How to Configure Flat Rates​
Step 1: Enable Flat Rates for Your Channel​
In Dashboard:
- Go to Configuration → Taxes
- Select your channel
- Set Method of tax calculation to "Use flat tax rate"
- Save
Via API:
- Mutation
- Variables
mutation TaxConfigurationUpdate($id: ID!, $input: TaxConfigurationUpdateInput!) {
taxConfigurationUpdate(id: $id, input: $input) {
errors {
field
message
}
taxConfiguration {
taxCalculationStrategy
}
}
}
{
"id": "VGF4Q29uZmlndXJhdGlvbjox",
"input": {
"taxCalculationStrategy": "FLAT_RATES"
}
}
Step 2: Set Default Country Rates​
Set default tax rates for each country where you sell. These rates apply to all products that don't have a specific tax class.
In Dashboard:
- Go to Configuration → Taxes
- Select Countries tab
- Click Add country or edit an existing one
- Enter the tax rate percentage (e.g., 23 for 23%)
- Save
Via API:
Use the taxCountryConfigurationUpdate mutation to set default country rates:
- Mutation
- Variables
mutation TaxCountryConfigurationUpdate($countryCode: CountryCode!, $updateTaxClassRates: [TaxClassRateInput!]!) {
taxCountryConfigurationUpdate(
countryCode: $countryCode
updateTaxClassRates: $updateTaxClassRates
) {
taxCountryConfiguration {
country {
code
}
taxClassCountryRates {
rate
}
}
errors {
field
message
}
}
}
{
"countryCode": "PL",
"updateTaxClassRates": [
{
"rate": 23
}
]
}
This example sets a 23% default tax rate for Poland.
Step 3: Create Tax Classes (Optional)​
Tax classes are needed when some products require different tax rates than the default country rate. For example, if you sell healthcare products in Poland that are taxed at 8% instead of the standard 23%, you need a tax class for them. If all your products use the same tax rate, you can skip this step.
Example Calculations​
Here are practical examples of how flat rates calculate taxes:
Example 1: Simple product with default rate
- Product price: $100.00
- Default country rate (Poland): 23%
- Tax amount: $100 × 0.23 = $23.00
- Total price: $123.00
Example 2: Product with tax class
- Product price: $100.00
- Tax class rate (Healthcare, Poland): 8%
- Tax amount: $100 × 0.08 = $8.00
- Total price: $108.00
Example 3: Multiple products with different rates
- Product A (standard): $100.00 at 23% = $23.00 tax
- Product B (healthcare): $50.00 at 8% = $4.00 tax
- Total tax: $27.00
- Total price: $177.00
Shipping Tax Rates​
You can configure shipping tax rates in two ways:
- Static rate - Assign a tax class to the shipping method
- Weighted rate - Calculate shipping tax as a weighted average of product tax rates (available from Saleor 3.21 and only when using the
FLAT_RATEStax calculation strategy)
Enabling Weighted Shipping Tax (API)​
Enable for the Whole Channel​
Use taxConfigurationUpdate to enable weighted shipping tax for a channel:
- Mutation
- Variables
mutation TaxConfigurationUpdate($id: ID!, $input: TaxConfigurationUpdateInput!) {
taxConfigurationUpdate(id: $id, input: $input) {
taxConfiguration {
useWeightedTaxForShipping
taxCalculationStrategy
}
errors {
field
message
}
}
}
{
"id": "VGF4Q29uZmlndXJhdGlvbjox",
"input": {
"taxCalculationStrategy": "FLAT_RATES",
"useWeightedTaxForShipping": true
}
}
Enable for a Specific Country​
You can also enable weighted shipping tax only for selected countries within a channel:
- Mutation
- Variables
mutation TaxConfigurationUpdate($id: ID!, $input: TaxConfigurationUpdateInput!) {
taxConfigurationUpdate(id: $id, input: $input) {
taxConfiguration {
countries {
country {
code
}
useWeightedTaxForShipping
taxCalculationStrategy
}
}
errors {
field
message
}
}
}
{
"id": "VGF4Q29uZmlndXJhdGlvbjox",
"input": {
"updateCountriesConfiguration": [
{
"countryCode": "CA",
"taxCalculationStrategy": "FLAT_RATES",
"useWeightedTaxForShipping": true,
"chargeTaxes": true,
"displayGrossPrices": true
}
]
}
}
For weighted shipping tax, Saleor calculates:
Weighted rate = (Σ line_net_price × line_tax_rate) / (Σ line_net_price)
Example:
- Product 1: $100 at 23% tax
- Product 2: $100 at 8% tax
- Shipping: $20
- Weighted shipping tax rate: (100×0.23 + 100×0.08) / (100 + 100) = 15.5%
- Shipping tax: $20 × 0.155 = $3.10
Dynamic Taxes​
Dynamic taxes delegate tax calculations to external tax providers like AvaTax, TaxJar, or custom tax apps. Instead of manually setting static rates, these providers calculate taxes in real-time based on current tax rules, product types, customer locations, and other factors.
Business Use Cases​
Dynamic taxes are ideal for:
- Stores with complex tax requirements (city, county, state taxes)
- Stores requiring tax compliance features (reporting, filing)
- Stores selling to businesses that need tax exemption handling
What Needs to Be Configured​
To use dynamic taxes, you need to:
-
Install a tax app - Install a tax provider app from the Saleor App Store (e.g., AvaTax)
-
Configure the tax app - Set up credentials and settings in the app
-
Enable dynamic taxes for channels - Switch your channel's tax calculation method to use the tax app:
In Dashboard:
- Go to Configuration → Taxes
- Select your channel
- Set Method of tax calculation to "Use app Tax app name"
- Save
Via API:
- Mutation
- Variables
mutation TaxConfigurationUpdate($id: ID!, $input: TaxConfigurationUpdateInput!) {
taxConfigurationUpdate(id: $id, input: $input) {
errors {
field
message
}
taxConfiguration {
taxCalculationStrategy
taxAppId
}
}
}{
"id": "VGF4Q29uZmlndXJhdGlvbjox",
"input": {
"taxCalculationStrategy": "TAX_APP",
"taxAppId": "saleor.tax"
}
} -
Create and assign tax classes to products, map tax classes in Tax App into tax provider codes - Every product must have a tax class that maps to the provider's tax codes
For detailed AvaTax configuration instructions, see the AvaTax App Configuration guide.
To see available tax apps, use query:
query GetShop {
shop {
availableTaxApps {
id
name
identifier
}
}
}
Country-Specific Configuration in Channel​
You can use different tax calculation methods for different countries within the same channel. For example, use flat rates for EU countries and dynamic taxes for the US:
In Dashboard:
- Go to Configuration → Taxes
- Select your channel
- Scroll down to the Country exceptions section
- Click Add country or edit an existing country configuration
- Select the country you want to configure
- Set the Method of tax calculation for that country (flat rates or a specific tax app)
- Configure other tax settings for that country if needed (charge taxes, display gross prices, etc.)
- Save the configuration
- Repeat for each country that needs a different tax calculation method
Via API:
- Mutation
- Variables
mutation TaxConfigurationUpdate($id: ID!, $input: TaxConfigurationUpdateInput!) {
taxConfigurationUpdate(id: $id, input: $input) {
errors {
field
message
}
taxConfiguration {
taxCalculationStrategy
countries {
country {
code
}
taxCalculationStrategy
}
}
}
}
{
"id": "VGF4Q29uZmlndXJhdGlvbjox",
"input": {
"taxCalculationStrategy": "FLAT_RATES",
"updateCountriesConfiguration": [
{
"countryCode": "US",
"taxCalculationStrategy": "TAX_APP",
"taxAppId": "saleor.tax"
}
]
}
}
Rounding Rules​
Saleor uses standard rounding rules for tax calculations:
- If the discarded fraction is >= 0.5, round up
- If the discarded fraction is < 0.5, round down
Examples:
- $9.945 → $9.95
- $9.94499 → $9.94
Most currencies are calculated to 2 decimal places.
Tax Exemption​
You can exempt specific checkouts or orders from taxes using the Tax Exemption API. This is useful for tax-exempt customers or special cases.
- Mutation
- Variables
mutation TaxExemptionManage($id: ID!, $taxExemption: Boolean!) {
taxExemptionManage(id: $id, taxExemption: $taxExemption) {
errors {
field
message
}
taxableObject {
... on Checkout {
taxExemption
}
}
}
}
{
"id": "Q2hlY2tvdXQ6ZTZiMzAzYmMtMzc2Zi00YThkLTkxYzAtNmU3MjYyNDU1OWU3",
"taxExemption": true
}
Tax exemption requires the MANAGE_TAXES permission.