工作区
试用 API
数百? 上千? Ginger 在几分钟内帮你全部搞定。
单品分类
一次 API 调用即可分类单个产品。
输入
产品描述
原产国
国家代码遵循 ISO 3166-1 alpha-2 标准。可从列表中选择或输入 2 位字母代码。
请求体预览
{
"description": "Cotton knit short sleeve T-shirt",
"country_of_origin": "DE"
}输出
点击“开始”后结果将显示在此处。
批量分类
一次 API 调用最多可分类 100 个产品。以下可试用最多 5 笔。
输入
产品描述
原产国
国家代码遵循 ISO 3166-1 alpha-2 标准。可从列表中选择或输入 2 位字母代码。
请求体预览
{
"items": [
{
"item_id": "item-1",
"description": "Cotton knit short sleeve T-shirt",
"country_of_origin": "DE"
},
{
"item_id": "item-2",
"description": "Cotton crew neck T-shirt",
"country_of_origin": "FR"
}
]
}输出
点击“开始”后结果将显示在此处。
拆分码组合计税
第 91 章产品(如手表)需按组成部件分别计税,而非以整体计算。我们的 API 会自动将这类产品拆解为各个组成部件,每个部件都有独立的 HTS 编码和关税计算。在请求中使用 components 字段即可获取每个组件的税率明细。这是大多数分类 API 直接跳过的功能,但真正的贸易合规意味着每一个产品都必须获得正确的关税待遇,没有例外。
Overview
The GingerControl OpenAPI provides a REST interface for automated HTS classification and tariff calculation. With a single API call, you can send a product description and country of origin and receive the corresponding HTS code along with a full tariff breakdown, including General (MFN) rate, Special rate, Section 301, Section 232 Metals, Section 122, and all applicable Chapter 99 entries.
Single-Product Endpoint
Classify one product per request with full tariff details
Batch Endpoint
Process up to 120 products in a single request
Split-Code Support
Handles split-code products with component-level tariffs
Full Tariff Stack
MFN + Section 301 + 232 + 122 + Chapter 99
Integration Steps
Read the API Contract
Before you start integrating with the GingerControl OpenAPI, we recommend that you read the API contract below in full. This will help you quickly understand the request patterns, input and output structures, error semantics, and rate-limiting rules, which in turn reduces integration and debugging effort.
Request a Test API Key
Once you understand the API contract, please contact us offline to request a test API key. After we receive your request, we will issue a test key and deliver it to you through an offline channel, such as email.
Warning
Test API keys come with a relatively small traffic quota and are typically valid for only 7-30 days. They are intended for development and debugging only and must not be used in production.
Development and Debugging
After you receive your test API key, you can begin development and debugging. In most cases, you will complete the basic API integration quickly, and then spend more time integrating the returned data into your own system.
Production Integration
Once your system integration is complete and you are ready to go live, please contact us offline to request a production API key. To ensure service quality, we may need to learn more about your calling patterns, IP allowlist, peak QPS, latency expectations, and related information before issuing a production-grade API key and delivering it to you through an offline channel.
Warning
Please keep your production API key secure. At the current stage, the API key is the sole basis for billing.
Single-Product Endpoint
Method: POST
Path: /openapi/v1/tariff
Base URL: https://gingercontrol-openapi-1019079553349.us-west2.run.app
Request Headers
| 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. |
Response Headers
| 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 |
Request Body
| 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%"
}
]
}
}Successful Response
| 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 |
Error Response
| 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."
}
}Error Codes
| 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 |
Quick Test
Replace YOUR_API_KEY with the key issued to you, then run:
curl -X POST 'https://gingercontrol-openapi-1019079553349.us-west2.run.app/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"
}
}'Batch Endpoint
Method: POST
Path: /openapi/v1/tariff/batch
Base URL: https://gingercontrol-openapi-1019079553349.us-west2.run.app
Request Headers
| 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, log tracing, and issue investigation. Server generates one if omitted. |
Response Headers
| 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 |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
items | array | Yes | List of products. Up to 120 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 | ISO 3166-1 alpha-2 country code. EU (European Union) and UK (United Kingdom) are also accepted; GB is accepted and processed as UK. |
items[].extra | object | No | Additional input. The current version only consumes steel_pour_country and aluminum_pour_country; all other fields are ignored. |
items[].extra.steel_pour_country | string | No | Steel pour country. Same rules as country_of_origin. |
items[].extra.aluminum_pour_country | string | No | Aluminum pour country. Same rules as country_of_origin. |
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
}
}Successful Response
| 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 |
Error Response
| 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."
}
}Error Codes
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 |
Quick Test
Replace YOUR_API_KEY with the key issued to you, then run:
curl -X POST 'https://gingercontrol-openapi-1019079553349.us-west2.run.app/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": {}
}
]
}'Rate Limits & Quotas
- All API calls are subject to request-level protection. When request frequency is too high, the system returns
429 Too Many Requests. - Quota is consumed by the number of products processed. The single-product endpoint consumes 1 item, while batch consumes based on the number of items.
- Both endpoints share the same item-level quota under the same API key.
- Test API keys have relatively small traffic quotas and are intended only for development and integration testing.
- Production API keys are configured based on each customer's traffic model.
Development Recommendations
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.
Security Recommendations
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.
Contact
For integration support, testing, production rollout, or ongoing operations, please contact us:
Email: chen@gingercontrol.com