# Check a declared country of origin (POST /v1/origin/validate)

> POST /v1/origin/validate: Check a declared country of origin. border.bot API reference (Origin).

Source: https://border.bot/docs/api/validate-origin

> Documentation index: https://border.bot/llms.txt. Every page is Markdown at its URL + `.md`.

`POST https://api.border.bot/v1/origin/validate`

Requires an API key (`Authorization: Bearer bb_live_…`).

How believable a declared origin is, given everything else known about the product: the share of the evidence pointing elsewhere (`probabilityOfMisrepresentation`), a verdict, the likely origin, and the reasons in words. With no evidence either way the verdict is `unknown`, never a guess. `needsReview` flags it when the misrepresentation probability reaches `reviewThreshold` (the request’s, else the workspace’s setting, else the platform default of 0.3), or when there is no evidence.

API key scope: `origin`.

## Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `idempotency-key` | string | no | Make retries safe: a repeat with the same key returns the original result without charging again (keys are scoped to your workspace). |

## Request body (JSON)

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `productUrl` | string | no | Product page URL: its structured data and “Made in …” text are read first. |
| `imageUrl` | string | no | Product photo (JPEG, PNG, WebP or GIF, up to 6 MB), as an http(s) URL or a base64 data URL: a visible “Made in …” label is strong evidence. |
| `description` | string | no | Product description. |
| `title` | string | no | Product name. |
| `brand` | string | no | Brand. |
| `sku` | string | no | Your SKU (kept with the result). |
| `gtin` | string | no | Barcode (GTIN, UPC, EAN). Its GS1 prefix shows where the brand registered: a weak hint, never proof. |
| `material` | string | no | Main materials. |
| `categories` | string[] | no | Category path, broadest first. |
| `price` | number | no | Selling price, in `currency`. |
| `currency` | string | no | ISO 4217 currency of `price`. |
| `shipFromCountry` | string | no | Country the goods ship from (often, not always, where they are made). ISO 3166-1 alpha-2, case-insensitive. |
| `reviewThreshold` | number | no | When `needsReview` is set (0–1). Inferring: an answer below this probability. Validating: a declaration whose `probabilityOfMisrepresentation` is at or above it. Without it, the workspace’s setting (dashboard → Settings → Origin review) applies, then the platform default (0.8 to infer, 0.3 to validate). |
| `declaredOrigin` | string | yes | The country of origin declared (by a supplier, a listing, a customs entry). ISO 3166-1 alpha-2, case-insensitive. |

## Responses

- `200`: The verdict on the declared origin, with reasons. (`ValidateOriginResponse`)
- `400`: Invalid input (`invalid_input`). (`Error`)
- `401`: Missing, invalid, revoked or expired API key (`unauthorized`). (`Error`)
- `402`: Not enough credits (`insufficient_credits`). Nothing was charged. (`Error`)
- `403`: Workspace suspended, action disabled, or the key lacks the scope (`org_suspended`, `action_disabled`, `forbidden`). (`Error`)
- `409`: A request with this Idempotency-Key is still in progress (`conflict`). (`Error`)
- `429`: Rate limited (`rate_limited`). Retry after `Retry-After` seconds; `RateLimit` says which limit was hit (`r=0`, `t` seconds until its window ends) and `RateLimit-Policy` its quota. (`Error`)
- `500`: Unexpected error (`internal`). (`Error`)
- `502`: The engine failed (`upstream_error`). The credits are refunded automatically. (`Error`)
- `504`: The engine timed out (`upstream_timeout`). The credits are refunded automatically. (`Error`)

## Example

```bash
curl -X POST 'https://api.border.bot/v1/origin/validate' \
  -H 'Authorization: Bearer bb_live_...' \
  -H 'Content-Type: application/json' \
  -d '{"declaredOrigin":"US","title":"Wireless earbuds","description":"Bluetooth 5.3. Made in China."}'
```
