# REST API for classification and landed cost

> REST API for HS code classification and landed cost. Create an API key, send your first request with curl, and handle credits, errors and idempotent retries.

Source: https://border.bot/developers
Last updated: 2026-10-09

Call the classification and landed-cost engine behind the border.bot dashboard from your checkout, catalogue or shipping software. It is JSON over HTTPS with Bearer API keys and prepaid credits, and you don’t need an SDK.

Base URL: `https://api.border.bot` · [API reference](https://border.bot/docs/api)

## Quickstart

### 1. Create an API key

Sign in to the dashboard and create a key for your workspace. It starts with bb_live_ and is shown once, so store it in your secrets manager straight away.

### 2. Classify a product

Send a description or a product URL with the destination country. Add the origin if you know it.

```bash
curl https://api.border.bot/v1/classify \
  -H "Authorization: Bearer $BORDERBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Heavyweight crew-neck T-shirt, 100% cotton jersey knit",
    "destinationCountry": "US",
    "originCountry": "VN"
  }'
```

### 3. Read the result

You get the code in the destination’s format, the official description at each level, a confidence score, the reasoning, alternatives, and the credits charged with your new balance.

```json
{
  "result": {
    "hsCode": "6109100012",
    "hsCodeFormatted": "6109.10.00.12",
    "nomenclature": "us",
    "confidence": "high",
    "needsReview": false,
    "hierarchy": [
      { "level": "chapter", "code": "61", "description": "Articles of apparel … knitted or crocheted" },
      { "level": "heading", "code": "6109", "description": "T-shirts, singlets, tank tops …" },
      { "level": "subheading", "code": "610910", "description": "Of cotton" }
    ],
    "alternatives": [ … ]
  },
  "credits": { "charged": 1, "balance": 99 }
}
```

### 4. Calculate landed cost

Pass the code, origin, destination, total goods value, currency and shipping cost to the landed-cost endpoint to get every duty, tax and fee line and the total. The API reference has the full request and response schemas.

## Concepts

### Authentication

Send your key in the Authorization header as Bearer bb_live_…. Keys belong to a workspace and only a hash is stored, so a lost key can’t be shown again. Revoke it and create a new one.

### Credits

Each billable call debits the workspace before it runs, in one atomic step, so a balance can never go negative. If the call fails, the credits are refunded automatically. Responses report what was charged and the balance left.

### Safe retries

Send an idempotency key with a request and repeat it as often as you need: you get the original result back and are not charged twice. The API reference documents the header.

### Same engine as the dashboard

The API, the dashboard, the MCP server and the free tools all run on the same classification and duty engine, with the same prices per action.

## Errors

Errors return JSON with a stable machine-readable code and a human-readable message, and the HTTP status that matches the code.

| Code | HTTP status | Meaning |
| --- | --- | --- |
| `invalid_input` | 400 | The request failed validation. The message names the field to fix. |
| `unauthorized` | 401 | The API key is missing, malformed or revoked. |
| `insufficient_credits` | 402 | The workspace balance is too low for this action. Top up in the dashboard. |
| `forbidden` | 403 | The key is valid but not allowed to perform this action (a key without the scope the endpoint needs: details.reason is missing_scope). |
| `not_found` | 404 | The resource or path doesn’t exist. |
| `conflict` | 409 | A request with the same idempotency key is still running, or the change clashes with existing data. Wait and retry. |
| `org_suspended` | 403 | The workspace is suspended. Contact support. |
| `payload_too_large` | 413 | The request body is over 10 MB. Link to a photo instead of sending it inline, or split a bulk run. |
| `version_retired` | 410 | The API version in the path has passed its sunset date. Move to the version the message names. |
| `action_disabled` | 403 | This action is temporarily switched off. Try again later. |
| `unsupported_country` | 422 | The destination isn’t covered for this action yet. The message says what is supported. |
| `rate_limited` | 429 | Too many requests in a short period. Back off and retry. |
| `upstream_error` | 502 | The engine couldn’t complete the request. Credits were refunded; retry. |
| `upstream_timeout` | 504 | The engine took too long. Credits were refunded; retry. |
| `internal` | 500 | Something went wrong on our side. Credits were refunded. |

## Coverage

- US HTS (10-digit)
- Canadian Customs Tariff (10-digit)
- EU Combined Nomenclature / TARIC
- UK Global Tariff (10-digit)
- Harmonized System (6-digit)
- National tariff

Landed cost: United States, United Kingdom, Canada, European Union (all 27 member states). Other destinations are checked when you run a calculation, and you’re told if one isn’t covered yet.

## Prefer an AI assistant?

Connect the [MCP server](https://border.bot/mcp) to use the same engine from Claude, ChatGPT, Codex, Cursor or another MCP client.
