New France e-invoicing mandate goes live September 2026 — our implementation is ready. See all mandates →
Tax Calculations

Customs duties and landed cost

POST /v1/duties/quote returns an estimate of the import duty, import VAT/GST and customs fees on a cross-border cart, without recording a calculation. The same estimate comes back on POST /v1/tax/calculate and POST /v1/tax/calculate/partner when you pass duties.include: true (or turn on the dutiesEnabled setting). Every measure is named, so a broker can reproduce the figure.

ℹ
None of this is tax. No duty field is ever added to totalTax or totalAmountWithTax, and your tax figures are identical with duties off, on, or degraded. The one amount a checkout may add is summary.importChargesAtCheckout; summary.totalAmountDue, present only alongside it, is totalAmountWithTax plus that amount. Figures are estimates and are not guaranteed: reconcile any difference with the carrier or broker invoice.

See also the Tax Calculations reference for the full calculate request and response.

Request

What to send

The body is the POST /v1/tax/calculate body. duties.include is implied on a quote; commit, credit notes and transactionDirection: "purchase" are rejected with 422. A quote is stateless: nothing is stored and no idempotency key is read. A partner_calc key adds the same required sellerRegistrationContext and partnerMerchantId as POST /v1/tax/calculate/partner.

FieldTypeDescription
lineItems[].commodityCodestringThe tariff code the duty is priced at. The most important input: it decides the precision of the estimate.
lineItems[].commodityCodeScheme"HS6" | "CN8" | "TARIC10" | "UK10" | "HTS10"Scheme of that code. Omitted: inferred from the digit count and the destination (schemeInferred: true on the result). A national code is exact only in its own territory; anywhere else its first six digits are used and the result is HS6_EXACT or HS6_AMBIGUOUS, not an error.
lineItems[].countryOfOriginstringISO 3166-1 alpha-2. Never inferred from shipFrom. Falls back to the product catalogue, then duties.defaultCountryOfOrigin, then the account default.
lineItems[].weightobject{ value, unit } with unit kg, g, lb or oz; per unit. Needed for per-kilogram duties.
shipFrom / lineItems[].shipFromobjectWhere goods are dispatched from; a different customs territory from the destination makes a customs crossing. customsStatus: "bonded" marks stock held under customs control.
incoterms / importerOfRecordstringWho imports. importerOfRecord wins over incoterms (DDP is the seller, any other rule the buyer), which wins over the account defaultImporterOfRecord.
insuranceobject{ amount, currency? }, part of the customs value where the destination values goods CIF.
duties.collectDepositbooleanAsk for the estimate to be collected at checkout when the buyer is the importer.
duties.defaultCountryOfOrigin, duties.ratePolicyForHs6stringPer-request overrides of the account settings. ratePolicyForHs6 is modal or highest; a collected deposit always uses the highest rate.

Mapping a Shopify product

ShopifyClearvo line item
harmonizedSystemCodecommodityCode (scheme inferred, or set commodityCodeScheme)
countryHarmonizedSystemCodes[]The entry for the destination country is its commodityCode with that country's national commodityCodeScheme.
countryCodeOfOrigincountryOfOrigin
weight and weightUnitweight.value and weight.unit
Product taxonomy categoryclassificationCodes: [{ "system": "shopify", "code": "aa-1-13" }]. Used when no code is sent, so the line is priced from its category as a proxy and never collected.
Response

What to show at checkout

Decide by consignments[].responsibleParty and collectedAtCheckout. Every quoted consignment also carries collection.reason, which says why nothing is collected when you asked for a deposit.

