tarifftrust 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ .mypy_cache/
5
+ .ruff_cache/
6
+ .pytest_cache/
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+ node_modules/
11
+ .next/
12
+ .env
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sébastien Chapeland EI (TariffTrust)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,223 @@
1
+ Metadata-Version: 2.5
2
+ Name: tarifftrust
3
+ Version: 0.1.0
4
+ Summary: Official Python client for the TariffTrust API: every US import duty and fee for an HTS code, an origin and a value, each with its official source.
5
+ Project-URL: Homepage, https://tarifftrust.com/api/
6
+ Project-URL: Documentation, https://tarifftrust.com/api/reference/
7
+ Project-URL: Guides, https://tarifftrust.com/guides/
8
+ Project-URL: Repository, https://github.com/tarifftrust/tarifftrust
9
+ Project-URL: Changelog, https://tarifftrust.com/changelog/
10
+ Author-email: TariffTrust <contact@tarifftrust.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: api-client,customs,harmonized-tariff-schedule,hts,import-duty,landed-cost,section-232,section-301,tariff,tariffs,trade-compliance
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Topic :: Office/Business :: Financial
24
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.10
27
+ Requires-Dist: httpx<1,>=0.25
28
+ Description-Content-Type: text/markdown
29
+
30
+ # tarifftrust: US tariff API client for Python
31
+
32
+ The official Python client for the [TariffTrust API](https://tarifftrust.com/api/). Send an HTS code,
33
+ a country of origin and a value. Get every US import duty and fee that applies, from the tariff
34
+ schedule and Sections 301, 232, 201 and 338 to the entry fees, each with its official, dated source.
35
+
36
+ ```bash
37
+ pip install tarifftrust
38
+ ```
39
+
40
+ Requires Python 3.10 or later. Fully typed, sync and async.
41
+
42
+ ## Quick start
43
+
44
+ Create a key in [your workspace](https://tarifftrust.com/keys/); your plan must include the API
45
+ ([plans](https://tarifftrust.com/pricing/)). Keep it on your server.
46
+
47
+ ```python
48
+ from tarifftrust import TariffTrust
49
+
50
+ client = TariffTrust(api_key="tarifftrust_...") # or set TARIFFTRUST_API_KEY
51
+
52
+ result = client.estimate(hts="6109.10.00.12", origin="CN", customs_value="10000")
53
+
54
+ print(result.status, result.estimated_duty)
55
+ for component in result.components:
56
+ print(component.label, component.amount, component.source.url)
57
+ ```
58
+
59
+ Read `status` first, then the amounts: decimal strings in US dollars, ready for `Decimal`.
60
+
61
+ **Unknown is never zero.** When `estimated_duty` is `None`, the duty could not be established: only
62
+ `known_duty_subtotal` is. See [the guide](https://tarifftrust.com/guides/#answer).
63
+
64
+ ## A whole declaration
65
+
66
+ MPF and HMF are charged once on a declaration: adding up single-product estimates gives a wrong total.
67
+
68
+ ```python
69
+ entry = client.estimate_entry(
70
+ transport_mode="ocean",
71
+ lines=[
72
+ {"reference": "PO-1042-1", "hts": "6109.10.00.12", "origin": "CN", "customs_value": "1000"},
73
+ {"reference": "PO-1042-2", "hts": "6109.10.00.12", "origin": "VN", "customs_value": "2500"},
74
+ ],
75
+ )
76
+ print(entry.estimated_duty, entry.total_fees, entry.estimated_landed_cost)
77
+ ```
78
+
79
+ ## Several products, a history, a saved estimate
80
+
81
+ ```python
82
+ batch = client.estimate_batch(
83
+ items=[
84
+ {"hts": "6109.10.00.12", "origin": "CN", "customs_value": "10000"},
85
+ {"hts": "6109.10.00.12", "origin": "VN", "customs_value": "10000"},
86
+ ]
87
+ )
88
+ for item in batch.results:
89
+ print(item.index, item.result.estimated_duty if hasattr(item, "result") else item.error.code)
90
+
91
+ history = client.estimate_history(
92
+ hts="6109.10.00.12", origin="CN", customs_value="10000", from_="2026-10-01"
93
+ )
94
+ for point in history.points:
95
+ print(point.as_of, point.estimated_duty)
96
+
97
+ saved = client.save_estimate(
98
+ estimate={"hts": "6109.10.00.12", "origin": "CN", "customs_value": "10000"}
99
+ )
100
+ print(saved.id)
101
+ ```
102
+
103
+ `from` is a reserved word in Python: it is `from_` here, as an argument and on an answer.
104
+
105
+ ## The catalog
106
+
107
+ ```python
108
+ found = client.search_hts(q="cotton t-shirt", limit=5)
109
+ line = client.get_hts("6109.10.00.12")
110
+ print(line.description, line.general)
111
+ ```
112
+
113
+ ## Async
114
+
115
+ `AsyncTariffTrust` has the same methods, awaited.
116
+
117
+ ```python
118
+ import asyncio
119
+ from tarifftrust import AsyncTariffTrust
120
+
121
+
122
+ async def main():
123
+ async with AsyncTariffTrust() as client:
124
+ return await asyncio.gather(
125
+ client.estimate(hts="6109.10.00.12", origin="CN", customs_value="10000"),
126
+ client.estimate(hts="6109.10.00.12", origin="VN", customs_value="10000"),
127
+ )
128
+ ```
129
+
130
+ ## Errors
131
+
132
+ Each refusal of the API is its own exception, under `APIError`.
133
+
134
+ ```python
135
+ from tarifftrust import APIError, InvalidInputError, RateLimitError
136
+
137
+ try:
138
+ result = client.estimate(hts="6109.10.00.12", origin="??", customs_value="10000")
139
+ except InvalidInputError as error:
140
+ print(error.fields) # each field refused
141
+ except APIError as error:
142
+ print(error.status, error.code, error.message, error.request_id)
143
+ ```
144
+
145
+ | Exception | Status | When |
146
+ | --- | --- | --- |
147
+ | `AuthenticationError` | 401 | No valid API key |
148
+ | `AccessRequiredError` | 402 | No active subscription, or the quota is used up (`quota_exceeded`) |
149
+ | `PermissionDeniedError` | 403 | The key lacks the permission, or the plan the API |
150
+ | `NotFoundError` | 404 | Nothing of that name |
151
+ | `ConflictError` | 409 | An idempotency key sent again with another request |
152
+ | `PayloadTooLargeError` | 413 | Send fewer products or lines |
153
+ | `InvalidInputError` | 400, 422 | `fields` names each field refused; a 400 is a body that is not valid JSON |
154
+ | `RateLimitError` | 429 | Too many requests |
155
+ | `ServiceUnavailableError` | 502, 503, 504 | Unavailable for now |
156
+ | `APIConnectionError`, `APITimeoutError` | | The API could not be reached |
157
+
158
+ All of them inherit from `TariffTrustError`.
159
+
160
+ ## Retries and idempotency
161
+
162
+ A call is tried again, twice by default, after a connection failure, a timeout or a gateway error, or
163
+ when the API gives a `Retry-After` of 60 seconds or less. A refusal without one is raised at once:
164
+ trying again would not help.
165
+
166
+ Every estimate carries an idempotency key, the same on each attempt, so a retry counts once in your
167
+ quota. To make a retry of your own safe, across restarts for instance, give your own key:
168
+
169
+ ```python
170
+ client.estimate(hts="6109.10.00.12", origin="CN", customs_value="10000", idempotency_key="po-1042")
171
+ ```
172
+
173
+ Within 7 days, the same key with the same request gives the first response, counted once; with
174
+ another request, a `ConflictError`.
175
+
176
+ ## Settings
177
+
178
+ ```python
179
+ client = TariffTrust(
180
+ api_key="tarifftrust_...", # or TARIFFTRUST_API_KEY
181
+ timeout=60.0, # seconds, at each step of an attempt: connecting, sending, each read
182
+ max_retries=2,
183
+ max_retry_wait=60.0, # the longest Retry-After waited for, in seconds
184
+ http_client=None, # your own httpx.Client (a proxy, your certificates): yours to close
185
+ )
186
+ ```
187
+
188
+ ## The answers
189
+
190
+ An answer is an object with the fields of the [reference](https://tarifftrust.com/api/reference/objects/)
191
+ as attributes, typed for your editor. A field the answer leaves out reads as its default or `None`. A
192
+ field newer than your version of the package reads as an attribute too. `to_dict()` gives the object
193
+ as the API sent it, and the types are in `tarifftrust.types`.
194
+
195
+ ## Operations
196
+
197
+ <!-- operations:start -->
198
+ | Method | Route | What it does |
199
+ | --- | --- | --- |
200
+ | `client.list_agreements()` | [`GET /v1/agreements`](https://tarifftrust.com/api/reference/#list-agreements) | List the trade agreements |
201
+ | `client.estimate()` | [`POST /v1/estimates`](https://tarifftrust.com/api/reference/#estimate) | Estimate one product |
202
+ | `client.estimate_batch()` | [`POST /v1/estimates/batch`](https://tarifftrust.com/api/reference/#estimate-batch) | Estimate up to 200 products |
203
+ | `client.estimate_entry()` | [`POST /v1/estimates/entry`](https://tarifftrust.com/api/reference/#estimate-entry) | Estimate a whole import declaration |
204
+ | `client.estimate_history()` | [`POST /v1/estimates/history`](https://tarifftrust.com/api/reference/#estimate-history) | Estimate one product at every change of the tariff |
205
+ | `client.list_facts()` | [`GET /v1/facts`](https://tarifftrust.com/api/reference/#list-facts) | List the questions an estimate may ask |
206
+ | `client.search_hts()` | [`GET /v1/hts`](https://tarifftrust.com/api/reference/#search-hts) | Search the US tariff schedule |
207
+ | `client.get_hts()` | [`GET /v1/hts/{code}`](https://tarifftrust.com/api/reference/#get-hts) | Read one line of the US tariff schedule |
208
+ | `client.list_saved_estimates()` | [`GET /v1/saved-estimates`](https://tarifftrust.com/api/reference/#list-saved-estimates) | List the saved estimates |
209
+ | `client.save_estimate()` | [`POST /v1/saved-estimates`](https://tarifftrust.com/api/reference/#save-estimate) | Calculate and save an estimate |
210
+ | `client.get_saved_estimate()` | [`GET /v1/saved-estimates/{id}`](https://tarifftrust.com/api/reference/#get-saved-estimate) | Read a saved estimate |
211
+ | `client.get_status()` | [`GET /v1/status`](https://tarifftrust.com/api/reference/#get-status) | Read the status and the coverage of the data |
212
+ <!-- operations:end -->
213
+
214
+ ## Links
215
+
216
+ [API reference](https://tarifftrust.com/api/reference/) ·
217
+ [Integration guides](https://tarifftrust.com/guides/) ·
218
+ [Examples](https://github.com/tarifftrust/tarifftrust/tree/main/examples) ·
219
+ [Changelog](https://tarifftrust.com/changelog/) ·
220
+ [Data status](https://tarifftrust.com/status/)
221
+
222
+ TariffTrust provides informational estimates from official US sources. It is not a customs broker and
223
+ does not issue binding classifications or customs determinations.
@@ -0,0 +1,194 @@
1
+ # tarifftrust: US tariff API client for Python
2
+
3
+ The official Python client for the [TariffTrust API](https://tarifftrust.com/api/). Send an HTS code,
4
+ a country of origin and a value. Get every US import duty and fee that applies, from the tariff
5
+ schedule and Sections 301, 232, 201 and 338 to the entry fees, each with its official, dated source.
6
+
7
+ ```bash
8
+ pip install tarifftrust
9
+ ```
10
+
11
+ Requires Python 3.10 or later. Fully typed, sync and async.
12
+
13
+ ## Quick start
14
+
15
+ Create a key in [your workspace](https://tarifftrust.com/keys/); your plan must include the API
16
+ ([plans](https://tarifftrust.com/pricing/)). Keep it on your server.
17
+
18
+ ```python
19
+ from tarifftrust import TariffTrust
20
+
21
+ client = TariffTrust(api_key="tarifftrust_...") # or set TARIFFTRUST_API_KEY
22
+
23
+ result = client.estimate(hts="6109.10.00.12", origin="CN", customs_value="10000")
24
+
25
+ print(result.status, result.estimated_duty)
26
+ for component in result.components:
27
+ print(component.label, component.amount, component.source.url)
28
+ ```
29
+
30
+ Read `status` first, then the amounts: decimal strings in US dollars, ready for `Decimal`.
31
+
32
+ **Unknown is never zero.** When `estimated_duty` is `None`, the duty could not be established: only
33
+ `known_duty_subtotal` is. See [the guide](https://tarifftrust.com/guides/#answer).
34
+
35
+ ## A whole declaration
36
+
37
+ MPF and HMF are charged once on a declaration: adding up single-product estimates gives a wrong total.
38
+
39
+ ```python
40
+ entry = client.estimate_entry(
41
+ transport_mode="ocean",
42
+ lines=[
43
+ {"reference": "PO-1042-1", "hts": "6109.10.00.12", "origin": "CN", "customs_value": "1000"},
44
+ {"reference": "PO-1042-2", "hts": "6109.10.00.12", "origin": "VN", "customs_value": "2500"},
45
+ ],
46
+ )
47
+ print(entry.estimated_duty, entry.total_fees, entry.estimated_landed_cost)
48
+ ```
49
+
50
+ ## Several products, a history, a saved estimate
51
+
52
+ ```python
53
+ batch = client.estimate_batch(
54
+ items=[
55
+ {"hts": "6109.10.00.12", "origin": "CN", "customs_value": "10000"},
56
+ {"hts": "6109.10.00.12", "origin": "VN", "customs_value": "10000"},
57
+ ]
58
+ )
59
+ for item in batch.results:
60
+ print(item.index, item.result.estimated_duty if hasattr(item, "result") else item.error.code)
61
+
62
+ history = client.estimate_history(
63
+ hts="6109.10.00.12", origin="CN", customs_value="10000", from_="2026-10-01"
64
+ )
65
+ for point in history.points:
66
+ print(point.as_of, point.estimated_duty)
67
+
68
+ saved = client.save_estimate(
69
+ estimate={"hts": "6109.10.00.12", "origin": "CN", "customs_value": "10000"}
70
+ )
71
+ print(saved.id)
72
+ ```
73
+
74
+ `from` is a reserved word in Python: it is `from_` here, as an argument and on an answer.
75
+
76
+ ## The catalog
77
+
78
+ ```python
79
+ found = client.search_hts(q="cotton t-shirt", limit=5)
80
+ line = client.get_hts("6109.10.00.12")
81
+ print(line.description, line.general)
82
+ ```
83
+
84
+ ## Async
85
+
86
+ `AsyncTariffTrust` has the same methods, awaited.
87
+
88
+ ```python
89
+ import asyncio
90
+ from tarifftrust import AsyncTariffTrust
91
+
92
+
93
+ async def main():
94
+ async with AsyncTariffTrust() as client:
95
+ return await asyncio.gather(
96
+ client.estimate(hts="6109.10.00.12", origin="CN", customs_value="10000"),
97
+ client.estimate(hts="6109.10.00.12", origin="VN", customs_value="10000"),
98
+ )
99
+ ```
100
+
101
+ ## Errors
102
+
103
+ Each refusal of the API is its own exception, under `APIError`.
104
+
105
+ ```python
106
+ from tarifftrust import APIError, InvalidInputError, RateLimitError
107
+
108
+ try:
109
+ result = client.estimate(hts="6109.10.00.12", origin="??", customs_value="10000")
110
+ except InvalidInputError as error:
111
+ print(error.fields) # each field refused
112
+ except APIError as error:
113
+ print(error.status, error.code, error.message, error.request_id)
114
+ ```
115
+
116
+ | Exception | Status | When |
117
+ | --- | --- | --- |
118
+ | `AuthenticationError` | 401 | No valid API key |
119
+ | `AccessRequiredError` | 402 | No active subscription, or the quota is used up (`quota_exceeded`) |
120
+ | `PermissionDeniedError` | 403 | The key lacks the permission, or the plan the API |
121
+ | `NotFoundError` | 404 | Nothing of that name |
122
+ | `ConflictError` | 409 | An idempotency key sent again with another request |
123
+ | `PayloadTooLargeError` | 413 | Send fewer products or lines |
124
+ | `InvalidInputError` | 400, 422 | `fields` names each field refused; a 400 is a body that is not valid JSON |
125
+ | `RateLimitError` | 429 | Too many requests |
126
+ | `ServiceUnavailableError` | 502, 503, 504 | Unavailable for now |
127
+ | `APIConnectionError`, `APITimeoutError` | | The API could not be reached |
128
+
129
+ All of them inherit from `TariffTrustError`.
130
+
131
+ ## Retries and idempotency
132
+
133
+ A call is tried again, twice by default, after a connection failure, a timeout or a gateway error, or
134
+ when the API gives a `Retry-After` of 60 seconds or less. A refusal without one is raised at once:
135
+ trying again would not help.
136
+
137
+ Every estimate carries an idempotency key, the same on each attempt, so a retry counts once in your
138
+ quota. To make a retry of your own safe, across restarts for instance, give your own key:
139
+
140
+ ```python
141
+ client.estimate(hts="6109.10.00.12", origin="CN", customs_value="10000", idempotency_key="po-1042")
142
+ ```
143
+
144
+ Within 7 days, the same key with the same request gives the first response, counted once; with
145
+ another request, a `ConflictError`.
146
+
147
+ ## Settings
148
+
149
+ ```python
150
+ client = TariffTrust(
151
+ api_key="tarifftrust_...", # or TARIFFTRUST_API_KEY
152
+ timeout=60.0, # seconds, at each step of an attempt: connecting, sending, each read
153
+ max_retries=2,
154
+ max_retry_wait=60.0, # the longest Retry-After waited for, in seconds
155
+ http_client=None, # your own httpx.Client (a proxy, your certificates): yours to close
156
+ )
157
+ ```
158
+
159
+ ## The answers
160
+
161
+ An answer is an object with the fields of the [reference](https://tarifftrust.com/api/reference/objects/)
162
+ as attributes, typed for your editor. A field the answer leaves out reads as its default or `None`. A
163
+ field newer than your version of the package reads as an attribute too. `to_dict()` gives the object
164
+ as the API sent it, and the types are in `tarifftrust.types`.
165
+
166
+ ## Operations
167
+
168
+ <!-- operations:start -->
169
+ | Method | Route | What it does |
170
+ | --- | --- | --- |
171
+ | `client.list_agreements()` | [`GET /v1/agreements`](https://tarifftrust.com/api/reference/#list-agreements) | List the trade agreements |
172
+ | `client.estimate()` | [`POST /v1/estimates`](https://tarifftrust.com/api/reference/#estimate) | Estimate one product |
173
+ | `client.estimate_batch()` | [`POST /v1/estimates/batch`](https://tarifftrust.com/api/reference/#estimate-batch) | Estimate up to 200 products |
174
+ | `client.estimate_entry()` | [`POST /v1/estimates/entry`](https://tarifftrust.com/api/reference/#estimate-entry) | Estimate a whole import declaration |
175
+ | `client.estimate_history()` | [`POST /v1/estimates/history`](https://tarifftrust.com/api/reference/#estimate-history) | Estimate one product at every change of the tariff |
176
+ | `client.list_facts()` | [`GET /v1/facts`](https://tarifftrust.com/api/reference/#list-facts) | List the questions an estimate may ask |
177
+ | `client.search_hts()` | [`GET /v1/hts`](https://tarifftrust.com/api/reference/#search-hts) | Search the US tariff schedule |
178
+ | `client.get_hts()` | [`GET /v1/hts/{code}`](https://tarifftrust.com/api/reference/#get-hts) | Read one line of the US tariff schedule |
179
+ | `client.list_saved_estimates()` | [`GET /v1/saved-estimates`](https://tarifftrust.com/api/reference/#list-saved-estimates) | List the saved estimates |
180
+ | `client.save_estimate()` | [`POST /v1/saved-estimates`](https://tarifftrust.com/api/reference/#save-estimate) | Calculate and save an estimate |
181
+ | `client.get_saved_estimate()` | [`GET /v1/saved-estimates/{id}`](https://tarifftrust.com/api/reference/#get-saved-estimate) | Read a saved estimate |
182
+ | `client.get_status()` | [`GET /v1/status`](https://tarifftrust.com/api/reference/#get-status) | Read the status and the coverage of the data |
183
+ <!-- operations:end -->
184
+
185
+ ## Links
186
+
187
+ [API reference](https://tarifftrust.com/api/reference/) ·
188
+ [Integration guides](https://tarifftrust.com/guides/) ·
189
+ [Examples](https://github.com/tarifftrust/tarifftrust/tree/main/examples) ·
190
+ [Changelog](https://tarifftrust.com/changelog/) ·
191
+ [Data status](https://tarifftrust.com/status/)
192
+
193
+ TariffTrust provides informational estimates from official US sources. It is not a customs broker and
194
+ does not issue binding classifications or customs determinations.
@@ -0,0 +1,70 @@
1
+ [project]
2
+ name = "tarifftrust"
3
+ version = "0.1.0"
4
+ description = "Official Python client for the TariffTrust API: every US import duty and fee for an HTS code, an origin and a value, each with its official source."
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
9
+ authors = [{ name = "TariffTrust", email = "contact@tarifftrust.com" }]
10
+ keywords = [
11
+ "tariff",
12
+ "tariffs",
13
+ "hts",
14
+ "harmonized-tariff-schedule",
15
+ "customs",
16
+ "import-duty",
17
+ "landed-cost",
18
+ "section-301",
19
+ "section-232",
20
+ "trade-compliance",
21
+ "api-client",
22
+ ]
23
+ classifiers = [
24
+ "Development Status :: 4 - Beta",
25
+ "Intended Audience :: Developers",
26
+ "Operating System :: OS Independent",
27
+ "Programming Language :: Python :: 3",
28
+ "Programming Language :: Python :: 3.10",
29
+ "Programming Language :: Python :: 3.11",
30
+ "Programming Language :: Python :: 3.12",
31
+ "Programming Language :: Python :: 3.13",
32
+ "Programming Language :: Python :: 3.14",
33
+ "Topic :: Office/Business :: Financial",
34
+ "Topic :: Software Development :: Libraries :: Python Modules",
35
+ "Typing :: Typed",
36
+ ]
37
+ dependencies = ["httpx>=0.25,<1"]
38
+
39
+ [project.urls]
40
+ Homepage = "https://tarifftrust.com/api/"
41
+ Documentation = "https://tarifftrust.com/api/reference/"
42
+ Guides = "https://tarifftrust.com/guides/"
43
+ Repository = "https://github.com/tarifftrust/tarifftrust"
44
+ Changelog = "https://tarifftrust.com/changelog/"
45
+
46
+ [dependency-groups]
47
+ dev = ["mypy>=1.13", "pytest>=8", "ruff>=0.8"]
48
+
49
+ [build-system]
50
+ requires = ["hatchling>=1.27"]
51
+ build-backend = "hatchling.build"
52
+
53
+ [tool.hatch.build.targets.wheel]
54
+ packages = ["src/tarifftrust"]
55
+
56
+ [tool.pytest.ini_options]
57
+ testpaths = ["tests"]
58
+ addopts = "-q"
59
+
60
+ [tool.ruff]
61
+ line-length = 100
62
+ target-version = "py310"
63
+ extend-exclude = ["src/tarifftrust/types.py", "src/tarifftrust/_operations.py"]
64
+
65
+ [tool.ruff.lint]
66
+ select = ["E", "F", "I", "UP", "B", "SIM"]
67
+
68
+ [tool.mypy]
69
+ strict = true
70
+ files = ["src"]
@@ -0,0 +1,39 @@
1
+ """Official Python client for the TariffTrust API: every US import duty and fee for an HTS code,
2
+ an origin and a value, each with its official source. https://tarifftrust.com/api/"""
3
+
4
+ from ._client import AsyncTariffTrust, TariffTrust
5
+ from ._errors import (
6
+ AccessRequiredError,
7
+ APIConnectionError,
8
+ APIError,
9
+ APITimeoutError,
10
+ AuthenticationError,
11
+ ConflictError,
12
+ InvalidInputError,
13
+ NotFoundError,
14
+ PayloadTooLargeError,
15
+ PermissionDeniedError,
16
+ RateLimitError,
17
+ ServiceUnavailableError,
18
+ TariffTrustError,
19
+ )
20
+ from ._version import __version__
21
+
22
+ __all__ = [
23
+ "APIConnectionError",
24
+ "APIError",
25
+ "APITimeoutError",
26
+ "AccessRequiredError",
27
+ "AsyncTariffTrust",
28
+ "AuthenticationError",
29
+ "ConflictError",
30
+ "InvalidInputError",
31
+ "NotFoundError",
32
+ "PayloadTooLargeError",
33
+ "PermissionDeniedError",
34
+ "RateLimitError",
35
+ "ServiceUnavailableError",
36
+ "TariffTrust",
37
+ "TariffTrustError",
38
+ "__version__",
39
+ ]