Declarant Docs
Playground Get an API key

Declarant API

Search and classify across 5,612 HS6 subheadings, resolve broad official tariff schedules across 12 priced destinations, and calculate duty, import VAT or GST, de minimis relief and border charges.

Base URL https://declarant.p.rapidapi.com Version 1.0.0 OpenAPI /v1/openapi.json

Overview

Classification results include the working. Each candidate code is returned with the General Rules of Interpretation that were applied, the product feature that decided the heading, a confidence figure, and the codes that ranked below it. Where a description is too vague to classify safely, the missing_information field lists the attributes that would settle it.

Landed-cost results are itemised. Duty rates, de minimis thresholds and import rules each carry the schedule they came from and the date that schedule was current. Valuation basis, tax base and every individual charge are returned separately, so a total can be checked against a broker invoice line by line.

Classification coverage and rate coverage are different. Search and classification use 5,612 HS6 subheadings from USITC 2026 Revision 12. Official ordinary/MFN schedules cover all 12 priced destinations with 125,276 destination-specific national records; 120,820 are calculable. Safe uniform rates cover 4,018 US, 4,590 UK, 4,594 EU, 4,902 Canadian and 5,173 Australian HS6 codes. An ambiguous HS6 returns 422 with national choices.
Valuation basis. The United States, Canada and Australia assess customs duty on an FOB transaction value, which excludes international freight. Most other markets assess it on CIF value, which includes freight and insurance. On a shipment where freight is 9% of value, using the wrong basis misstates the duty line by about 9%. Declarant applies the correct basis for each destination and states which one it used in valuation.duty_base_method.

Authentication

Send your RapidAPI key on every request. Subscribing to any plan, including the free tier, issues one.

X-RapidAPI-Key: your-key-here
X-RapidAPI-Host: declarant.p.rapidapi.com

GET /v1/health requires no key, so uptime monitors can reach it. Every other endpoint requires one.

Quickstart

Classify a product and price it into the United States.

cURL

curl -X POST 'https://declarant.p.rapidapi.com/v1/landed-cost' \
  -H 'X-RapidAPI-Key: YOUR_KEY' \
  -H 'X-RapidAPI-Host: declarant.p.rapidapi.com' \
  -H 'Content-Type: application/json' \
  -d '{
    "hs_code": "6109.10",
    "origin": "BD",
    "destination": "US",
    "goods_value": 4200,
    "freight": 380,
    "insurance": 45,
    "currency": "USD",
    "quantity": 600,
    "transport_mode": "ocean",
    "entry_type": "formal"
  }'

JavaScript

const res = await fetch('https://declarant.p.rapidapi.com/v1/classify', {
  method: 'POST',
  headers: {
    'X-RapidAPI-Key': process.env.RAPIDAPI_KEY,
    'X-RapidAPI-Host': 'declarant.p.rapidapi.com',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    description: "Men's crew neck t-shirt, 100% combed cotton jersey",
    destination: 'US',
    origin: 'BD',
    top_k: 3,
  }),
});

const { candidates, missing_information } = await res.json();
console.log(candidates[0].hs_code_formatted);  // 6109.10
console.log(candidates[0].confidence);         // 0.91
console.log(candidates[0].gri_applied);        // ["GRI 1", "GRI 6"]

Python

import os, requests

r = requests.post(
    "https://declarant.p.rapidapi.com/v1/classify",
    headers={
        "X-RapidAPI-Key": os.environ["RAPIDAPI_KEY"],
        "X-RapidAPI-Host": "declarant.p.rapidapi.com",
    },
    json={
        "description": "Stainless steel vacuum insulated water bottle, 750ml",
        "destination": "GB",
        "top_k": 3,
    },
    timeout=30,
)
r.raise_for_status()
top = r.json()["candidates"][0]
print(top["hs_code_formatted"], top["confidence"], top["rationale"])

Errors

Every non-2xx response uses the same envelope. Branch on error.code, which is stable. The message text may be reworded between releases.

{
  "error": {
    "code": "plan_upgrade_required",
    "message": "Batch classification is not available on the BASIC plan. Upgrade to PRO or above.",
    "upgrade_url": "https://rapidapi.com/declarant/api/declarant/pricing",
    "request_id": "0f3c1a2e-..."
  }
}
StatusCodeMeaning
400invalid_requestValidation failed. details lists the offending fields.
401unauthorizedMissing or unrecognised key.
403plan_upgrade_requiredValid request, but beyond the plan's entitlements.
404not_foundThe HS code, market or route is not in the dataset.
422calculation_requires_inputA national code or schedule-specific quantity is required to avoid guessing.
429rate_limit_exceededBurst limit hit. Honour Retry-After.
502upstream_errorThe reasoning layer was unavailable for an operation that cannot safely use lexical fallback.

