One endpoint, four official lists
Bring 28,242 sanctions and export-control entries from US OFAC, the UN, the EU and China MOFCOM into your own ERP, risk or KYC systems. Send a name; get back whether it matched, which entries it matched, and a link to the official record you can open and verify.
Four sources, four formats: OFAC ships CSV, the UN ships XML, the EU has its own database, and China MOFCOM has no API at all — only announcement web pages.
And the lists move daily — our last OFAC refresh came back 97 entries lighter (delistings must be synced too, or you produce false positives).
That maintenance cost is ongoing, not one-off.
The API requires the API plan (US$19.9/mo, includes everything in membership).
Sign in, open the Membership tab to subscribe, then create a key under API keys. Keys look like tp_xxxxxxxx.
The plaintext key is shown only once, at creation — put it into your secret manager right away.
curl -H "Authorization: Bearer tp_YOUR_KEY" "https://tradeprotected.com/api/v1/screen?name=GAZPROM"
{
"matched": true,
"count": 2,
"rows": [
{
"source": "OFAC",
"name": "GAZPROM NEFT",
"type": "entity",
"programs": "RUSSIA-EO14024",
"listed_on": "2022-02-24",
"url": "https://sanctionssearch.ofac.treas.gov/..."
}
]
}
matched is a boolean you can branch on directly; rows[].url points at the official record — file it as your verification evidence.
Screen a single name. Parameter name (required, max 200 characters). A 7-digit number is treated as a vessel IMO and matched exactly.
Batch screening, up to 100 names per call. Handy for checking buyer, seller, shipowner and consignee in one go before an order.
Browse or bulk-pull the lists, for keeping your own copy in sync. Parameters: q keyword, source, type, limit (default 100, max 500), offset.
Entry counts and last-updated time per source. A sync job can check this first and skip a full pull when nothing changed.
name | Name to screen, or a 7-digit IMO. Required for GET /screen |
|---|---|
names | Array of names for batch screening, in the POST body, max 100 |
source | OFAC / UN / EU / EUX / CN; empty means all |
type | entity / individual / vessel / aircraft |
format | json (default) / xlsx (Excel) / csv / ndjson |
limit | Rows per page, default 100, max 500 |
offset | Offset, used with limit for paging |
Same data, three ways to consume it, ordered by how much code you have to write:
Paste the snippet below into any page of your corporate site and a sanctions search box appears, backed by our database and plain enough to blend into your layout. A good fit for forwarders, law firms and associations offering clients a self-service check.
<iframe src="https://tradeprotected.com/embed?key=tp_YOUR_KEY&lang=en"
style="width:100%;height:420px;border:1px solid #e4eaf1;border-radius:12px"
loading="lazy"></iframe>
A key inside embed code is publicly visible — anyone viewing your page source can read it. So set the allowed domains for that key under Membership → API keys (e.g. yourcompany.com); even if the key is copied, it will not work on another site. This is the same approach front-end keys like Google Maps use.
We recommend separate keys for embedding and for server-side calls: lock the embed key to your domain, and keep the server key unlocked but only on your server. One account can hold five keys at a time, which is enough to split by environment.
Add the format parameter — every query endpoint supports it.
?format=xlsx. A real .xlsx file with bilingual headers, tuned column widths and a bold dark header row: double-click and it goes straight into the report annex, no reformatting.?format=csv. Includes a UTF-8 BOM so Excel opens non-Latin text correctly; convenient for scripts.?format=ndjson. One independent JSON object per line, suited to streaming pipelines — a full pull never has to be held in memory at once.matched and count summary fields for programmatic decisions.# export the China MOFCOM list to Excel
curl -H "Authorization: Bearer tp_YOUR_KEY" "https://tradeprotected.com/api/v1/sanctions?source=CN&limit=500&format=xlsx" -o cn-list.xlsx
# save a single screening result as a spreadsheet for your audit file
curl -H "Authorization: Bearer tp_YOUR_KEY" "https://tradeprotected.com/api/v1/screen?name=GAZPROM&format=xlsx" -o gazprom.xlsx
# look up a vessel by IMO
curl -H "Authorization: Bearer tp_YOUR_KEY" "https://tradeprotected.com/api/v1/screen?name=9209508"
import requests
KEY = "tp_YOUR_KEY"
r = requests.get(
"https://tradeprotected.com/api/v1/screen",
params={"name": "GAZPROM"},
headers={"Authorization": "Bearer " + KEY},
timeout=20,
)
r.raise_for_status()
data = r.json()
if data["matched"]:
print("MATCH", data["count"], "hit(s) — needs manual review")
for row in data["rows"]:
print(row["source"], row["name"], row["url"])
const KEY = process.env.TP_API_KEY;
async function screen(name) {
const url = new URL("https://tradeprotected.com/api/v1/screen");
url.searchParams.set("name", name);
const r = await fetch(url, { headers: { authorization: "Bearer " + KEY } });
if (!r.ok) throw new Error("screen failed: " + r.status);
return r.json();
}
const out = await screen("SOVCOMFLOT");
console.log(out.matched ? "MATCH " + out.count : "clear");
names = ["GAZPROM", "ACSL", "SOVCOMFLOT"]
r = requests.post(
"https://tradeprotected.com/api/v1/screen",
json={"names": names},
headers={"Authorization": "Bearer " + KEY},
timeout=60,
)
for item in r.json()["results"]:
flag = "MATCH" if item["matched"] else "clear"
print(flag, item["query"], item["count"])
1000 calls per key per day, resetting at 00:00 UTC. Every response carries these two headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
An account can hold up to five active keys. Splitting them by environment (production / staging / a specific colleague) means you can revoke one without disturbing the other callers.
Errors always return {"error":{"code":"...","message":"..."}}. Branch on code, not on the message text.
| 401 | missing_key no key supplied · invalid_key key invalid or revoked |
|---|---|
| 403 | membership_required not subscribed or expired — keys stop working the moment the plan lapses and resume on renewal, no need to reissue |
| 429 | quota_exceeded daily allowance used up |
| 400 | missing_name / name_too_long / too_many_names parameter problems |
Matching is normalised substring and phrase matching, so a hit is a due-diligence signal, not a legal conclusion. Namesakes and transliteration differences can produce false positives and false negatives; make the final call against the official record at url.
The API plan includes everything in membership, plus the data API, the embeddable widget and Excel export.
Comparable screening APIs are typically annual contracts starting in the thousands of dollars. Ours is monthly and cancellable any time. Run a few queries free and judge the data before committing.