Build production trade
infrastructure.
Authentication, endpoints, webhooks, errors, SDKs, and changelog. Everything required to wire TariffOS into ERPs, quoting engines, and freight platforms.
The TariffOS API
The TariffOS API is a JSON over HTTPS interface for tariff intelligence, landed-cost computation, and trade compliance. It is the same engine that powers our dashboards, AI assistant, and enterprise integrations — exposed as primitives you can wire into any quoting engine, ERP, or freight platform.
All requests are made against https://api.tariffos.com and require a Bearer token. Responses are JSON, latencies are sub-100ms p95, and the surface area is versioned via the URL.
Run a sample request right here
The console below executes against an in-browser sandbox using mocked responses modeled on the production schema. Swap the placeholder API key for a real sk_test_… sandbox key to hit sandbox.api.tariffos.com directly.
https://sandbox.api.tariffos.com/v2/tariff/lookup?hs=8703.80&origin=CN&destination=USDemo only. Production keys grant per-workspace scope.
From zero to landed cost in 60 seconds
- Request a key from enterprise sales or hit our self-serve sandbox.
- Export it as
TARIFFOS_KEY. - Call
POST /v2/landed-costwith an HS code and shipment value. - Subscribe to
tariff.changedwebhooks for ongoing intelligence.
curl https://api.tariffos.com/v2/landed-cost \
-H "Authorization: Bearer $TARIFFOS_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: shp_4kJ29fA" \
-d '{
"hs_code": "8703.80",
"origin": "CN",
"destination": "US",
"value_usd": 48000,
"incoterm": "FOB"
}'Sandbox and production
| Environment | Base URL | Data | Rate limit |
|---|---|---|---|
| Sandbox | https://sandbox.api.tariffos.com | Frozen Q1 dataset | 60 r/min |
| Production | https://api.tariffos.com | Live, multi-region | By plan |
| EU residency | https://eu.api.tariffos.com | Live, EU-only egress | By plan |
URL-versioned, additive by default
Major versions live in the URL (/v2/…). Field additions and new enum values are non-breaking. Removals or rename ship as /v3 with a 12-month overlap and deprecation headers.
Sunset and Deprecation response headers per RFC 8594.Authentication overview
TariffOS supports three auth modes. Use API keys for server-side integrations, OAuth 2.0 for third-party apps acting on behalf of a tenant, and request signing when calling from untrusted edges.
| Mode | Use case | Header |
|---|---|---|
| API key | Server → API | Authorization: Bearer sk_live_… |
| OAuth 2.0 | Third-party app | Authorization: Bearer <access_token> |
| HMAC signing | Edge / browser | X-TariffOS-Signature: t=…,v1=… |
API keys
Keys are scoped to an environment and a workspace. Live keys are prefixed sk_live_; sandbox keys are sk_test_. Treat keys as secrets — store them in your platform's secret manager, never in source control.
GET /v2/tariff/lookup?hs=8703.80&origin=CN&destination=US HTTP/1.1
Host: api.tariffos.com
Authorization: Bearer sk_live_REPLACE_ME
Accept: application/json401 key_revoked within 5 seconds globally.OAuth 2.0 (Authorization Code + PKCE)
For partner apps acting on behalf of a TariffOS tenant. Standard OAuth 2.1 with PKCE; access tokens expire in 1 hour, refresh tokens in 60 days.
| Endpoint | Path |
|---|---|
| Authorize | https://auth.tariffos.com/oauth/authorize |
| Token | https://auth.tariffos.com/oauth/token |
| Revoke | https://auth.tariffos.com/oauth/revoke |
| Discovery | /.well-known/openid-configuration |
| Scope | Grants |
|---|---|
| tariff:read | Read tariff lookups + landed cost |
| shipments:write | Create shipment intents and quotes |
| alerts:manage | Subscribe and manage webhook endpoints |
| admin | Full workspace administration |
Request signing (HMAC-SHA256)
For environments where a key cannot be embedded (browser SDK, partner edge), sign each request with a short-lived signing secret derived server-side.
{timestamp}.{method}.{path}.{sha256(body)}
X-TariffOS-Signature: t=1714694400,v1=4f2e…c0a1/v2/tariff/lookupTariff lookup
Resolve the live applicable duty rate for a given HS code, origin, and destination — including special programs (Section 232/301, IEEPA, reciprocal tariffs).
| Field | Type | Req | Description |
|---|---|---|---|
| hs | string | required | HS code, 6–10 digits. |
| origin | string | required | ISO 3166-1 alpha-2 origin country. |
| destination | string | required | ISO 3166-1 alpha-2 destination country. |
| as_of | string | optional | ISO date — historical lookup. |
GET /v2/tariff/lookup?hs=8703.80&origin=CN&destination=US{
"hs_code": "8703.80",
"origin": "CN",
"destination": "US",
"applied_rate_pct": 44.5,
"components": [
{ "kind": "mfn", "rate_pct": 2.5 },
{ "kind": "section_301", "rate_pct": 25.0 },
{ "kind": "reciprocal", "rate_pct": 17.0 }
],
"effective": "2025-04-01",
"_meta": { "latency_ms": 38, "version": "v2.4.1" }
}/v2/landed-costLanded cost
Full landed-cost decomposition: duty, fees (MPF/HMF/VAT), freight, brokerage, and FTA-eligible savings. Returns alternative-sourcing recommendations when material savings exist.
| Field | Type | Req | Description |
|---|---|---|---|
| hs_code | string | required | HS code. |
| origin | string | required | ISO origin country. |
| destination | string | required | ISO destination country. |
| value_usd | number | required | Commercial invoice value. |
| incoterm | string | optional | FOB, CIF, DDP, EXW, … |
| weight_kg | number | optional | Used for freight modeling. |
POST /v2/landed-cost
Content-Type: application/json
Idempotency-Key: shp_4kJ29fA
{
"hs_code": "8703.80",
"origin": "CN",
"destination": "US",
"value_usd": 48000,
"incoterm": "FOB"
}{
"shipment_id": "shp_4kJ29fA",
"currency": "USD",
"value": 48000.00,
"duty": {
"mfn": 1200.00,
"section_301": 12000.00,
"reciprocal": 8160.00,
"total": 21360.00
},
"fees": { "mpf": 538.40, "hmf": 60.00 },
"freight_estimate": 2840.00,
"brokerage": 425.00,
"total_landed": 73223.40,
"fta_eligible": [],
"recommendations": [
{ "action": "shift_origin", "to": "VN", "savings_usd": 8420.00 }
]
}/v2/classifyAI classification
Map a free-text product description (and optional attributes) to the most likely HS code, with confidence and citations to the explanatory notes.
| Field | Type | Req | Description |
|---|---|---|---|
| description | string | required | Plain-text product description. |
| attributes | object | optional | Material, intended use, weight, etc. |
| destination | string | optional | Tunes classification to local nomenclature. |
POST /v2/classify
{
"description": "Cordless impact driver, lithium-ion, 18V, with carry case",
"attributes": { "powered_by": "battery" },
"destination": "US"
}{
"candidates": [
{ "hs_code": "8467.21", "confidence": 0.92, "title": "Drills, electromechanical, hand-held, …" },
{ "hs_code": "8467.29", "confidence": 0.05, "title": "Other tools, with self-contained electric motor" }
],
"citations": ["WCO Explanatory Note 84.67 (II)(B)"],
"_meta": { "model": "tariff-classifier-v3", "latency_ms": 612 }
}/v2/fta/eligibilityFTA eligibility
Check whether a shipment qualifies for preferential treatment under any active free trade agreement between the origin and destination.
| Field | Type | Req | Description |
|---|---|---|---|
| hs | string | required | HS code. |
| origin | string | required | Origin ISO. |
| destination | string | required | Destination ISO. |
GET /v2/fta/eligibility?hs=6109.10&origin=VN&destination=US{
"eligible_agreements": [],
"near_misses": [
{
"agreement": "GSP",
"blocked_by": "expired_2020-12-31",
"would_save_pct": 16.5
}
]
}/v2/origin/rulesRules of origin
Returns the substantial-transformation tests and regional value content thresholds for an HS code under a given agreement.
| Field | Type | Req | Description |
|---|---|---|---|
| hs | string | required | HS code. |
| agreement | string | required | USMCA, CPTPP, EU-VN, … |
GET /v2/origin/rules?hs=8703.80&agreement=USMCA{
"agreement": "USMCA",
"tests": [
{ "kind": "tariff_shift", "from": "8708", "to": "8703" },
{ "kind": "rvc", "method": "net_cost", "threshold_pct": 75 },
{ "kind": "labor_value", "threshold_pct": 40, "wage_floor_usd": 16 }
]
}/v2/scenarios/simulateScenario simulate
Run a what-if across one or many shipments with hypothetical tariff schedules, sourcing changes, or FX shocks. Returns deltas and worst/best case ranges.
| Field | Type | Req | Description |
|---|---|---|---|
| shipments | array | required | Array of shipment intents. |
| overrides | object | required | Tariff, FX, or sourcing overrides. |
POST /v2/scenarios/simulate
{
"shipments": [{ "hs_code": "8703.80", "origin": "CN", "destination": "US", "value_usd": 48000 }],
"overrides": { "reciprocal_tariff_pct": { "CN": 30 } }
}{
"baseline_total_landed": 73223.40,
"scenario_total_landed": 79463.40,
"delta_usd": 6240.00,
"delta_pct": 8.52
}/v2/changes/sinceTariff changes
Pull all schedule changes that affect your subscribed HS codes / lanes since a given timestamp. Designed for nightly batch reconciliation.
| Field | Type | Req | Description |
|---|---|---|---|
| since | string | required | ISO 8601 timestamp. |
| lanes | string | optional | Comma-separated origin>destination pairs. |
GET /v2/changes/since?since=2025-04-01T00:00:00Z&lanes=CN>US,VN>US{
"changes": [
{
"id": "chg_91kfA2",
"kind": "rate_change",
"hs": "8703.80",
"lane": "CN>US",
"from_pct": 27.5,
"to_pct": 44.5,
"effective": "2025-04-09",
"source": "USTR Federal Register 90 FR 12345"
}
],
"next_cursor": "cur_…"
}Webhooks
Subscribe an HTTPS endpoint to receive event notifications. Deliveries are signed with HMAC-SHA256 over the raw request body and a per-endpoint signing secret. Retries follow exponential backoff (1m → 24h) for up to 72 hours.
curl https://api.tariffos.com/v2/alerts/subscribe \
-H "Authorization: Bearer $TARIFFOS_KEY" \
-d '{
"url": "https://hooks.acme.com/tariffos",
"events": ["tariff.changed", "shipment.recommendation"],
"filters": { "lanes": ["CN>US", "VN>US"] }
}'import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(req: { headers: Record<string,string>, rawBody: string }, secret: string) {
const sig = req.headers["x-tariffos-signature"]; // t=...,v1=...
const parts = Object.fromEntries(sig.split(",").map(p => p.split("=")));
const expected = createHmac("sha256", secret)
.update(`${parts.t}.${req.rawBody}`)
.digest("hex");
return timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}Event reference
| Event | Fires when |
|---|---|
| tariff.changed | A duty rate on a subscribed lane is updated. |
| policy.announced | A policy memo is published before becoming effective. |
| fta.changed | An agreement enters/exits force or rules update. |
| shipment.recommendation | An optimization is found for a recurring lane. |
| alert.exposure_breach | Aggregate exposure crosses a configured threshold. |
Streaming API (SSE)
For low-latency dashboards, stream the same events over Server-Sent Events on GET /v2/stream. Authenticate with a short-lived stream token issued by POST /v2/stream/token.
const es = new EventSource(`https://api.tariffos.com/v2/stream?token=${streamToken}`);
es.addEventListener("tariff.changed", (e) => {
const change = JSON.parse(e.data);
console.log("New rate:", change.to_pct);
});Errors
Errors return a stable shape. The code field is the contract — do not branch on message, which is for humans.
{
"error": {
"code": "tariff_not_found",
"message": "No tariff schedule for HS 9999.99 on lane XX>US.",
"request_id": "req_01HZ…",
"doc_url": "https://docs.tariffos.com/errors#tariff_not_found"
}
}| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | Malformed input or missing required field. |
| 401 | unauthorized | Missing or invalid API key. |
| 403 | scope_required | Token lacks the required OAuth scope. |
| 404 | tariff_not_found | No schedule for the requested HS / lane. |
| 409 | idempotency_conflict | Same Idempotency-Key, different payload. |
| 422 | validation_failed | Schema valid, business rule violated. |
| 429 | rate_limited | Throttled — see Retry-After header. |
| 500 | internal_error | Surface as retryable; we are paged. |
| 503 | upstream_unavailable | A government data source is degraded. |
Rate limits
| Plan | Sustained | Burst | Concurrency |
|---|---|---|---|
| Sandbox | 60 r/min | 120 r/min | 4 |
| Growth | 1,200 r/min | 3,000 r/min | 32 |
| Enterprise | Custom | Custom | Custom |
Every response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. On 429, respect Retry-After.
Idempotency
All POST endpoints accept an Idempotency-Key header (UUID v4 recommended). Replays within 24 hours return the original response, including status code. Different payloads under the same key return 409 idempotency_conflict.
Pagination
List endpoints use cursor pagination. Pass ?limit=100&cursor=… — responses include next_cursor when more pages exist. Maximum page size is 500.
SDKs & libraries
| Language | Package | Status |
|---|---|---|
| TypeScript / Node | @tariffos/sdk | GA |
| Python | tariffos | GA |
| Go | github.com/tariffos/tariffos-go | Beta |
| Java | com.tariffos:sdk | Beta |
| .NET | TariffOS.Sdk | Preview |
| Ruby | tariffos | Preview |
Postman collection
Import the live collection — every endpoint, pre-request scripts for HMAC signing, and example sandbox keys.
https://docs.tariffos.com/postman/tariffos.postman_collection.jsonOpenAPI 3.1 specification
The full machine-readable spec — generate clients, mock servers, or contract tests directly from it.
https://api.tariffos.com/v2/openapi.json
sha256: 9f4c…1ab2Changelog
- 2025-04-12ADDEDReciprocal tariff component
Tariff lookup and landed cost now decompose the new reciprocal-tariff component. Existing fields are unchanged.
- 2025-03-30ADDEDEU residency endpoint
eu.api.tariffos.com — all data plane traffic stays within EU regions.
- 2025-02-18CHANGEDStable webhook signing v1
x-tariffos-signature now uses the stable t=…,v1=… format. Legacy x-signature is deprecated for removal 2025-08-01.
- 2025-01-04ADDEDScenario simulate endpoint
POST /v2/scenarios/simulate — model tariff, FX, and sourcing overrides across portfolios.
Need a sandbox key?
Approval in 24 hours. Production keys gated to enterprise plans.