Duty rules belong to market countries. Reads require read_markets; writes require write_markets. Rules can be configured while duties are disabled. Each country has at most one rule. Its de minimis value is an exact decimal in the currency assigned to that country in Pricing. Default and HS-code rates preserve one of three explicit shapes: ad_valorem uses rate, specific uses amount plus per, and compound uses all three. Irrelevant fields are rejected, not ignored. HS codes accept dotted, spaced, or hyphenated display forms but are stored canonically as an even 2-12 digit code; canonical collisions fail the write. Update is partial. Use clear_de_minimis_value to remove the threshold and default_duty_rate_delete_origin to remove an origin’s default rate. Sending hs_rates replaces the complete map; do not combine it with an HS-rate upsert or delete. The de minimis comparison uses imported merchandise after discounts, excluding domestic goods. Values equal to the threshold are not exempt.
Endpoints#
Get duty limits
Read the limits used by duty-rule screens and integrations.
Returns the live rule, HS-rate, search, and pagination limits enforced by the service. Read this before building create or edit forms instead of hardcoding values.
Path parameters
| Name | Type | Description |
|---|---|---|
marketId
required
|
uuid |
Market id. |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400STORE_API_INVALID_REQUEST_BODYmarketIdmust be a valid UUID. -
404MARKET_NOT_FOUNDThe market does not exist in this store.
List available duty countries
Find the market countries that can receive a duty rule.
Returns a paginated list of the market's countries, whether duties are enabled for each country, and whether a rule already exists. The readiness counts identify shippable catalog items missing weight, HS code, or country of origin.
Path parameters
| Name | Type | Description |
|---|---|---|
marketId
required
|
uuid |
Market id. |
Query parameters
| Name | Type | Description |
|---|---|---|
search
|
string |
Search by localized country name or ISO country code. |
page
|
integer |
Page number, starting at 1. |
per_page
|
integer |
Rows per page, capped by the live duty limits. |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400STORE_API_INVALID_REQUEST_BODYmarketIdmust be a valid UUID. -
404MARKET_NOT_FOUNDThe market does not exist in this store.
-
400MARKET_DUTY_SEARCH_TOO_LONGThe search value exceeds the live duty limit.
-
400VALIDATION_LIST_INVALID_PAGEPage is not an integer of at least 1.
-
400VALIDATION_LIST_INVALID_LIMITPer-page is outside the configured range.
List duty rules
List the market's country duty rules.
Returns paginated rules with their de minimis value, origin-aware default rates, HS-code rates, status, and timestamps. Use the detail endpoint before editing a rule.
Path parameters
| Name | Type | Description |
|---|---|---|
marketId
required
|
uuid |
Market id. |
Query parameters
| Name | Type | Description |
|---|---|---|
search
|
string |
Search by localized country name or ISO country code. |
page
|
integer |
Page number, starting at 1. |
per_page
|
integer |
Rows per page, capped by the live duty limits. |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400STORE_API_INVALID_REQUEST_BODYmarketIdmust be a valid UUID. -
404MARKET_NOT_FOUNDThe market does not exist in this store.
-
400MARKET_DUTY_SEARCH_TOO_LONGThe search value exceeds the live duty limit.
-
400VALIDATION_LIST_INVALID_PAGEPage is not an integer of at least 1.
-
400VALIDATION_LIST_INVALID_LIMITPer-page is outside the configured range.
Create a duty rule
Add a duty rule for one country in the market.
The country must belong to the market, have a serving currency, and not already have a rule. Create an inactive rule while configuring rates; enable it once the required catalog data is ready. Default and HS-code rates may vary by origin country; use * as the fallback origin. Duty is charged on each line's customs value: its value after discounts, without the tax its price includes. In a tax-inclusive market, a line of 120 including 20% VAT at a 12% duty rate pays 12.00 duty, not 14.40. When the market's duty_collection_mode is collect_at_checkout, import VAT is charged on the goods plus their duty: 100 with 12 duty at 20% VAT is 22.40. Duty is calculated first; the VAT on duty uses each item's own tax rates, is always added on top of the duty (never included in a price), and is part of the order's tax total, so in a tax-inclusive market the total is prices plus duty plus VAT on duty. A successful create publishes duty_rules/create with the complete saved rule.
Path parameters
| Name | Type | Description |
|---|---|---|
marketId
required
|
uuid |
Market id. |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Body parameters
| Name | Type | Description |
|---|---|---|
country_code
required
|
string |
ISO 3166-1 alpha-2 destination country assigned to this market. |
de_minimis_value
|
decimal-string|null |
Non-negative threshold for the customs value of imported merchandise (after discounts, without the tax prices include), in the currency assigned to this country. Domestic goods are excluded. Duty is not charged when that value is at or below the threshold. Precision follows the currency (zero decimals for JPY/KRW, three for KWD); maximum 99999999.9999. Send a decimal point without grouping or currency symbols. |
default_duty_rates
|
object |
Origin-country to duty-rate map. Use |
hs_rates
|
object |
Origin-country to canonical-HS-code duty-rate map. Display punctuation is accepted and normalized. |
is_enabled
required
|
boolean |
Whether this rule participates in duty calculation. |
Errors
-
400STORE_API_INVALID_REQUEST_BODYmarketIdmust be a valid UUID. -
404MARKET_NOT_FOUNDThe market does not exist in this store.
-
400MARKET_DUTY_RULE_RATE_REQUIREDAn enabled destination needs at least one rate.
-
400MARKET_DUTY_AMOUNT_INVALIDThe tariff amount is not a valid decimal.
-
400MARKET_DUTY_AMOUNT_NEGATIVEThe tariff amount is negative.
-
400MARKET_DUTY_AMOUNT_TOO_LARGEThe tariff amount exceeds 999999999999999.9999.
-
400MARKET_DUTY_AMOUNT_TOO_PRECISEThe tariff coefficient exceeds four decimal places.
-
400MARKET_DUTY_RATE_INVALIDThe rate or update mutation combination is invalid.
-
400MARKET_DUTY_RATE_TOO_PRECISEThe percentage exceeds two decimal places.
-
400MARKET_DUTY_DE_MINIMIS_INVALIDThe de minimis value is not a valid decimal.
-
400MARKET_DUTY_DE_MINIMIS_NEGATIVEThe de minimis value is negative.
-
400MARKET_DUTY_DE_MINIMIS_TOO_LARGEThe de minimis value exceeds the live maximum.
-
400MARKET_DUTY_DE_MINIMIS_TOO_PRECISEThe de minimis value has too many decimal places.
-
400MARKET_DUTY_RATE_TYPE_INVALIDA rate type is not
ad_valorem,specific, orcompound. -
400MARKET_DUTY_RATE_SHAPE_INVALIDA rate includes fields that do not belong to its selected type.
-
400MARKET_DUTY_RATE_REQUIREDAn ad valorem or compound rate is missing its percentage.
-
400MARKET_DUTY_RATE_OUT_OF_RANGEA percentage rate is outside the supported range.
-
400MARKET_DUTY_AMOUNT_REQUIREDA specific or compound rate is missing its amount.
-
400MARKET_DUTY_RATE_PER_INVALIDA specific or compound rate does not use
kgorunit. -
400MARKET_DUTY_HS_CODE_INVALID_FORMATAn HS code cannot be normalized to an even 2 to 12 digit code.
-
400MARKET_DUTY_HS_RATES_TOO_MANYThe rule exceeds the live HS-rate limit.
-
400MARKET_DUTY_ORIGIN_INVALIDAn origin is invalid, matches the destination, or duplicates another origin after normalization.
-
400MARKET_DUTY_COUNTRY_NOT_IN_MARKETThe destination country is not assigned to this market.
-
409MARKET_DUTY_RULE_ALREADY_EXISTSThis country already has a duty rule in the market.
-
400MARKET_DUTY_RULE_LIMIT_REACHEDThe market has reached its live duty-rule limit.
-
400MARKET_DUTY_COUNTRY_CURRENCY_MISSINGThe destination country has no serving currency in this market.
Get a duty rule by country
Read the complete duty rule for one destination country.
Use this endpoint when the destination country is known but the rule id is not. It returns the same complete object as the id-based detail endpoint.
Path parameters
| Name | Type | Description |
|---|---|---|
marketId
required
|
uuid |
Market id. |
countryCode
required
|
string |
ISO 3166-1 alpha-2 destination country code. |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400STORE_API_INVALID_REQUEST_BODYmarketIdmust be a valid UUID. -
404MARKET_NOT_FOUNDThe market does not exist in this store.
-
404DUTY_RULE_COUNTRY_NOT_FOUNDNo duty rule exists for this destination.
Get a duty rule
Read one duty rule and its complete rate configuration.
Use the returned rule to populate an edit form. HS codes are returned in canonical even-length 2 to 12 digit form, grouped by origin country.
Path parameters
| Name | Type | Description |
|---|---|---|
marketId
required
|
uuid |
Market id. |
ruleId
required
|
uuid |
Duty country rule id. |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400STORE_API_INVALID_REQUEST_BODYmarketIdmust be a valid UUID. -
404MARKET_NOT_FOUNDThe market does not exist in this store.
-
404DUTY_RULE_NOT_FOUNDThe duty rule does not exist in this market.
Update a duty rule
Change selected parts of one duty rule.
This is a partial update. Use explicit delete fields to remove de minimis, a default origin rate, or one HS-code rate. Sending hs_rates replaces the complete origin-to-HS map. An unchanged request publishes nothing; a successful change publishes duty_rules/update with the complete saved rule.
Path parameters
| Name | Type | Description |
|---|---|---|
marketId
required
|
uuid |
Market id. |
ruleId
required
|
uuid |
Duty country rule id. |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Body parameters
| Name | Type | Description |
|---|---|---|
de_minimis_value
|
decimal-string|null |
Set a non-negative threshold in the saved destination currency, at that currency precision and no greater than 99999999.9999. |
clear_de_minimis_value
|
boolean |
Remove the saved de minimis threshold. Omit de_minimis_value when this is true. |
default_duty_rate_upsert
|
object |
Add or replace one origin-specific default rate: |
default_duty_rate_delete_origin
|
string |
Remove the default rate for this origin code. Use |
default_duty_rates
|
object |
Replace the complete origin-rate map in one transaction. Use |
hs_rates
|
object |
Replace the complete origin-to-HS-code rate map. Do not combine this with an HS-rate upsert or delete. |
hs_rate_upsert
|
object |
Add or replace one HS rate: origin code, HS code, and rate. |
hs_rate_delete_code
|
string |
Canonical or display-form HS code to remove. |
hs_rate_delete_origin
|
string |
Origin map from which |
is_enabled
|
boolean |
Whether this rule participates in duty calculation. |
Errors
-
400STORE_API_INVALID_REQUEST_BODYmarketIdmust be a valid UUID. -
404MARKET_NOT_FOUNDThe market does not exist in this store.
-
404DUTY_RULE_NOT_FOUNDThe duty rule does not exist in this market.
-
400MARKET_DUTY_RULE_RATE_REQUIREDAn enabled destination needs at least one rate.
-
400MARKET_DUTY_AMOUNT_INVALIDThe tariff amount is not a valid decimal.
-
400MARKET_DUTY_AMOUNT_NEGATIVEThe tariff amount is negative.
-
400MARKET_DUTY_AMOUNT_TOO_LARGEThe tariff amount exceeds 999999999999999.9999.
-
400MARKET_DUTY_AMOUNT_TOO_PRECISEThe tariff coefficient exceeds four decimal places.
-
400MARKET_DUTY_RATE_INVALIDThe rate or update mutation combination is invalid.
-
400MARKET_DUTY_RATE_TOO_PRECISEThe percentage exceeds two decimal places.
-
400MARKET_DUTY_DE_MINIMIS_INVALIDThe de minimis value is not a valid decimal.
-
400MARKET_DUTY_DE_MINIMIS_NEGATIVEThe de minimis value is negative.
-
400MARKET_DUTY_DE_MINIMIS_TOO_LARGEThe de minimis value exceeds the live maximum.
-
400MARKET_DUTY_DE_MINIMIS_TOO_PRECISEThe de minimis value has too many decimal places.
-
400MARKET_DUTY_RATE_TYPE_INVALIDA rate type is not
ad_valorem,specific, orcompound. -
400MARKET_DUTY_RATE_SHAPE_INVALIDA rate includes fields that do not belong to its selected type.
-
400MARKET_DUTY_RATE_REQUIREDAn ad valorem or compound rate is missing its percentage.
-
400MARKET_DUTY_RATE_OUT_OF_RANGEA percentage rate is outside the supported range.
-
400MARKET_DUTY_AMOUNT_REQUIREDA specific or compound rate is missing its amount.
-
400MARKET_DUTY_RATE_PER_INVALIDA specific or compound rate does not use
kgorunit. -
400MARKET_DUTY_HS_CODE_INVALID_FORMATAn HS code cannot be normalized to an even 2 to 12 digit code.
-
400MARKET_DUTY_HS_RATES_TOO_MANYThe rule exceeds the live HS-rate limit.
-
400MARKET_DUTY_ORIGIN_INVALIDAn origin is invalid, matches the destination, or duplicates another origin after normalization.
Delete a duty rule
Remove a country's duty rule and every saved rate beneath it.
Future calculations stop using the rule. Existing orders retain the duty evidence saved in their pricing snapshots. A successful deletion publishes duty_rules/delete with the rule id, market id, and country code.
Path parameters
| Name | Type | Description |
|---|---|---|
marketId
required
|
uuid |
Market id. |
ruleId
required
|
uuid |
Duty country rule id. |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400STORE_API_INVALID_REQUEST_BODYmarketIdmust be a valid UUID. -
404MARKET_NOT_FOUNDThe market does not exist in this store.
-
404DUTY_RULE_NOT_FOUNDThe duty rule does not exist in this market.
Check duty health
Find catalog items checkout cannot charge duty on.
Checks every enabled duty rule in markets with duties turned on against the shippable items of active products, the same way checkout rates them. Items whose origin is the rule's destination pay no duty and are skipped. For each rule it returns counts and up to 20 example items for: missing_hs_code, missing_origin, missing_weight (only where the matching rate is charged per kg) and missing_rate (no rate for the item's origin and HS code, and no * default), plus unrated_origins, the origin countries with no matching rate and how many items each covers. currency_mismatch is true when the rule's currency differs from the serving currency of its destination country: checkout then charges no duty to that country at all. Each example's product_id, and variant_id for a variant, identify the item to fix. status is ok when a rule has nothing to fix and issues otherwise; the top-level status is issues when any rule has one. At checkout, an item that cannot be rated pays no duty and the order goes ahead; staff and API orders containing one are refused with an ORDER_DUTY_* error. The report is computed for the whole catalog and may be up to 60 seconds old; generated_at says when it was computed. Markets list responses include duty_health_available, which is false when there is nothing to check.
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Webhook events#
Duty-rule events are inserted in the same database transaction as every create, update, or delete. Payloads preserve ad valorem, specific, and compound rate shapes.
Duty rule created
Fired when a country duty rule is created in a market.
Payload fields
| Field | Type | Description |
|---|---|---|
duty_rule.id |
string |
Always present |
duty_rule.market_id |
string |
Selectable in the Payload builder |
duty_rule.country_code |
string |
Selectable in the Payload builder |
duty_rule.de_minimis_value |
string |
Selectable in the Payload builder
Exact non-negative imported-merchandise threshold after discounts, expressed at the destination currency precision. Domestic goods are excluded; equality is not exempt. |
duty_rule.de_minimis_currency |
string |
Selectable in the Payload builder
Destination currency used by the threshold and specific/compound tariff coefficients. |
duty_rule.default_duty_rates |
object |
Selectable in the Payload builder
Origin-keyed rate maps. Percentages allow two decimals; per-unit/per-kg coefficients allow four, independently of currency minor units. Calculated duties settle at currency precision with reconciled line allocations. |
duty_rule.hs_rates |
object |
Selectable in the Payload builder
Origin-keyed rate maps. Percentages allow two decimals; per-unit/per-kg coefficients allow four, independently of currency minor units. Calculated duties settle at currency precision with reconciled line allocations. |
duty_rule.is_enabled |
boolean |
Selectable in the Payload builder |
duty_rule.created_at |
string |
Selectable in the Payload builder |
duty_rule.updated_at |
string |
Selectable in the Payload builder |
Duty rule updated
Fired when a country duty rule or its HS rates change.
Payload fields
| Field | Type | Description |
|---|---|---|
duty_rule.id |
string |
Always present |
duty_rule.market_id |
string |
Selectable in the Payload builder |
duty_rule.country_code |
string |
Selectable in the Payload builder |
duty_rule.de_minimis_value |
string |
Selectable in the Payload builder
Exact non-negative imported-merchandise threshold after discounts, expressed at the destination currency precision. Domestic goods are excluded; equality is not exempt. |
duty_rule.de_minimis_currency |
string |
Selectable in the Payload builder
Destination currency used by the threshold and specific/compound tariff coefficients. |
duty_rule.default_duty_rates |
object |
Selectable in the Payload builder
Origin-keyed rate maps. Percentages allow two decimals; per-unit/per-kg coefficients allow four, independently of currency minor units. Calculated duties settle at currency precision with reconciled line allocations. |
duty_rule.hs_rates |
object |
Selectable in the Payload builder
Origin-keyed rate maps. Percentages allow two decimals; per-unit/per-kg coefficients allow four, independently of currency minor units. Calculated duties settle at currency precision with reconciled line allocations. |
duty_rule.is_enabled |
boolean |
Selectable in the Payload builder |
duty_rule.created_at |
string |
Selectable in the Payload builder |
duty_rule.updated_at |
string |
Selectable in the Payload builder |
Duty rule deleted
Fired when a country duty rule is deleted.
Payload fields
| Field | Type | Description |
|---|---|---|
duty_rule.id |
string |
Always present |
duty_rule.market_id |
string |
Selectable in the Payload builder |
duty_rule.country_code |
string |
Selectable in the Payload builder |