Include request_id when reporting a problem. It appears in every response body and in the X-Request-Id header.

Plans and limits

RapidAPI meters the monthly allowance. Each plan also carries a short-window burst limit, which caps how fast a single client can call the service.

PlanRequests / monthBurst / 10sBatch sizeCandidates
Basic — free10053
Pro2,50030255
Ultra15,000801008
Mega100,00020025010

GET /v1/me returns the entitlements the gateway resolved for your key.


POST /v1/classify

Ranks candidates from the 5,612-subheading HS6 nomenclature against a product description and explains each result.

Request

FieldTypeNotes
description requiredstringWhat the product is. Material, construction and function determine the heading.
materialstringFibre or material composition. For textiles and footwear this often decides the rate on its own.
intended_usestringWhat the article is for. Two physically similar goods can sit in different chapters on this basis.
origin, destinationstringISO 3166-1 alpha-2.
top_kinteger1–10, capped by plan. Default 3.

Response

{
  "candidates": [
    {
      "hs_code": "610910",
      "hs_code_formatted": "6109.10",
      "description": "T-shirts, singlets and other vests, of cotton, knitted or crocheted",
      "chapter": "61",
      "heading": "6109",
      "confidence": 0.91,
      "rationale": "Knitted construction and cotton fibre content place the article in
                    heading 6109; the cotton subheading follows at GRI 6.",
      "gri_applied": ["GRI 1", "GRI 6"],
      "statistical_unit": "doz."
    }
  ],
  "method": "ai_assisted",
  "missing_information": [],
  "shortlist_size": 18,
  "cached": false,
  "data_as_of": "2026-07-21"
}
Check method before relying on a result. ai_assisted means the reasoning layer ran. lexical means it was unavailable and results were ranked on text match alone. Confidence figures on that path are capped and should be read as weak signals rather than classifications.

POST /v1/batch/classify

Classifies up to 250 products in one call. Available on Pro and above. A failure on one item does not fail the batch: each result carries its own status of ok, no_match or error, and the response ends with a summary count.

{
  "items": [
    { "id": "SKU-1001", "description": "Stainless steel vacuum insulated water bottle, 750ml" },
    { "id": "SKU-1002", "description": "Bluetooth over-ear headphones with active noise cancelling" }
  ],
  "destination": "GB",
  "top_k": 1
}

POST /v1/landed-cost

Calculates the cost of importing a consignment into a destination market. Supply hs_code if you know it. Supply description instead and the goods are classified first, in which case the response includes that classification and flags that the code was inferred rather than given. Description-only pricing requires AI-assisted classification; if the reasoning layer is unavailable, this route returns 502 instead of converting a weak lexical match into a duty estimate.

FieldTypeNotes
hs_code / descriptionstringOne of the two is required.
origin, destination requiredstringISO 3166-1 alpha-2.
goods_value requirednumberCommercial value excluding freight and insurance.
currencystringISO 4217. Default USD.
freight, insurancenumberDefault 0. Affects the duty base in CIF markets.
quantityintegerDrives per_unit_landed_cost.
weight_kg, volume_litersnumberUsed for national formulas stated per kilogram or liter.
customs_quantity, customs_quantity_unitnumber, stringSupply together for a schedule-specific measure. The unit must exactly match /v1/national-lines.
transport_modeenumair, ocean, road, rail, courier. Some fees are ocean-only.
entry_typeenumformal or informal. Formal entries attract processing fees.
claim_preferencebooleanSee below. Default false.
claim_preference defaults to false. A preferential rate under an agreement such as USMCA is only usable if the goods satisfy the product-specific rule of origin and the importer holds a valid certificate at the time of entry. Most shipments move without one, so defaulting to the preferential rate would understate their cost. Set it to true once you hold the certificate. Either way the response names the programme, the certificate requirement, and what claiming it would save.

Response shape

