API
Duty calculations and usage as JSON, for partners who run CustomsGenius inside their own product. Every call is served from https://app.customsgenius.com.
A partner holds one key (cgp_...), issued under the partner agreement. The key is a server secret: it mints short-lived tokens and reads usage, and it never reaches a browser. The token does the calculating, bound to one of your users. To get a key, write to team@customsgenius.com.
1. Mint a token
POST/api/partner/embed-token with the key as the bearer. Once per user session, from your server.
POST /api/partner/embed-token
Authorization: Bearer cgp_...
Content-Type: application/json
{ "userId": "your-user-id", "userLabel": "optional, for support" }
{ "token": "eyJhbGciOi...", "expiresAt": "2026-10-14T12:25:49.000Z",
"embedUrl": "https://app.customsgenius.com/embed/calculator?token=eyJhbGciOi..." }
The token lives 12 hours. userId is your own opaque id (1 to 128 characters); usage is reported per userId. embedUrl frames the full calculator in your colors if you want the screen rather than the numbers.
2. Calculate
POST/api/embed/tariff-simulate with the token as the bearer.
POST /api/embed/tariff-simulate
Authorization: Bearer eyJhbGciOi...
Content-Type: application/json
{ "htsCode": "8479.89.9597", "originCountry": "DE", "value": 25000,
"transportMode": "ocean", "entryDate": "2026-10-13" }
| Field | Meaning |
|---|---|
htsCode | The HTS code, dots optional. At least 8 digits; a partner account may require the full 10. |
originCountry | Country of origin, ISO 3166-1 two letters. Origin, not country of export. |
value | Customs value in US dollars. Omit it for rates only (every amount is null). |
transportMode | ocean, air, rail or truck. Decides the harbor maintenance fee. |
entryDate | YYYY-MM-DD. The duties in force on that date, past dates included. |
The calculator's further inputs (metal content, a USMCA qualification, SPI claims, AD/CVD deposits, the attestations behind each election) ride on the same body; ask us for the list when a screen needs one.
A real answer, trimmed to what a duty display needs:
{
"dutyLines": [
{ "code": "8479.89.9597", "description": "Other", "ratePct": 2.5, "amount": 625 },
{ "code": "9903.05.39", "description": "Section 301 Forced Labor", "program": "Section 301 Forced Labor",
"ratePct": 0, "amount": 0, "preExclusionRatePct": 7.5, "preExclusionAmount": 1875,
"exclusionNote": "Excluded: subject to Section 232 action (9903.05.90, U.S. note 52(f))",
"exclusionClaimCode": "9903.05.90" },
{ "code": "9903.82.10", "description": "Combined 232", "program": "Combined 232", "ratePct": 12.5, "amount": 3125 }
],
"mpf": 86.6, "hmf": 31.25, "totalDuty": 3867.85, "landedCost": 28867.85,
"warnings": [],
"pgaFlags": [ { "flag_code": "FD1", "agency_code": "FDA", "requirement": "may_be_required",
"description": "FDA CLEARANCE MAY BE REQUIRED" } ],
"adCvdWarnings": [],
"ch99DisplayNames": { "9903.82.10": "Section 232 Metals - Derivatives Floor (15%)" }
}
| Field | Meaning |
|---|---|
dutyLines | One row per duty: the HTS line's general rate, then each Chapter 99 program that applies. ratePct is a percent of the customs value, amount is dollars. A program another program excludes stays listed at 0 with exclusionNote, the pre-exclusion figures and the heading the filer claims. |
mpf, hmf | Merchandise processing fee and harbor maintenance fee for the line as its own entry. hmf is null off the water. |
totalDuty | Every duty line plus the two fees. |
landedCost | value plus totalDuty. |
warnings | Sentences worth showing beside the number. Empty when there is nothing to say. |
pgaFlags | Partner government agency flags on the code: agency, requirement (required, may_be_required, informational) and ACE's description. |
adCvdWarnings | Antidumping and countervailing duty orders that may cover the code and origin, with case numbers. A deposit is priced only when the body names the case. |
elections | Claims that would change the duty (a US-content attestation, an FTA claim), each with its code and amount; the default is what dutyLines priced. |
ch99DisplayNames | A display name for each Chapter 99 code in the answer. |
Other fields serve the calculator's own screen (eligibleSpis, mfnAncestorPath, quota and a few more). Ignore them.
3. Usage
GET/api/partner/usage?month=2026-10 with the key as the bearer. One UTC month, default the current one: one row per userId (calculations, lookups, bulk rows and files, rejected and failed requests, first and last seen), token mints, totals, each key's limits, and a breakdown by day with the ten codes and ten origins priced most.
Errors
| Status | Meaning |
|---|---|
| 400 | An input the engine cannot price. The error sentence names the field. |
| 401 | Missing, invalid or expired token, or an unknown key. Mint again. |
| 403 | The key was revoked. |
| 429 | A budget is spent. Retry-After says when. |
| 503 | Ours. Retry later. |
Limits
| Budget | Default |
|---|---|
| Token mints | 60 per minute per key |
| Calculations, per partner | 300 per minute |
Calculations, per userId | 30 per minute |
| Usage reads | 30 per minute per key |
| Monthly calculations | uncapped unless agreed |
Every calculation is real and metered, in staging as in production. Cache the answer per line and recompute when an input or the entry date changes. For a batch job, tell us the volume before you build it.