API Documentation
Complete guide to integrating with the Duties & Tariffs API V.1.0.2 View changelog
Getting Started
The API provides programmatic access to comprehensive HTS (Harmonized Tariff Schedule) data through our Resolve Tariff endpoint - the primary endpoint for getting complete tariff information including base duty rates, additional measures (Section 301, 232, IEEPA), and country-specific applied rates. Also includes access to curated trade news. This RESTful API uses standard HTTP response codes and returns JSON-encoded responses.
https://tariffsapi.com/api/v1
/api/v1/tariffs/resolve with hts and origin parameters to get complete tariff information.
Set resolve_chapter_99=true to resolve reference-only measures to numeric rates.
Prerequisites
- An active premium subscription
- A valid API key (generate one from your API Keys page)
- Basic knowledge of RESTful APIs and HTTP requests
Authentication
All API requests must be authenticated using your API key. We support two authentication methods:
Method 1: Bearer Token (Recommended)
Include your API key in the Authorization header:
curl "https://tariffsapi.com/api/v1/tariffs/resolve?hts=8541.10.00.80&origin=CN" \
-H "Authorization: Bearer YOUR_API_KEY"
Method 2: X-API-Key Header
Alternatively, use the X-API-Key header:
curl "https://tariffsapi.com/api/v1/tariffs/resolve?hts=8541.10.00.80&origin=CN" \
-H "X-API-Key: YOUR_API_KEY"
Rate Limits
To ensure fair usage and system stability, API requests are rate-limited per API key:
| Plan | Requests per Minute | Requests per Day |
|---|---|---|
| Premium | 60 | 1,000 |
Rate Limit Headers
Every API response includes these headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1640995200
Tariff Resolution API
Resolve complete tariff information including base duty rates (HTS Column 1 General, Special, and Column 2) and additional measures (Section 301, 232, IEEPA) for any HTS code and country of origin.
/api/v1/tariffs/resolve
Main Endpoint
Primary consumer-facing endpoint. Given an HTS code and country of origin, returns the complete tariff picture: base duty (general or special via trade agreements) plus applicable additional measures (Section 301, 232, IEEPA). Uses HTS inheritance when needed. Returns a transparent breakdown—never silently sums rates. Use resolve_chapter_99=true to resolve reference-only measures (e.g. “See 9903.91.05”) to numeric rates by looking up the Chapter 99 HTS line in our database; rates are never invented.
Query Parameters
| Parameter | Required | Description |
|---|---|---|
hts |
Yes | HTS number (any length; inheritance applies) |
origin |
Yes | ISO-2 country code (e.g., CN, MX, CA). Required to resolve additional duties. |
as_of |
Optional | Date (YYYY-MM-DD) for resolution (default: today) |
include_unknown_effective_dates |
Optional | Include measures with unknown effective dates (default: true — current unless proven otherwise). Set false to exclude. |
resolve_chapter_99 |
Optional | When true, resolve reference-only measures (e.g. "See 9903.91.05") to numeric rates by looking up the Chapter 99 HTS line in our database (default: false). Use true when the origin is subject to additional duties (e.g. China CN for Section 301) to get resolved_additional_ad_valorem_rate and total_resolved_ad_valorem_rate in the summary. Accepts true or 1. Unresolved states are returned explicitly; we never invent rates. |
Example Request
const axios = require('axios');
// For origins where additional duties apply (e.g. CN), use resolve_chapter_99: true to get numeric rates
const response = await axios.get('https://tariffsapi.com/api/v1/tariffs/resolve', {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
params: {
hts: '8541.10.00.80',
origin: 'CN',
as_of: '2026-02-05',
include_unknown_effective_dates: true,
resolve_chapter_99: true
}
});
console.log(response.data);
import requests
# For origins where additional duties apply (e.g. CN), use resolve_chapter_99=True to get numeric rates
response = requests.get(
'https://tariffsapi.com/api/v1/tariffs/resolve',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
params={
'hts': '8541.10.00.80',
'origin': 'CN',
'as_of': '2026-02-05',
'include_unknown_effective_dates': True,
'resolve_chapter_99': True
}
)
print(response.json())
require 'net/http'
require 'json'
# For origins where additional duties apply (e.g. CN), use resolve_chapter_99: true to get numeric rates
params = {
hts: '8541.10.00.80',
origin: 'CN',
as_of: '2026-02-05',
include_unknown_effective_dates: true,
resolve_chapter_99: true
}
query = URI.encode_www_form(params)
uri = URI("https://tariffsapi.com/api/v1/tariffs/resolve?#{query}")
request = Net::HTTP::Get.new(uri)
request['Authorization'] = 'Bearer YOUR_API_KEY'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
puts JSON.parse(response.body)
Example Response
With resolve_chapter_99=true and origin CN, reference measures (e.g. "See 9903.91.05") are resolved to numeric rates when the Chapter 99 line exists in our database:
{
"resolution": {
"requested_hts": "8541.10.00.80",
"resolved_hts": "8541.10.00",
"origin": "CN",
"as_of": "2026-02-05",
"include_unknown_effective_dates": true,
"resolve_chapter_99": true
},
"base_tariff": {
"type": "general",
"rate_type": "ad_valorem",
"percentage_component": 0.0,
"per_unit_component": null,
"agreement": null
},
"additional_measures": [
{
"program": "section_301",
"rate_type": "reference",
"details": "See 9903.91.05",
"chapter_99_code": "9903.91.05",
"effective_date_unknown": true,
"uncertain": true,
"resolved_rate": {
"rate_type": "ad_valorem",
"percentage_component": 0.25,
"source": "chapter_99",
"chapter_99_hts": "9903.91.05"
},
"chapter_99_resolution": {
"status": "resolved",
"resolved_hts": "9903.91.05",
"product_id": 12345
}
}
],
"summary": {
"applicable_ad_valorem_rate": 0.0,
"resolved_additional_ad_valorem_rate": 25.0,
"total_resolved_ad_valorem_rate": 25.0,
"notes": [
"Base duty is 0%",
"Section 301: See 9903.91.05 for details"
]
},
"notice": "This duty and tariff resolution is advisory only and not legally binding. Always verify with official sources."
}
When resolve_chapter_99=true, reference measures may include resolved_rate (numeric rate from the Chapter 99 line) and chapter_99_resolution (status: resolved, not_found, no_numeric_rate, or multiple_rates). The summary may also include resolved_additional_ad_valorem_rate and total_resolved_ad_valorem_rate.
Missing hts or origin returns 422. Unknown HTS returns 404. Results are advisory only.
/api/v1/tariffs/resolve_batch
New
High Performance
Efficient bulk resolution. Resolve up to 200 HTS codes in a single API call with automatic deduplication and bulk data loading. 10-50x faster than individual requests. Perfect for bulk imports, rate analysis, and high-volume applications.
Request Body Parameters
| Parameter | Required | Description |
|---|---|---|
requests |
Yes | Array of request objects (max 200 items) |
requests[].hts |
Yes | HTS number for this item |
requests[].origin |
Yes | ISO-2 country code for this item |
requests[].as_of |
Optional | Date override for this specific item (YYYY-MM-DD) |
as_of |
Optional | Default date for all items (default: today) |
include_unknown_effective_dates |
Optional | Include measures with unknown dates (default: true) |
resolve_chapter_99 |
Optional | Resolve Chapter 99 references to numeric rates (default: false) |
Example Request
const axios = require('axios');
const response = await axios.post(
'https://tariffsapi.com/api/v1/tariffs/resolve_batch',
{
requests: [
{ hts: '8541.10.0080', origin: 'CN' },
{ hts: '7208.10.15', origin: 'CA' },
{ hts: '8703.23.00', origin: 'MX', as_of: '2025-01-15' }
],
as_of: '2026-02-13',
include_unknown_effective_dates: true,
resolve_chapter_99: false
},
{
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}
);
console.log(`Processed ${response.data.meta.count} items in ${response.data.meta.ms_total}ms`);
console.log(response.data.results);
import requests
response = requests.post(
'https://tariffsapi.com/api/v1/tariffs/resolve_batch',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
json={
'requests': [
{'hts': '8541.10.0080', 'origin': 'CN'},
{'hts': '7208.10.15', 'origin': 'CA'},
{'hts': '8703.23.00', 'origin': 'MX', 'as_of': '2025-01-15'}
],
'as_of': '2026-02-13',
'include_unknown_effective_dates': True,
'resolve_chapter_99': False
}
)
batch = response.json()
print(f"Processed {batch['meta']['count']} items in {batch['meta']['ms_total']}ms")
for result in batch['results']:
if result['ok']:
print(f"✓ {result['data']['resolution']['resolved_hts']}")
else:
print(f"✗ {result['error']['message']}")
require 'net/http'
require 'json'
uri = URI('https://tariffsapi.com/api/v1/tariffs/resolve_batch')
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request['Authorization'] = 'Bearer YOUR_API_KEY'
request.body = {
requests: [
{ hts: '8541.10.0080', origin: 'CN' },
{ hts: '7208.10.15', origin: 'CA' },
{ hts: '8703.23.00', origin: 'MX', as_of: '2025-01-15' }
],
as_of: '2026-02-13',
include_unknown_effective_dates: true,
resolve_chapter_99: false
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
batch = JSON.parse(response.body)
puts "Processed #{batch['meta']['count']} items in #{batch['meta']['ms_total']}ms"
batch['results'].each do |result|
if result['ok']
puts "✓ #{result['data']['resolution']['resolved_hts']}"
else
puts "✗ #{result['error']['message']}"
end
end
curl -X POST https://tariffsapi.com/api/v1/tariffs/resolve_batch \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"requests": [
{ "hts": "8541.10.0080", "origin": "CN" },
{ "hts": "7208.10.15", "origin": "CA" },
{ "hts": "8703.23.00", "origin": "MX", "as_of": "2025-01-15" }
],
"as_of": "2026-02-13",
"include_unknown_effective_dates": true,
"resolve_chapter_99": false
}'
Example Response
{
"meta": {
"count": 3,
"unique": 3,
"ms_total": 45.23
},
"results": [
{
"index": 0,
"ok": true,
"data": {
"resolution": {
"requested_hts": "8541.10.0080",
"resolved_hts": "8541.10.00.80",
"origin": "CN",
"as_of": "2026-02-13"
},
"base_tariff": { ... },
"additional_measures": [ ... ],
"summary": {
"applicable_ad_valorem_rate": 25.0,
"notes": ["Base: 0.0% (general) + Additional: 25.0% (section_301)"]
}
}
},
{
"index": 1,
"ok": true,
"data": { ... }
},
{
"index": 2,
"ok": false,
"error": {
"code": "not_found",
"message": "HTS code not found: 8703.23.00"
}
}
]
}
- Automatic deduplication - Identical requests (same HTS+origin+date) resolved once
- Per-item errors - Some items can fail without breaking the batch
- Cache integration - Results cached for 24 hours, same as single endpoint
- High throughput - Process 150 requests in ~50ms (4,500+ req/s)
- Same logic - Identical results to single
/resolveendpoint
Common Use Cases
Bulk Import Analysis
Analyze tariffs for entire product catalog in seconds
Multiple Origins
Compare duties for same HTS from different countries
Historical Analysis
Track rate changes over time with per-item dates
Quote Generation
Generate accurate duty calculations for multiple line items
Performance Benchmarks
| Batch Size | Typical Time | vs Individual Requests |
|---|---|---|
| 10 items | 50-150ms | 10-20x faster |
| 50 items | 200-400ms | 20-30x faster |
| 100 items | 400-800ms | 20-40x faster |
| 200 items | 800-1500ms | 25-50x faster |
Each result includes an index field matching the original request array position and an ok boolean indicating success.
Failed items include an error object with code and message fields.
/api/v1/tariffs/by_hts/:hts_number
Get base duties and additional measures for a single HTS data point. Automatically inherits from parent HTS if no duties found for exact match. Returns detailed duty information including all rate types.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
origin |
string | ISO country code for filtering additional duties |
as_of |
date | Date for filtering effective additional duties (default: today) |
include_unknown_effective_dates |
boolean | Include additional duties with unknown effective dates (default: true — current unless proven otherwise). Set false to exclude. |
Example Request
const axios = require('axios');
const htsNumber = '8448.51.10.00';
const response = await axios.get(
`https://tariffsapi.com/api/v1/tariffs/by_hts/${htsNumber}`,
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
},
params: {
origin: 'CN',
include_unknown_effective_dates: true
}
}
);
console.log(response.data);
import requests
hts_number = '8448.51.10.00'
response = requests.get(
f'https://tariffsapi.com/api/v1/tariffs/by_hts/{hts_number}',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
params={
'origin': 'CN',
'include_unknown_effective_dates': True
}
)
print(response.json())
require 'net/http'
require 'json'
hts_number = '8448.51.10.00'
params = {
origin: 'CN',
include_unknown_effective_dates: true
}
query_string = URI.encode_www_form(params)
uri = URI("https://tariffsapi.com/api/v1/tariffs/by_hts/#{hts_number}?#{query_string}")
request = Net::HTTP::Get.new(uri)
request['Authorization'] = 'Bearer YOUR_API_KEY'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts JSON.parse(response.body)
Note: The response includes detailed information about base duties, additional measures, and provides full transparency about data sources and inference confidence levels.
Error Handling
The API uses standard HTTP response codes and returns detailed error messages in JSON format.
| Status Code | Description |
|---|---|
| 200 | Success - Request completed successfully |
| 400 | Bad Request - Invalid parameters |
| 401 | Unauthorized - Invalid or missing API key |
| 404 | Not Found - Resource doesn't exist |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Server Error - Something went wrong on our end |
Error Response Format
{
"error": {
"code": "unauthorized",
"message": "Invalid API key provided",
"details": "The API key is either missing, invalid, or has been revoked"
}
}
Code Examples
JavaScript (Node.js)
const axios = require('axios');
const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://tariffsapi.com/api/v1';
async function resolveTariff() {
try {
const response = await axios.get(`${BASE_URL}/tariffs/resolve`, {
headers: {
'Authorization': `Bearer ${API_KEY}`
},
params: {
hts: '8541.10.00.80',
origin: 'CN',
resolve_chapter_99: true
}
});
console.log(response.data);
} catch (error) {
console.error('Error:', error.response.data);
}
}
resolveTariff();
Python
import requests
API_KEY = 'YOUR_API_KEY'
BASE_URL = 'https://tariffsapi.com/api/v1'
headers = {
'Authorization': f'Bearer {API_KEY}'
}
def resolve_tariff():
response = requests.get(
f'{BASE_URL}/tariffs/resolve',
headers=headers,
params={
'hts': '8541.10.00.80',
'origin': 'CN',
'resolve_chapter_99': True
}
)
if response.status_code == 200:
data = response.json()
print(data)
else:
print(f'Error: {response.status_code}')
print(response.json())
resolve_tariff()
Ruby
require 'net/http'
require 'json'
API_KEY = 'YOUR_API_KEY'
BASE_URL = 'https://tariffsapi.com/api/v1'
params = {
hts: '8541.10.00.80',
origin: 'CN',
resolve_chapter_99: true
}
query = URI.encode_www_form(params)
uri = URI("#{BASE_URL}/tariffs/resolve?#{query}")
request = Net::HTTP::Get.new(uri)
request['Authorization'] = "Bearer #{API_KEY}"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
if response.code == '200'
data = JSON.parse(response.body)
puts data
else
puts "Error: #{response.code}"
puts response.body
end
PHP
<?php
$apiKey = 'YOUR_API_KEY';
$baseUrl = 'https://tariffsapi.com/api/v1';
$params = http_build_query([
'hts' => '8541.10.00.80',
'origin' => 'CN',
'resolve_chapter_99' => true
]);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $baseUrl . '/tariffs/resolve?' . $params);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $apiKey
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
$data = json_decode($response, true);
print_r($data);
} else {
echo "Error: $httpCode\n";
echo $response;
}
?>
Support
Need help with the API? We're here to assist you.
Documentation
This page contains comprehensive documentation for all API endpoints.
Email Support
Contact us at support@tariffsapi.com
Tariffs API