The response is grouped so each figure can be checked on its own:

  • valuation — goods, freight, insurance, CIF, and the duty and tax bases with the method used to derive each.
  • duty — rate, amount, programme, whether de minimis relieved it, and any additional duties that stack on top.
  • fees — each country-specific fee as its own line, with the rate, floor and ceiling that produced it.
  • excluded_fees — fees that are charged on the entry but are denominated in another currency, and so are absent from totals. Normally empty; see the note below.
  • tax — import VAT or GST, its base, and whether relief applied.
  • de_minimis — the thresholds, the assessed value, and any FX rate used to compare across currencies.
  • provenance — the source schedule and as-of date for every input.
  • notes — conditions that materially affect the figures returned.
Price in the destination's currency to get its fees. Processing fees carry floors and ceilings set in the destination's own currency — the US Merchandise Processing Fee, for example, runs between $33.58 and $651.50. Converting those bounds would invent precision customs will not apply, so a request priced in another currency returns the fee under excluded_fees instead of estimating it, and totals excludes it. Quote US entries in USD and Australian entries in AUD for a complete total.

GET /v1/hs/{code}

Accepts 2, 4, 6, 8 or 10 digits, with or without separators. National 8/10-digit inputs resolve to their internationally harmonised HS6 parent. Returns the HS node, its hierarchy, children, and any safe standard rates loaded for that subheading.

GET /v1/hs/6109.10
GET /v1/hs/851762
GET /v1/hs/64

GET /v1/duty

Resolves the rate for an origin and destination pair. A rate specific to the origin country, which is how free-trade agreements and preference schemes are held, takes precedence over the standard rate. Additional duties charged on top are returned as separate figures rather than folded into one number.

GET /v1/duty?hs=64041190&origin=VN&destination=US

GET /v1/national-lines

Lists jurisdiction-specific legal tariff lines below HS6, their raw statutory formulas, and whether each formula is directly calculable. Use this endpoint when /v1/duty or /v1/landed-cost asks for a national code.

GET /v1/national-lines?hs=640411&destination=US&limit=25

GET /v1/countries

Returns 20 import-rule profiles. Each item includes landed_cost_supported and duty_rate_subheadings, so clients can distinguish the 12 destinations with loaded rates from reference-only profiles.


Data and provenance

Duty rates come from the published national schedules: the USITC Harmonized Tariff Schedule, EU TARIC, the UK Global Tariff, the Canada Customs Tariff and the Australian Customs Tariff. Import rules, meaning consumption tax rates and bases, de minimis thresholds and processing fees, come from the corresponding revenue and border authorities.

Every rate row and country record carries an as_of date and a source string. Both appear on any response that depends on them.

The classification index contains 5,612 HS6 subheadings and 1,228 headings from the official USITC 2026 Revision 12 export, released 21 July 2026. The US, UK, EU, Canadian and Australian source schedules contain 56,739 unique tariff lines, represented as 125,276 destination-specific records across all 12 priced markets. Of those records, 120,820 are directly calculable and 4,456 conditional or non-linear records remain reference-only. Import-rule profiles cover 20 destinations.

Exchange rates are indicative. They are used for one purpose: comparing a shipment value against a de minimis threshold set in another currency. Where that happens, the response says so and returns the rate applied. Customs will use its own published rate for the entry date. Declarant does not provide FX quotes.

Caching

Classification results are cached for 30 days against a hash of the product facts, brand, origin, destination and requested candidate count. A cache hit returns X-Declarant-Cache: HIT and "cached": true.

Only ai_assisted results are cached. A lexical result is a degraded answer and is never held.

Scope and limitations

Declarant produces estimates for commercial planning: pricing, margin modelling, duty display at checkout, and catalogue pre-classification. It is not a customs broker, and its output is not customs, legal or tax advice. What is actually owed is determined by the customs authority of the importing country, on the goods presented and the schedule in force on the date of entry.

What the service does not cover:

  • Compound and specific rates. A small number of subheadings, including certain watches and spirits, carry a per-unit component alongside the percentage rate. Where the stored figure approximates one, the subheading's classification_note says so.
  • Antidumping and countervailing duties. Not covered. These are specific to a case and an exporter, and can be many times the ordinary rate.
  • Subnational tax. US state and local sales tax, Canadian PST, QST and HST, and equivalents elsewhere. These sit outside the customs entry.
  • Temporary and trade-remedy tariffs. Section 232, Section 301, antidumping, countervailing and other country- or exporter-specific additional duties are not loaded. The response carries a duty.surcharges field for future data, but it is not a signal that those measures were checked.
  • Rules of origin. Declarant does not verify origin. claim_preference is taken as an assertion by the caller.