Python SDK for the Neo Tariff API
Project description
neo-tariff
Python SDK for the Neo Tariff API — US tariff duty calculation, HTS code search, and trade data.
Installation
pip install neo-tariff
Or install a specific pre-release:
pip install neo-tariff --pre
Quick start
from neo_tariff import NeoTariff
client = NeoTariff(api_key="ntf_...")
result = client.rates.evaluate_entry(
hts_code="7208.10.15",
country_of_origin="CN",
cost=10_000,
qty=1_000,
)
data = result.data # CalcResponse (typed Pydantic model)
if data.summary:
net = data.summary.duty_totals.get("net")
if net:
print(f"Total duty: ${net.total:,.2f}")
Authentication
Pass your API key directly or set the NEO_TARIFF_API_KEY environment variable:
import os
from neo_tariff import NeoTariff
# Explicit
client = NeoTariff(api_key="ntf_...")
# From environment
client = NeoTariff(api_key=os.environ["NEO_TARIFF_API_KEY"])
Resources
Rates — Tariff duty calculation
# Single entry
result = client.rates.evaluate_entry(
hts_code="7208.10.15",
country_of_origin="CN",
cost=10_000,
qty=1_000,
reciprocal=True, # Include Ch.99 reciprocal tariffs
)
# result.data → CalcResponse
# Batch (up to 1000 entries)
result = client.rates.evaluate_entries(
data=[
{"hts_code": "7208.10.15", "country_of_origin": "CN", "cost": 10000, "qty": 1000},
{"hts_code": "8471.30.01", "country_of_origin": "JP", "cost": 5000, "qty": 100},
]
)
# result.data → list[CalcResponse]
# Multi-country comparison for one HTS code
result = client.rates.evaluate_multicountry(
hts_code="7208.10.15",
countries=["CN", "DE", "JP"],
cost=10_000,
qty=1_000,
)
# result.data → list[CalcResponse]
Search — HTS code lookup
# Search by description
result = client.search.hts(query="steel plates", limit=10)
# result.data → list[APIRespSearchHtsItem]
for item in result.require_data():
print(f"{item.hts_code}: {item.description}")
# Autocomplete by code prefix
result = client.search.autocomplete_hts(prefix="7208", limit=5)
# result.data → list[APIRespAutocompleteHtsItem]
# Natural language description search
result = client.search.hts_by_description(query="cold rolled steel sheets")
# result.data → list[APIRespAutocompleteHtsItem]
# Full-text document search (sections, chapters, codes, notes)
result = client.search.hts_docs(query="steel", limit=10)
# result.data → dict (untyped — complex nested structure)
Context — HTS structure and country data
# HTS code context with rates
result = client.context.get_hts_code("7208.10.15")
# result.data → APIRespDataHtsCodeHub
# Detailed code info
result = client.context.get_hts_details("7208100000")
# result.data → APIRespDataHtsCodeContext
print(result.data.description, result.data.indent_level)
# List HTS sections
result = client.context.list_sections()
# List chapters in a section
result = client.context.list_chapters_by_section("1")
# Country lookup
result = client.context.get_country("CN")
# result.data → CountryRecord
print(result.data.country_name, result.data.programs)
# All countries
result = client.context.list_countries()
# result.data → list[CountryRecord]
Compare — Version and country diffs
# Compare tariff across countries
result = client.compare.tariff(
hts_code="7208.10.15",
countries=["CN", "DE"],
cost=10_000,
qty=1_000,
)
# result.data → dict[str, CalcResponse]
# Compare HTS rates between versions
result = client.compare.hts_rates(
"7208.10.15",
year_a=2025, version_a=15,
year_b=2025, version_b=25,
)
# result.data → CompareRatesResponse
# Compare two source versions
result = client.compare.sources(
year_a=2025, version_a=15,
year_b=2025, version_b=25,
)
# result.data → CompareSourcesResponse
Versions — Available HTS revisions
result = client.versions.list()
# result.data → list[HtsSourceVersion]
for v in result.require_data():
print(f"Year {v.year} v{v.version} {'(active)' if v.is_active else ''}")
Async usage
Every resource method has an async counterpart:
from neo_tariff import AsyncNeoTariff
async def main():
async with AsyncNeoTariff(api_key="ntf_...") as client:
result = await client.rates.evaluate_entry(
hts_code="7208.10.15",
country_of_origin="CN",
cost=10_000,
qty=1_000,
)
print(result.data.totals)
Response envelope
All methods return APIResponse[T]:
result = client.versions.list()
result.success # bool
result.data # T (the typed payload)
result.meta # APIMeta | None (timestamp, operation, hts_year, etc.)
result.errors # list[APIRespError] | None
# Convenience: raises NeoTariffError if data is None
data = result.require_data()
Raw response access
For debugging or when you need the raw HTTP response:
raw = client.with_raw_response.versions.list()
raw.http_response.status_code # 200
raw.parsed # APIResponse or None
Error handling
from neo_tariff import (
NeoTariffError, # Base for all SDK errors
NeoTariffHTTPError, # Non-2xx HTTP response
AuthenticationError, # 401/403
NotFoundError, # 404
ValidationError, # 422
RateLimitError, # 429
ServerError, # 500+
NeoTariffAPIError, # 2xx but success=False
NeoTariffConnectionError, # Network/timeout errors
)
try:
result = client.rates.evaluate_entry(...)
except AuthenticationError:
print("Check your API key")
except RateLimitError:
print("Slow down!")
except NeoTariffHTTPError as e:
print(f"HTTP {e.status_code}: {e.message}")
except NeoTariffAPIError as e:
print(f"API error: {e.errors}")
except NeoTariffConnectionError:
print("Network issue")
Retry logic
The SDK automatically retries transient failures (408, 429, 500, 502, 503, 504 and network errors) with exponential backoff:
client = NeoTariff(api_key="ntf_...", max_retries=2) # Default: 2 retries
client = NeoTariff(api_key="ntf_...", max_retries=0) # Disable retries
client = NeoTariff(api_key="ntf_...", max_retries=5) # More retries for batch jobs
Configuration
client = NeoTariff(
api_key="ntf_...",
base_url="https://tariff-data.enterprise-neo.com", # Default
timeout=30.0, # Request timeout in seconds
max_retries=2, # Retry count for transient failures
)
Typed response models
All models use ConfigDict(extra="allow") — new API fields are preserved without breaking existing code.
| Method | Return type |
|---|---|
rates.evaluate_entry() |
APIResponse[CalcResponse] |
rates.evaluate_entries() |
APIResponse[list[CalcResponse]] |
rates.evaluate_multicountry() |
APIResponse[list[CalcResponse]] |
search.hts() |
APIResponse[list[APIRespSearchHtsItem]] |
search.autocomplete_hts() |
APIResponse[list[APIRespAutocompleteHtsItem]] |
search.hts_by_description() |
APIResponse[list[APIRespAutocompleteHtsItem]] |
search.hts_docs() |
APIResponse[Any] |
context.get_hts_code() |
APIResponse[APIRespDataHtsCodeHub] |
context.get_hts_details() |
APIResponse[APIRespDataHtsCodeContext] |
context.get_hts_hub() |
APIResponse[Any] |
context.list_sections() |
APIResponse[Any] |
context.list_chapters_by_section() |
APIResponse[Any] |
context.list_countries() |
APIResponse[list[CountryRecord]] |
context.get_country() |
APIResponse[CountryRecord] |
compare.tariff() |
APIResponse[dict[str, CalcResponse]] |
compare.hts_rates() |
APIResponse[CompareRatesResponse] |
compare.sources() |
APIResponse[CompareSourcesResponse] |
versions.list() |
APIResponse[list[HtsSourceVersion]] |
Request models (optional)
For IDE autocomplete on request bodies:
from neo_tariff.types import CalcInputs
inputs = CalcInputs(
hts_code="7208.10.15",
country_of_origin="CN",
cost=10_000,
qty=1_000,
)
result = client.rates.evaluate_entry(**inputs.model_dump())
Requirements
Development
git clone https://github.com/Enterprise-Neo/neo-tariff-python.git
cd neo-tariff-python
pip install -e ".[dev]"
# Run tests
python -m pytest tests/ -q
# Lint
ruff check . --fix && ruff format .
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file neo_tariff-0.1.0.dev3.tar.gz.
File metadata
- Download URL: neo_tariff-0.1.0.dev3.tar.gz
- Upload date:
- Size: 118.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f55e630f83b9c2704b25b37173fa31800aef393ae1b0ee7e83940a1c1cd8c12a
|
|
| MD5 |
e20992586ae70fa47c4a86a4f512faa6
|
|
| BLAKE2b-256 |
be491592de4381ecfc847c4114b3d655f0e02fa77e5ecd5b929b1acd331108c3
|
Provenance
The following attestation bundles were made for neo_tariff-0.1.0.dev3.tar.gz:
Publisher:
publish.yml on Enterprise-Neo/neo-tariff-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
neo_tariff-0.1.0.dev3.tar.gz -
Subject digest:
f55e630f83b9c2704b25b37173fa31800aef393ae1b0ee7e83940a1c1cd8c12a - Sigstore transparency entry: 939434926
- Sigstore integration time:
-
Permalink:
Enterprise-Neo/neo-tariff-python@b6d9ffcc4c2dadabb2b03c58ae8184a80d3176ce -
Branch / Tag:
refs/heads/develop - Owner: https://github.com/Enterprise-Neo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b6d9ffcc4c2dadabb2b03c58ae8184a80d3176ce -
Trigger Event:
push
-
Statement type:
File details
Details for the file neo_tariff-0.1.0.dev3-py3-none-any.whl.
File metadata
- Download URL: neo_tariff-0.1.0.dev3-py3-none-any.whl
- Upload date:
- Size: 34.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01c05e4d6d176d60141c28c3645716f78cdec78a264f53f0fde8780d9b48753d
|
|
| MD5 |
eaff93aacee713007edf6fac1aac741e
|
|
| BLAKE2b-256 |
a1bc6f3c4fe6983a58bba4b97b51872484be14bd12054d2d31a95c51abcbedca
|
Provenance
The following attestation bundles were made for neo_tariff-0.1.0.dev3-py3-none-any.whl:
Publisher:
publish.yml on Enterprise-Neo/neo-tariff-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
neo_tariff-0.1.0.dev3-py3-none-any.whl -
Subject digest:
01c05e4d6d176d60141c28c3645716f78cdec78a264f53f0fde8780d9b48753d - Sigstore transparency entry: 939434934
- Sigstore integration time:
-
Permalink:
Enterprise-Neo/neo-tariff-python@b6d9ffcc4c2dadabb2b03c58ae8184a80d3176ce -
Branch / Tag:
refs/heads/develop - Owner: https://github.com/Enterprise-Neo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b6d9ffcc4c2dadabb2b03c58ae8184a80d3176ce -
Trigger Event:
push
-
Statement type: