Python SDK for the OpenSanctions API and on-premise yente instances.
Full documentation, including the tutorial and API reference, lives at yenteclient.followthemoney.tech.
pip install yente-client # SDK only
pip install 'yente-client[cli]' # SDK + `yente-cli` command-line tool
pip install 'yente-client[mcp]' # SDK + `yente-mcp` server for LLM agentsPython 3.11+; runtime deps are pydantic and httpx. The [cli] extra
adds typer and rich; the [mcp] extra adds fastmcp. The
MCP server exposes the
matching surface to LLM agents over the Model Context Protocol.
from yente_client import Client, Person
with Client(api_key="...", app_name="MyScreeningApp") as c:
hits = c.match(
Person(firstName="Aleksandr", lastName="Zacharov", birthDate="1965"),
datasets=["sanctions"],
threshold=0.7,
)
if hits.top is not None:
print(hits.top.caption, hits.top.score)
for match in hits.matches:
print(match.id, match.properties.get("topics", []))The API key can be generated at
opensanctions.org/account. It's
read in this example from the OPENSANCTIONS_API_KEY env var if you skip
passing api_key=. To target a yente instance, pass base_url= (no key needed).
# Free-text search
res = c.search("acme", datasets=["default"], schema="Company")
# Fetch one entity by ID; nested=True (default) inlines adjacent entities
entity = c.fetch("NK-aU5ybkbRFJucf8YMwsJvDw")
for sanction in entity.properties.get("sanctions", []):
print(sanction.properties["authority"])
# Operational endpoints
c.datasets() # available datasets and freshness
c.programs() # sanctions-program catalog (resolves programId codes)
c.algorithms() # enabled matching algorithms
c.healthz() # livenessThe package ships generated classes for every FtM schema (Person, Company,
Vessel, Organization, …). All take typed list[str] properties; a single
string is coerced to a one-element list. Unknown properties raise
pydantic.ValidationError at construction.
from yente_client import Person, Company
p = Person(firstName="Aleksandr", lastName="Zacharov", country="ru")
c = Company(name="Acme LLC", jurisdiction="us")
Person(birth_date="1965") # ValidationError — snake_case isn't aliased
Person(notARealProp="X") # ValidationError — extra="forbid"Client accepts:
| Kwarg | Default | Notes |
|---|---|---|
api_key |
None |
Sent as Authorization: ApiKey <key>. |
base_url |
https://api.opensanctions.org |
Override for a yente instance or staging. |
app_name |
None |
Identifier added to the User-Agent comment. |
user_agent |
None |
Full override; bypasses the assembled UA. |
timeout |
30s read, 10s connect |
Pass an httpx.Timeout(...) for fine control. |
verify |
True |
SSL verification; pass a CA bundle path or False. |
proxy |
None |
Forwarded to httpx.Client(proxy=...). |
headers |
None |
Merged onto every request; Authorization and User-Agent win. |
transport |
None |
Custom httpx.BaseTransport (e.g. MockTransport for tests). |
pip install yente-client[cli] ships a yente-cli binary that mirrors the SDK:
export OPENSANCTIONS_API_KEY=sk_... # or pass --api-key
# Screen a known entity (KYC / sanctions checks):
yente-cli match -s Person -p firstName=Aleksandr -p lastName=Zacharov -d sanctions
# Free-text discovery by name:
yente-cli search "acme" -d default -s Company
# Fetch one entity (id from match/search):
yente-cli fetch NK-aU5ybkbRFJucf8YMwsJvDw
# Discover the data model (offline, no API key):
yente-cli ref schemas # all schemas with matchable flags
yente-cli ref schema Person -f json # full property list, types, deprecation
yente-cli ref topics # the Topic enum
yente-cli ref countries # country codes the server speaks
# Discover server state:
yente-cli status # client + server + auth + loaded datasets
yente-cli datasets # full per-source dataset list
yente-cli programs # sanctions programs behind programId codes
yente-cli algorithms # enabled algorithms, default + bestOutput formats: -f table (default on TTY), -f json (pretty, default when piped),
-f jsonl (one item per line, ideal for jq and LLM pipelines).
search vs match: use match for any matching task, even with partial
input (a name, name + country, …) — it returns scored, ranked candidates.
search is for user-facing search UIs (a search box or autocomplete a human
types into), not a fallback for match on sparse input.
Exit codes:
0≥1 result1zero results (lets shell scripts gate on&&)2usage error (bad flag, unknown schema/property)3API error (4xx, 5xx)4network/transport error
Designed for LLM agents: every command's --help carries worked examples and
documented JSON output shapes; unknown schema/property names get fuzzy
suggestions ("Did you mean birthDate?"). Run yente-cli --help first.
Every non-2xx response raises a subclass of YenteError:
BadRequestError(400)AuthenticationError(401, 403)NotFoundError(404)RateLimitError(429, with.retry_afterwhen set)ServerError(5xx)APIError(other; carries.status_codeand.detail)TransportError(network failure before the request reached the server)
Retries are not built in — failed requests raise; callers handle backoff.