Skip to main content

Taxes and Duties (Landed Cost)

Get the import VAT and import duties a shipment will attract, alongside the freight cost.

What you get

When Stream estimates taxes and duties, two extra line items appear in the estimate's line_items:

DescriptionWhat it is
Import DutiesCustoms duty payable on the goods entering the destination country
Import VATImport VAT / GST payable on the import into the destination country

They sit alongside Base Rate, Fuel Surcharge and the rest, in the same currency, so the estimate total is the landed cost rather than the freight cost.

These are estimates. They are calculated from the HS codes you supply and the destination's tariff schedule, and the amount customs actually assesses can differ. Stream re-estimates when the order is placed and again if the goods are re-declared.

Asking for them on a quote

Set estimate_taxes_and_duties: true on Create Quote, and send hs_codes.

{
"estimate_taxes_and_duties": true,
"purpose_of_shipment_id": 8,
"hs_codes": [
{
"code": "8544429000",
"description": "insulated copper cable, 2m, with connectors",
"country_id": 226,
"quantity": 10,
"weight": 0.4,
"cost": 12.50
}
]
}

The response echoes estimate_taxes_and_duties back, so you can confirm the request was honoured:

{
"id": 1,
"estimate_taxes_and_duties": true,
"estimates": [
{
"estimate_id": 55788,
"shipping_company": "DHL Express",
"line_items": [
{ "description": "Base Rate", "cost": 920.00, "currency_id": "USD" },
{ "description": "Fuel Surcharge", "cost": 138.00, "currency_id": "USD" },
{ "description": "Import Duties", "cost": 46.75, "currency_id": "USD" },
{ "description": "Import VAT", "cost": 220.31, "currency_id": "USD" }
]
}
]
}

The default is false. Omit it and you get a freight-only quote, exactly as before — existing integrations are unaffected.

HS code fields

hs_codes is an array, and takes the same fields on Create Quote and Create Order.

FieldTypeRequiredDescription
codestringYesThe HS / commodity code — see Code length matters
descriptionstringYesPlain description of the goods, max 250 characters
country_idintegerYesCountry of manufacture, not of origin or destination
weightnumberYesMass of one unit, in the request's mass_unit
quantitynumberNoNumber of units on this line
costnumberNoValue of one unit, in the request's value_of_goods_currency_id
eccnstringNoExport Control Classification Number, where one applies
nature_of_transactionstringNoEU nature-of-transaction code

weight and cost are per unit, not line totals. A line of 10 cables at 0.4 kg each is quantity: 10, weight: 0.4 — not weight: 4.

item_mass and item_value are accepted as synonyms for weight and cost.

When you will get nothing back

Estimation is skipped silently — no error, just no Import VAT or Import Duties line items. Every one of these must hold:

  1. The shipment must clear customs. Skipped when the route is intra-EU, domestic (same origin and destination country), between the US and Puerto Rico, or when is_document: true.
  2. The incoterm must make you liable. Only DDP, EXW, FOB and FCA qualify. On DAP / DDU the consignee settles with customs directly, so Stream does not estimate.
  3. You must send hs_codes. The calculation is driven off them.
  4. The value must exceed the destination's de minimis threshold. Below it, no VAT or duty is due and nothing is returned. The exception is goods manufactured in China entering the US, where de minimis never applies.

Two further cases return duties but no VAT:

  • Your company holds a VAT deferment for the destination country, so import VAT is settled through your own arrangement rather than billed by Stream.
  • The reason_for_shipment_id is a return, a temporary export or import, or mutilated samples — these waive clearance charges, and waive both VAT and duties.
is_document: true is the most common surprise

A document shipment never clears customs, so it never attracts VAT or duties, whatever the incoterm and whatever you send. If you are getting freight-only estimates on a DDP lane, check this field first.

Code length matters

Stream does not reject a short code, and that is the trap. Destinations tariff on a specific number of digits — commonly eight or ten, six at the least. A code shorter than the destination requires still returns an estimate, but a less accurate one, and it is the single biggest source of an estimate that does not match the customs bill.

Send the full code your destination expects. Six digits is the shortest that carries any tariff meaning; anything below that is close to a guess.

Taxes and duties on orders

Orders estimate taxes and duties automatically. There is no field to set on Create Order and nothing to opt into — when the order is placed, Stream estimates against the same four conditions above and adds the charges if they apply.

This means a quote requested without estimate_taxes_and_duties can still become an order that carries import VAT and duties. The freight-only quote was never the landed cost, it just did not say so. Quote with estimate_taxes_and_duties: true when you need to show a customer the full cost up front.

The charges appear on Get Orders under invoice_data.line_items, with the same Import Duties and Import VAT descriptions.