border.bot
Docs menu

API reference

Calculate duties, taxes and landed cost

POST https://api.border.bot/v1/calculate

Requires an API key (Authorization: Bearer bb_live_…).

Duties, taxes, fees and the landed cost for one HS code / origin / destination (the destinations GET /countries marks landedCost). Costs 1 credit. Unsupported destinations return 422 unsupported_country without charging.

API key scope: calculate.

Headers#

Name Type Required Description
idempotency-key string no Make retries safe: a repeat with the same key returns the original result without charging again (keys are scoped to your workspace).

Request body (JSON)#

Name Type Required Description
destinationCountry string yes Destination: one GET /countries marks landedCost. ISO 3166-1 alpha-2, case-insensitive.
currency string no ISO 4217 currency of value, shippingCost and insuranceCost.
shippingCost number no Shipping cost (affects CIF-based duty/VAT bases).
insuranceCost number no Insurance cost.
transportMode "air" | "sea" | "road" | "rail" no Transport mode (fees such as HMF apply to sea freight).
shippingTerms "EXW" | "FCA" | "FAS" | "FOB" | "CFR" | "CIF" | "CPT" | "CIP" | "DAP" | "DPU" | "DDP" no Incoterm of the price (Incoterms 2020). Under C and D terms (CFR, CIF, CPT, CIP, DAP, DPU, DDP) the price already carries the goods to the destination, so shippingCost isn’t added to the customs value again.
shipmentChannel "courier" | "postal" no How the parcel travels: courier (express carriers, default) or postal — affects de minimis and channel-specific regimes.
entryDate string no Calculate with the rates in force on this date (YYYY-MM-DD). Default: today.
tradeAgreement string no Ignored. Preferential rates are applied automatically from the origin and destination; the agreement used is returned as tradeAgreement.
region string no State, province or territory, where import taxes differ inside the country. Canada needs one (ON, QC, BC…).
purpose "sale" | "gift" | "sample" | "return" no Why the goods are sent: some thresholds differ for gifts, samples and returns. Default: sale.
businessBuyer boolean no The buyer is a business: some taxes are reverse-charged or apply differently.
sellerRegistrations string[] no Tax schemes the seller is registered for (EU_IOSS, GB_VAT, AU_GST, NZ_GST, NO_VOEC…). Taxes the seller collects at checkout are returned with collectedBy: "seller".
preference string no best (default): the lowest preferential rate the origin qualifies for. none: the general rate only. Or a programme code (S for USMCA into the US). Every option is returned in options.
claims string[] no Exemption, relief and quota codes being claimed (US Chapter 99 exclusions such as 9903.88.69; an end-use authorisation such as TARIC document N990; a tariff quota order number such as 050331). Codes you could claim are returned in claims.available.
enforceValidation boolean no Refuse a shipment that matches one of the destination’s reject validation rules (400 invalid_input, details.reason: "validation_failed", refunded) instead of reporting it in validation.
hsCode string yes HS/HTS code (4–10 digits; dots and spaces are ignored).
originCountry string yes Country of origin — drives preferential rates and additional duties (e.g. Section 301). ISO 3166-1 alpha-2, case-insensitive.
value number yes Total customs value of the goods in the shipment (unit price × quantity), in currency, excluding shipping.
quantity integer no Number of units.
weight number no Shipment weight (needed for weight-based duties). Requires weightUnit.
weightUnit "kg" | "lb" no Unit of weight.
volumeLiters number no Volume of the goods in litres, for duties charged per litre (wine, spirits, fuel).
alcoholPercent number no Alcohol by volume (%), for duties charged per litre of pure alcohol.
components object[] no Metal content by value (line totals in currency), for duties charged on it: US Section 232 steel, aluminum and copper derivatives. Without it, those duties come back as regulatory (conditional).
metalWeightPercent number no Share of the product’s weight that is metal (0–100), for content-based exemptions.
conditions string[] no Rate conditions the goods meet, when the destination reserves a rate for them: a harmonised kind (pharmaceutical, end_use, certificate, company, quality, route) or the publisher’s own code (EU TARIC additional code 2500). Without it the default rate is charged (the unconditional one, or the highest when every rate has a condition); the rates you could claim are returned in options with their condition. The importer must hold what justifies a claimed condition.

Responses#

  • 200: The landed-cost breakdown and the credits charged. (CalculateResponse)
  • 400: Invalid input (invalid_input). (Error)
  • 401: Missing, invalid, revoked or expired API key (unauthorized). (Error)
  • 402: Not enough credits (insufficient_credits). Nothing was charged. (Error)
  • 403: Workspace suspended, action disabled, or the key lacks the scope (org_suspended, action_disabled, forbidden). (Error)
  • 409: A request with this Idempotency-Key is still in progress (conflict). (Error)
  • 422: Destination not supported (unsupported_country). (Error)
  • 429: Rate limited (rate_limited). Retry after Retry-After seconds; RateLimit says which limit was hit (r=0, t seconds until its window ends) and RateLimit-Policy its quota. (Error)
  • 500: Unexpected error (internal). (Error)
  • 502: The engine failed (upstream_error). The credits are refunded automatically. (Error)
  • 504: The engine timed out (upstream_timeout). The credits are refunded automatically. (Error)

Example#

bash
curl -X POST 'https://api.border.bot/v1/calculate' \
  -H 'Authorization: Bearer bb_live_...' \
  -H 'Content-Type: application/json' \
  -d '{"hsCode":"6109.10.00.12","originCountry":"CN","destinationCountry":"US","value":120,"currency":"USD","shippingCost":15}'