responsiblePartycollectedAtCheckoutTypical caseTax fields (unchanged)Show the buyer
sellerfalseDDP registered seller; IOSS up to €150 (the €3 is the IOSS holder's cost)Normal destination VAT/GST or IOSS at checkout, or US sales tax on the priceNothing new. Use landedCost for pricing and margin.
customerfalseDAP or buyer importer, no depositOUT_OF_SCOPE, tax code O, rate 0Optional notice: "Import duties and taxes of approximately X may be payable to the carrier on delivery." Not added to the total.
customertrueDeposit model (duties.collectDeposit, buyer is importer)Same as aboveAdd summary.importChargesAtCheckout as its own line, "Estimated import charges"; charge totalAmountDue. Never label it tax. Refund any excess.
anyanyduties.status: "not_applicable": domestic, intra-EU, GB to GBNormalNothing.

Reading an estimate

  • duties.status is quoted, not_applicable, degraded or disabled. A duty failure is a 200 with degraded and a reason, never a 5xx, and it never changes the tax figures or the calculation's own degraded flag.
  • estimate: false means no modelled source of variance (a flat or zero regime, or tariff-line precision with no origin-scoped measure and no static FX). It is never a guarantee: the declarant's classification, valuation, origin and declaration choices prevail. estimateReasons is the closed list behind estimate: true.
  • precision runs TARIFF_LINE, HS6_EXACT, HS6_AMBIGUOUS, PLATFORM_CODE, CATEGORY_PROXY, CHAPTER_PROXY, UNRESOLVED. The last three are never collected from a buyer.
  • Each measure carries its rateExpression, a closed union: ad_valorem_pct, top_up_to_pct, flat, specific, compound, alternative and min_max.
  • Measures that exist but could not be evaluated (not yet in force, or origin unknown) are in notEvaluated and block collection.
  • The IOSS response may also carry customsDuty. It is the same €3 per item as the consignment's duty (source fee_rule): customsDuty is that one fee, consignments[] is the whole landed-cost estimate, so never add the two together.
  • Amounts using a static FX rate say so in fx.source and fxSource; they are not live rates.

Turn duties on for the account with PATCH /v1/tax/settings: dutiesEnabled, dutyRatePolicyForHs6, defaultCountryOfOrigin. The quote_duties tool in the Clearvo MCP server and clearvo duties quote in the CLI call this endpoint; the TypeScript SDK exposes quoteDuties() and the DutiesResult type.

Worked examples

Example 1: $40 China-origin T-shirt, UK warehouse to Texas

JSON request — POST /v1/duties/quote
{
  "currency": "USD",
  "date": "2026-10-03",
  "supplier": {
    "name": "Acme Apparel Ltd",
    "billingAddress": {
      "country": "GB",
      "postalCode": "SW1A 1AA"
    }
  },
  "customer": {
    "name": "Jordan Lee",
    "billingAddress": {
      "country": "US",
      "region": "TX",
      "postalCode": "78701"
    },
    "shippingAddress": {
      "country": "US",
      "region": "TX",
      "postalCode": "78701"
    }
  },
  "shipFrom": {
    "country": "GB",
    "postalCode": "SW1A 1AA"
  },
  "lineItems": [
    {
      "id": "l1",
      "amount": 40,
      "quantity": 1,
      "productName": "Cotton T-shirt",
      "commodityCode": "6109100012",
      "commodityCodeScheme": "HTS10",
      "countryOfOrigin": "CN"
    }
  ],
  "duties": {
    "include": true
  }
}
JSON response
{
  "currency": "USD",
  "duties": {
    "status": "quoted",
    "contentVersion": 1
  },
  "consignments": [
    {
      "id": "c1",
      "lineIds": [
        "l1"
      ],
      "status": "quoted",
      "dispatchTerritory": "GB",
      "destinationTerritory": "US",
      "customsStatus": "free_circulation",
      "valuation": {
        "basis": "FOB",
        "goods": 40,
        "freight": 0,
        "insurance": 0,
        "customsValue": 40,
        "currency": "USD"
      },
      "regime": null,
      "duty": {
        "total": 9.6,
        "source": "tariff",
        "estimate": true
      },
      "importTax": {
        "label": null,
        "collection": "none",
        "base": 40,
        "rate": 0,
        "amount": 0,
        "baseIncludes": [
          "customs_value"
        ],
        "sellerRegistrationRequired": false,
        "notes": []
      },
      "fees": [
        {
          "code": "US_MPF_INFORMAL",
          "label": "Merchandise Processing Fee (informal entry)",
          "amount": 2.77,
          "currency": "USD",
          "basis": "flat",
          "entryType": "informal",
          "entryTypeAssumed": true,
          "incidence": "SELLER_COST"
        }
      ],
      "responsibleParty": "unresolved",
      "responsiblePartySource": "unresolved",
      "collectedAtCheckout": false,
      "collection": {
        "requested": false,
        "collected": false,
        "reason": "not_requested"
      },
      "landedCost": 52.37,
      "importChargesAtCheckout": 0,
      "sellerBorne": {
        "duty": 0,
        "importTax": 0,
        "fees": 0,
        "total": 0
      },
      "precision": "TARIFF_LINE",
      "estimate": true,
      "estimateReasons": [
        "origin_measures_apply",
        "measure_not_in_force",
        "preference_not_considered",
        "entry_type_assumed"
      ],
      "notEvaluated": [
        {
          "familyCode": "US_301_BY_ORIGIN_CN",
          "measureType": "SECTION_301_BY_ORIGIN",
          "reason": "not_in_force",
          "legalStatus": "announced"
        }
      ],
      "fxSource": null,
      "sellerRegistrationGap": false
    }
  ],
  "lineItems": [
    {
      "id": "l1",
      "duty": {
        "consignmentId": "c1",
        "commodityCode": "6109100012",
        "scheme": "HTS10",
        "codeSource": "request",
        "precision": "TARIFF_LINE",
        "origin": "CN",
        "originSource": "request",
        "customsValue": 40,
        "amount": 9.6,
        "measures": [
          {
            "type": "MFN",
            "rate": 0.165,
            "rateExpression": {
              "type": "ad_valorem_pct",
              "value": 16.5
            },
            "amount": 6.6,
            "legalBasis": null,
            "effectiveFrom": "2026-01-01"
          },
          {
            "type": "SECTION_301_LIST_4A",
            "rate": 0.075,
            "rateExpression": {
              "type": "ad_valorem_pct",
              "value": 7.5
            },
            "amount": 3,
            "legalBasis": "HTSUS 9903.88.15",
            "effectiveFrom": "2026-01-01"
          }
        ],
        "notEvaluated": [
          {
            "familyCode": "US_301_BY_ORIGIN_CN",
            "measureType": "SECTION_301_BY_ORIGIN",
            "reason": "not_in_force",
            "legalStatus": "announced"
          }
        ],
        "missingInputs": [],
        "estimateReasons": [
          "origin_measures_apply",
          "measure_not_in_force",
          "preference_not_considered"
        ]
      }
    }
  ],
  "summary": {
    "totalDuty": 9.6,
    "totalImportTax": 0,
    "totalImportFees": 2.77,
    "totalLandedCost": 52.37,
    "sellerBorneImportCosts": 0
  }
}

How to read it

  • Duty $9.60: 16.5% MFN ($6.60) plus 7.5% Section 301 List 4A ($3.00). The by-origin China measure is announced, not in force: it is listed in notEvaluated and never applied.
  • The informal-entry Merchandise Processing Fee of $2.77 applies (a $40 parcel is an informal entry, entryTypeAssumed: true), not the $34.58 formal-entry minimum. A fee is a seller cost and is never added to what the buyer pays.
  • No importer of record is set, so responsibleParty is unresolved and nothing is collected (collection.reason: not_requested). Texas sales tax on the $40 is unchanged. estimate: true because origin-scoped measures apply and one is not in force.
Worked examples

Example 2: €120 item, UK to France, IOSS-registered seller

JSON request — POST /v1/duties/quote
{
  "currency": "EUR",
  "date": "2026-10-03",
  "supplier": {
    "name": "Acme Apparel Ltd",
    "billingAddress": {
      "country": "GB",
      "postalCode": "SW1A 1AA"
    }
  },
  "customer": {
    "name": "Camille Martin",
    "billingAddress": {
      "country": "FR",
      "postalCode": "75001"
    },
    "shippingAddress": {
      "country": "FR",
      "postalCode": "75001"
    }
  },
  "shipFrom": {
    "country": "GB",
    "postalCode": "SW1A 1AA"
  },
  "importerOfRecord": "BUYER",
  "lineItems": [
    {
      "id": "l1",
      "amount": 120,
      "quantity": 1,
      "productName": "Cotton T-shirt",
      "commodityCode": "61091000",
      "commodityCodeScheme": "CN8",
      "countryOfOrigin": "GB"
    }
  ],
  "duties": {
    "include": true,
    "collectDeposit": true
  }
}
JSON response
{
  "currency": "EUR",
  "duties": {
    "status": "quoted",
    "contentVersion": 1
  },
  "consignments": [
    {
      "id": "c1",
      "lineIds": [
        "l1"
      ],
      "status": "quoted",
      "dispatchTerritory": "GB",
      "destinationTerritory": "EU",
      "customsStatus": "free_circulation",
      "valuation": {
        "basis": "CIF",
        "goods": 120,
        "freight": 0,
        "insurance": 0,
        "customsValue": 120,
        "currency": "EUR"
      },
      "regime": {
        "code": "EU_IOSS_150",
        "name": "EU_IOSS_150",
        "basis": "intrinsic_value",
        "thresholdAmount": 150,
        "thresholdCurrency": "EUR",
        "comparedValue": 120,
        "nearThreshold": false,
        "consequence": {
          "vat": "checkout",
          "duty": "flat_per_item"
        },
        "feeCode": "EU_LOW_VALUE_CONSIGNMENT_CUSTOMS_DUTY",
        "taxTreatmentMismatch": false,
        "notes": []
      },
      "duty": {
        "total": 3,
        "source": "fee_rule",
        "feeCode": "EU_LOW_VALUE_CONSIGNMENT_CUSTOMS_DUTY",
        "estimate": false
      },
      "importTax": {
        "label": "VAT",
        "collection": "checkout",
        "base": 123,
        "rate": 0,
        "amount": 0,
        "baseIncludes": [
          "customs_value",
          "duty",
          "freight"
        ],
        "sellerRegistrationRequired": false,
        "notes": []
      },
      "fees": [],
      "responsibleParty": "seller",
      "responsiblePartySource": "regime",
      "collectedAtCheckout": false,
      "collection": {
        "requested": true,
        "collected": false,
        "reason": "regime_vat_at_checkout"
      },
      "landedCost": 123,
      "importChargesAtCheckout": 0,
      "sellerBorne": {
        "duty": 3,
        "importTax": 0,
        "fees": 0,
        "total": 3
      },
      "precision": null,
      "estimate": false,
      "estimateReasons": [],
      "notEvaluated": [],
      "fxSource": null,
      "sellerRegistrationGap": false
    }
  ],
  "lineItems": [
    {
      "id": "l1",
      "duty": {
        "consignmentId": "c1",
        "commodityCode": "61091000",
        "scheme": "CN8",
        "codeSource": "request",
        "precision": null,
        "origin": "GB",
        "originSource": "request",
        "customsValue": 120,
        "amount": 3,
        "measures": [
          {
            "type": "REGIME_FLAT",
            "rate": null,
            "rateExpression": {
              "type": "flat",
              "amount": 0,
              "currency": "EUR"
            },
            "amount": 3,
            "legalBasis": null,
            "effectiveFrom": "2026-07-01"
          }
        ],
        "notEvaluated": [],
        "missingInputs": [],
        "estimateReasons": []
      }
    }
  ],
  "summary": {
    "totalDuty": 3,
    "totalImportTax": 0,
    "totalImportFees": 0,
    "totalLandedCost": 123,
    "sellerBorneImportCosts": 3
  }
}

How to read it

  • French VAT is collected at checkout under IOSS and sits in totalTax, so import VAT is 0 with collection: "checkout" and nothing is added to the buyer's total.
  • The EU €3 per-item customs duty is the IOSS holder's cost: responsibleParty: "seller", collection.reason: "regime_vat_at_checkout", importChargesAtCheckout: 0, sellerBorne.duty: 3.
  • Asking for a deposit and naming the buyer as importer changes nothing: under IOSS the declarant is the seller. estimate: false means no modelled source of variance, not a guarantee.
Worked examples

Example 3: the same item at €200, China origin, DAP

JSON request — POST /v1/duties/quote
{
  "currency": "EUR",
  "date": "2026-10-03",
  "supplier": {
    "name": "Acme Apparel Ltd",
    "billingAddress": {
      "country": "GB",
      "postalCode": "SW1A 1AA"
    }
  },
  "customer": {
    "name": "Camille Martin",
    "billingAddress": {
      "country": "FR",
      "postalCode": "75001"
    },
    "shippingAddress": {
      "country": "FR",
      "postalCode": "75001"
    }
  },
  "shipFrom": {
    "country": "GB",
    "postalCode": "SW1A 1AA"
  },
  "incoterms": "DAP",
  "lineItems": [
    {
      "id": "l1",
      "amount": 200,
      "quantity": 1,
      "productName": "Cotton T-shirt",
      "commodityCode": "61091000",
      "commodityCodeScheme": "CN8",
      "countryOfOrigin": "CN"
    },
    {
      "id": "ship",
      "amount": 12,
      "productName": "Shipping",
      "taxCategory": "shipping_handling"
    }
  ],
  "duties": {
    "include": true,
    "collectDeposit": true
  }
}
JSON response
{
  "currency": "EUR",
  "duties": {
    "status": "quoted",
    "contentVersion": 1
  },
  "consignments": [
    {
      "id": "c1",
      "lineIds": [
        "l1"
      ],
      "status": "quoted",
      "dispatchTerritory": "GB",
      "destinationTerritory": "EU",
      "customsStatus": "free_circulation",
      "valuation": {
        "basis": "CIF",
        "goods": 200,
        "freight": 12,
        "insurance": 0,
        "customsValue": 212,
        "currency": "EUR"
      },
      "regime": null,
      "duty": {
        "total": 25.44,
        "source": "tariff",
        "estimate": false
      },
      "importTax": {
        "label": "VAT",
        "collection": "border",
        "base": 237.44,
        "rate": 0.2,
        "amount": 47.49,
        "baseIncludes": [
          "customs_value",
          "duty",
          "freight"
        ],
        "sellerRegistrationRequired": false,
        "notes": []
      },
      "fees": [],
      "responsibleParty": "customer",
      "responsiblePartySource": "incoterms",
      "collectedAtCheckout": true,
      "collection": {
        "requested": true,
        "collected": true,
        "reason": "collected"
      },
      "landedCost": 284.93,
      "importChargesAtCheckout": 72.93,
      "sellerBorne": {
        "duty": 0,
        "importTax": 0,
        "fees": 0,
        "total": 0
      },
      "precision": "TARIFF_LINE",
      "estimate": false,
      "estimateReasons": [],
      "notEvaluated": [],
      "fxSource": null,
      "sellerRegistrationGap": false
    }
  ],
  "lineItems": [
    {
      "id": "l1",
      "duty": {
        "consignmentId": "c1",
        "commodityCode": "61091000",
        "scheme": "CN8",
        "codeSource": "request",
        "precision": "TARIFF_LINE",
        "origin": "CN",
        "originSource": "request",
        "customsValue": 212,
        "amount": 25.44,
        "measures": [
          {
            "type": "MFN",
            "rate": 0.12,
            "rateExpression": {
              "type": "ad_valorem_pct",
              "value": 12
            },
            "amount": 25.44,
            "legalBasis": null,
            "effectiveFrom": "2026-01-01"
          }
        ],
        "notEvaluated": [],
        "missingInputs": [],
        "estimateReasons": []
      }
    }
  ],
  "summary": {
    "totalDuty": 25.44,
    "totalImportTax": 47.49,
    "totalImportFees": 0,
    "totalLandedCost": 284.93,
    "sellerBorneImportCosts": 0,
    "importChargesAtCheckout": 72.93,
    "totalAmountDue": 284.93
  }
}

How to read it

  • Above €150 no low-value regime applies. Duty €25.44 is 12% of a CIF customs value of €212 (200 goods + 12 freight). Import VAT €47.49 is 20% of customs value plus duty (€237.44).
  • incoterms: "DAP" makes the buyer the importer and a deposit was requested, so collectedAtCheckout is true and summary.importChargesAtCheckout is €72.93. Show it as its own line, "Estimated import charges"; charge totalAmountDue.
  • With incoterms: "DDP" the same cart is seller-borne and nothing is collected.
Sources

Data sources and attribution

  • United Kingdom: Contains public sector information licensed under the Open Government Licence v3.0.
  • European Union: Combined Nomenclature and TARIC data, source acknowledged in accordance with Commission Decision 2011/833/EU on the reuse of Commission documents.
  • United States: Harmonized Tariff Schedule of the United States (HTSUS), a public-domain work of the US International Trade Commission.

Estimates only, with no guarantee of accuracy. Clearvo is not a customs broker and does not file entries.