Docs menu
Get started
API reference
Classification
Landed cost
Products
Compliance
Reference
Origin
API reference
Calculate a whole shipment
POST https://api.border.bot/v1/calculate/shipment
Requires an API key (Authorization: Bearer bb_live_…).
Duties, taxes, fees and the landed cost of a cart or order to one destination: up to 50 lines, freight and insurance shared out by value, one de minimis check, and per-entry fees charged once. Costs 1 credit per line. Priced on border.bot’s own data: a destination it doesn’t cover yet returns 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. |
items |
object[] | yes | The shipment’s lines (up to 50), each with its code, origin and line value. Freight and insurance are shared out by value. |
Responses#
200: The shipment’s landed cost, line by line, and the credits charged. (CalculateShipmentResponse)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 covered by border.bot’s own data (unsupported_country). (Error)429: Rate limited (rate_limited). Retry afterRetry-Afterseconds;RateLimitsays which limit was hit (r=0,tseconds until its window ends) andRateLimit-Policyits 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#
curl -X POST 'https://api.border.bot/v1/calculate/shipment' \
-H 'Authorization: Bearer bb_live_...' \
-H 'Content-Type: application/json' \
-d '{"destinationCountry":"GB","currency":"USD","shippingCost":12,"items":[{"hsCode":"6109.10","originCountry":"CN","value":60,"quantity":3},{"hsCode":"6204.62","originCountry":"BD","value":45}]}'