border.bot
Docs menu

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 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/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}]}'