API契約を読む
下記の契約は、リクエストのパターン、レスポンスの構造、エラーの意味、レート制限をカバーしています。20分の読み込みが、数日分のデバッグを節約します。
APIリファレンス
HTS分類と関税計算を、あなたのシステムに直接統合します。製品説明と原産地を送信すると、1回のREST呼び出しでHTSコードと完全な関税スタックの内訳が返されます。
パフォーマンス
数百のSKU? 数千? Gingerはそのすべてを数分で分類します。
1回のAPI呼び出しで単一の製品を分類します。
応答時間は本番トラフィック全体で測定されています。低いパーセンタイルは典型的な体験を、高いパーセンタイルは最悪ケースの裾を表します。
平均
36秒
すべての本番リクエストにわたる平均応答時間。
中央値(p50)
30秒
すべてのリクエストの半数がこの時間内に完了します。
p95
79秒
リクエストの95%がこの時間内に完了します。典型的な最悪ケースです。
p99
108秒
負荷がかかっていても、リクエストの99%がこの時間内に完了します。
1回のAPI呼び出しで最大200製品を分類します。
大規模カタログのために構築。1回のリクエストがバッチ全体を並列処理し、数分で完了します。
呼び出しあたりの品目数
200
バッチAPI呼び出しあたりの最大製品数。
完了時間
3~5分
バッチ全体を最初から最後まで処理する典型的な所要時間。
1日あたりの処理能力
20万件以上
本番稼働ティアの1日あたりの分類処理量。カスタムのエンタープライズティアは1時間あたり10万件の分類まで拡張します。
腕時計などの第91類製品は、単一の単位としてではなく、構成要素ごとに課税されます。APIはそれらを自動的に構成部分に分割し、各部分がそれぞれ独自のHTSコードと関税計算を持つcomponents配列を返します。ほとんどの分類APIはこれを単に飛ばしてしまいますが、真の貿易コンプライアンスとは、例外なくすべての製品が正しい関税処理を受けることを意味します。
GingerControl OpenAPIは、HTS分類と関税計算を自動化するためのRESTインターフェースです。製品説明と原産地を送信すると、1回の呼び出しでHTSコードと完全な関税内訳が返されます。
分類結果はあなたのチームのためのリサーチ出力です。1,000製品以上にわたる社内ベンチマークでは、エンジンは99.86%の正確性に達しており、すべての結果は申告前にライセンスを持つ通関業者が確認することを前提に設計されています。
単一製品エンドポイント
1リクエストにつき1製品を、完全な関税詳細とともに。
バッチエンドポイント
1リクエストにつき最大200製品。
分割コード対応
分割コード製品向けの構成要素レベルの関税。
完全な関税スタック
一般(MFN)税率および特別税率、Section 301、232、122、そして該当するすべての第99類エントリー。
下記の契約は、リクエストのパターン、レスポンスの構造、エラーの意味、レート制限をカバーしています。20分の読み込みが、数日分のデバッグを節約します。
お問い合わせいただければ、メールなどのオフラインチャネルを通じてテストキーをお届けします。
警告
テストキーは少量のクォータを持ち、7~30日で失効します。開発とデバッグ専用であり、本番稼働には使用できません。
ほとんどのチームは基本的な統合を素早く完了し、残りの時間を、返されたデータを自社システムに組み込むことに費やします。
本番稼働の準備が整ったら、本番キーをリクエストしてください。呼び出しパターン、IP許可リスト、ピークQPSに合わせてサイズを設定します。
警告
本番APIキーは安全に保管してください。現段階では、APIキーが課金の唯一の根拠となります。
Method: POST
Path: /openapi/v1/tariff
Base URL: https://api.gingercontrol.com
| Header | Required | Description |
|---|---|---|
Content-Type | Yes | Must be application/json |
X-Api-Key | Yes | Caller credential issued offline by GingerControl. Used for authentication, rate limiting, and quota control. |
X-Request-Id | No | Request trace identifier for troubleshooting and log tracing. Server generates one if omitted. |
| Header | Description | Purpose |
|---|---|---|
Content-Type | Always application/json | Indicates the response body format |
X-Request-Id | Echoes the caller-provided value, or a server-generated value | Recommended for logging and troubleshooting |
Retry-After | Returned only with 429 Too Many Requests | Tells the caller how many seconds to wait before retrying |
| Field | Type | Required | Description |
|---|---|---|---|
description | string | Yes | Product description. Must not be empty; max 10,000 characters. |
country_of_origin | string | Yes | ISO 3166-1 alpha-2 country code. EU (European Union) and UK (United Kingdom) are also accepted; GB is accepted and processed as UK. |
extra | object | No | Additional input. The current version only consumes steel_pour_country and aluminum_pour_country; all other fields are ignored. |
extra.steel_pour_country | string | No | Steel pour country. Same rules as country_of_origin. |
extra.aluminum_pour_country | string | No | Aluminum pour country. Same rules as country_of_origin. |
Request Example
{
"description": "Cotton knit short sleeve T-shirt",
"country_of_origin": "DE",
"extra": {
"steel_pour_country": "IT",
"aluminum_pour_country": "FR"
}
}Response Example
{
"hts_code": "6109.10.0012",
"tariffs": {
"general_rate": "16.5%",
"special_rate": "Free",
"Section 301": [],
"Section 232 - Metals": [],
"Section 122": [
{
"code": "9903.03.01",
"rate": "10%"
}
]
}
}| Field | Type | Meaning | Notes |
|---|---|---|---|
hts_code | string | The HTS code determined for the product | Normally a 10-digit code; a split-code product may return an 8-digit parent code such as 9101.11.40 |
tariffs | object | null | The set of tariff-related data for the product | May be null for split-code products |
tariffs.general_rate | string | null | General rate | This may also be understood as MFN |
tariffs.special_rate | string | null | Special rate | The raw text is lightly normalized, for example by removing a trailing parenthetical note |
tariffs.<module_key> | array | List of Chapter 99 entries for the module | Each element is {code, rate} |
tariffs.<module_key>[].code | string | Chapter 99 code | For example, 9903.85.08 |
tariffs.<module_key>[].rate | string | Rate | Percentage string such as 25% |
components | array | Component list for a split-code product | Omitted for ordinary products |
components[].hts_code | string | Component HTS code | Always 10 digits |
components[].tariffs | object | null | Tariff data for the component |
| Field | Type | Meaning | Notes |
|---|---|---|---|
detail | object | Error object | |
detail.code | string | Error code | Intended for programmatic handling |
detail.message | string | Error message | Intended for logging and troubleshooting |
Error Response Example
{
"detail": {
"code": "invalid_request",
"message": "Invalid request body."
}
}| HTTP Status | Code | Description |
|---|---|---|
401 | missing_api_key | X-Api-Key was not provided |
401 | invalid_api_key | API key validation failed |
403 | api_key_revoked | The API key has been revoked |
403 | client_disabled | The caller account has been disabled |
422 | invalid_request | Request body is malformed or fields do not satisfy the contract |
429 | request_rate_limited | Request-level protection was triggered |
429 | item_rate_limited | Item-level quota protection was triggered |
500 | classification_failed | HTS identification failed |
500 | calculator_failed | Tariff calculation failed |
500 | internal_error | An unclassified internal error occurred |
Replace YOUR_API_KEY with the key issued to you, then run:
curl -X POST 'https://api.gingercontrol.com/openapi/v1/tariff' \
-H 'Content-Type: application/json' \
-H 'X-Api-Key: YOUR_API_KEY' \
-H 'X-Request-Id: manual-single-001' \
-d '{
"description": "Cotton knit short sleeve T-shirt",
"country_of_origin": "DE",
"extra": {
"steel_pour_country": "IT",
"aluminum_pour_country": "FR"
}
}'Method: POST
Path: /openapi/v1/tariff/batch
Base URL: https://api.gingercontrol.com
Request and response headers are identical to the Single-Product Endpoint: Content-Type, X-Api-Key, and optional X-Request-Id on the request; X-Request-Id and Retry-After (on 429) on the response.
| Field | Type | Required | Description |
|---|---|---|---|
items | array | Yes | List of products. Up to 200 items per request. |
items[].item_id | string | Yes | Caller-defined unique identifier for result reconciliation. Must be unique within the request. |
items[].description | string | Yes | Product description. Must not be empty; max 10,000 characters. |
items[].country_of_origin | string | Yes | Same rules as the single-product country_of_origin. |
items[].extra | object | No | Same rules as the single-product extra object. |
Request Example
{
"items": [
{
"item_id": "SKU-DE-001",
"description": "Cotton knit short sleeve T-shirt",
"country_of_origin": "DE",
"extra": {
"steel_pour_country": "IT"
}
},
{
"item_id": "SKU-FR-002",
"description": "Cotton crew neck T-shirt",
"country_of_origin": "FR",
"extra": {}
}
]
}Response Example
{
"items": [
{
"item_id": "SKU-DE-001",
"status": "ok",
"hts_code": "6109.10.0012",
"tariffs": {
"general_rate": "16.5%",
"special_rate": "Free",
"Section 301": [],
"Section 232 - Metals": [],
"Section 122": [
{ "code": "9903.03.01", "rate": "10%" }
]
}
},
{
"item_id": "SKU-FR-002",
"status": "ok",
"hts_code": "6109.10.0004",
"tariffs": {
"general_rate": "16.5%",
"special_rate": "Free",
"Section 301": [],
"Section 232 - Metals": [],
"Section 122": [
{ "code": "9903.03.01", "rate": "10%" }
]
}
}
],
"summary": {
"total": 2,
"succeeded": 2,
"failed": 0
}
}| Field | Type | Meaning | Notes |
|---|---|---|---|
items | array | List of batch processing results | The response order matches the request order |
items[].item_id | string | Caller-provided unique identifier | Used for result reconciliation |
items[].status | string | Processing status | Either ok or failed |
items[].hts_code | string | HTS code for a successful item | Normally a 10-digit code; a split-code product may return an 8-digit parent code; present only when status = ok |
items[].tariffs | object | null | Tariff data for a successful item | May be null for split-code products; present only when status = ok |
items[].tariffs.general_rate | string | null | General rate | This may also be understood as MFN |
items[].tariffs.special_rate | string | null | Special rate | Lightly normalized before being returned |
items[].tariffs.<module_key> | array | Module entries | Each element is {code, rate} |
items[].tariffs.<module_key>[].code | string | Chapter 99 code | |
items[].tariffs.<module_key>[].rate | string | Rate | |
items[].components | array | Component list for a split-code product | Omitted for ordinary products; present only when status = ok |
items[].components[].hts_code | string | Component HTS code | Always 10 digits |
items[].components[].tariffs | object | null | Tariff data for the component | |
items[].code | string | Failure code for a failed item | Present only when status = failed |
summary | object | Summary information for the batch request | |
summary.total | integer | Total number of items in this request | |
summary.succeeded | integer | Number of successful items | |
summary.failed | integer | Number of failed items |
| Field | Type | Meaning | Notes |
|---|---|---|---|
detail | object | Error object | |
detail.code | string | Error code | Intended for programmatic handling |
detail.message | string | Error message | Intended for logging and troubleshooting |
Error Response Example
{
"detail": {
"code": "item_rate_limited",
"message": "Item quota exceeded."
}
}Batch-Level Error Codes
| HTTP Status | Code | Description |
|---|---|---|
401 | missing_api_key | X-Api-Key was not provided in the request headers |
401 | invalid_api_key | API key validation failed |
403 | api_key_revoked | The API key has been revoked |
403 | client_disabled | The caller account has been disabled |
422 | invalid_request | The top-level structure is invalid, item_id values are duplicated, fields are missing, field types are incorrect, or field values do not satisfy the contract |
429 | request_rate_limited | Request-level protection was triggered |
429 | item_rate_limited | Item-level quota protection was triggered |
500 | internal_error | An unclassified batch-level internal error occurred |
Item-Level Failure Codes
| Code | Description |
|---|---|
classification_failed | HTS identification failed for that item |
calculator_failed | Tariff calculation failed for that item |
internal_error | An unclassified internal error occurred for that item |
Replace YOUR_API_KEY with the key issued to you, then run:
curl -X POST 'https://api.gingercontrol.com/openapi/v1/tariff/batch' \
-H 'Content-Type: application/json' \
-H 'X-Api-Key: YOUR_API_KEY' \
-H 'X-Request-Id: manual-batch-001' \
-d '{
"items": [
{
"item_id": "SKU-DE-001",
"description": "Cotton knit short sleeve T-shirt",
"country_of_origin": "DE",
"extra": { "steel_pour_country": "IT" }
},
{
"item_id": "SKU-FR-002",
"description": "Cotton crew neck T-shirt",
"country_of_origin": "FR",
"extra": {}
}
]
}'429 Too Many Requests.Validate request bodies
If you receive 422, the request body structure, field types, or field values usually do not match the contract. Check the request body first.
Handle rate limits gracefully
If you receive 429, implement retry behavior using the Retry-After response header.
Log request IDs
Keep request logs and record the X-Request-Id for each call. This significantly reduces troubleshooting time.
Configure timeouts and retries
Configure reasonable timeouts, retries, and failure alerts so that network fluctuations can be handled robustly.
Do not embed your API key in frontend code, browser code, or any environment exposed to end users.
Do not use production API keys in test, development, or temporary debugging environments.
Store your API key in a secure configuration system, such as a secret manager or tightly controlled environment variables.
If an API key is lost, suspected to be leaked, or needs to be rotated, please contact us as soon as possible.
For integration support, testing, production rollout, or ongoing operations, please contact us:
Email: chen@gingercontrol.com
We use cookies to understand how visitors interact with our site. No personal data is shared with advertisers.