Medusa integration

Tariffs API for Medusa.

Add US duty and tariff calculation to a Medusa checkout with a single REST call. No new service to deploy, no GraphQL gymnastics.

Medusa puts the checkout in your codebase, which is exactly the right place to compute landed cost. This page shows how to call Tariffs API from a Medusa cart-completion workflow or storefront, return the duty amount, and surface it as a line item or shipping option modifier.

Why this works

Built for Medusa developers.

Headless-native

Medusa is API-first. So are we. One HTTP call from your storefront or backend, deterministic JSON back.

Owns the checkout

Your team controls the cart flow. We're a data dependency, not a checkout takeover. No iframe, no redirect.

Public pricing

$199/month flat, 100,000 calls included. No demo call, no per-shipment fee, no contract.

US duty stacking covered

Base HTSUS duty plus Section 301, 232, IEEPA, and Chapter 99 measures applied automatically by origin and HTS code.

In your code

Drop it in.

Three snippets: signup, server-side call from a Medusa workflow step, and storefront-side call. Pick whichever fits your architecture.

1. Get an API key

bash
# Sign up at https://tariffsapi.com — 14-day free trial, no card required.
# Your key lives at /api-keys after signup.
export TARIFFSAPI_KEY="ta_live_..."

2. Server-side: Medusa workflow step (TypeScript)

typescript
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"

export const calculateDutyStep = createStep(
  "calculate-duty",
  async ({ htsCode, originCountry }: { htsCode: string; originCountry: string }) => {
    const res = await fetch(
      `https://tariffsapi.com/api/v1/tariffs/resolve?hts=${htsCode}&origin=${originCountry}`,
      { headers: { Authorization: `Bearer ${process.env.TARIFFSAPI_KEY}` } }
    )
    const data = await res.json()
    const rate = data.summary.total_resolved_ad_valorem_rate / 100
    return new StepResponse({ rate, raw: data })
  }
)

3. Storefront: Next.js route handler

typescript
// app/api/duty/route.ts
export async function GET(req: Request) {
  const { searchParams } = new URL(req.url)
  const hts = searchParams.get("hts")
  const origin = searchParams.get("origin")

  const res = await fetch(
    `https://tariffsapi.com/api/v1/tariffs/resolve?hts=${hts}&origin=${origin}`,
    { headers: { Authorization: `Bearer ${process.env.TARIFFSAPI_KEY}` } }
  )
  return Response.json(await res.json())
}
What you get back

One endpoint. Deterministic JSON.

GET /api/v1/tariffs/resolve?hts=8541.10.00.80&origin=CN returns the base duty rate, every applicable Chapter 99 measure, a confidence score, and the candidates we considered when the match isn't exact. The bulk endpoint takes up to 200 codes per call. Plain REST, JSON in JSON out, no SDK required.

GET /api/v1/tariffs/resolve?hts=8541.10.00.80&origin=CN

{
  "summary": {
    "applicable_ad_valorem_rate": 0.0,
    "resolved_additional_ad_valorem_rate": 25.0,
    "total_resolved_ad_valorem_rate": 25.0
  },
  "base_tariff": { "percentage_component": 0.0 },
  "additional_measures": [
    {
      "program": "section_301",
      "chapter_99_code": "9903.91.05",
      "resolved_rate": { "percentage_component": 0.25 }
    }
  ]
}
FAQ

Medusa + Tariffs API

Is there an official Medusa plugin?

Not yet. A first-party @tariffsapi/medusa-plugin is on the roadmap. For now the integration is a direct HTTP call from a workflow step or your storefront, which most Medusa teams prefer anyway since it keeps the plugin surface small.

Where in the cart lifecycle should I call this?

Two options. Call it at cart update so the duty appears live as items are added (best UX, more requests). Or call it once at cart completion as a workflow step (cheaper, duty appears only at checkout). Bulk endpoint helps if you call per-item.

Do I need an HTS code on each Medusa product?

Yes. Store the HTSUS code as a product metadata field (e.g. metadata.hts_code) and read it from line_item.variant.product.metadata in your workflow. If you don't have codes yet, Tariffs API also exposes a search endpoint for lookup.

How do I show the duty to the customer?

Either as a separate line item (most common, transparent) or rolled into shipping. Medusa's cart model supports both via custom adjustments. The page renders whatever you pass.

Sources

Add US duty to your Medusa checkout in an afternoon.