Developers

API reference

The public endpoints behind Screening, Search, Sources and the collection pages — the same ones this site calls. Read-only, JSON, no key required for the endpoints below. New to the API? Start with the API guide; machine-readable: openapi.json (OpenAPI 3). For production screening volume and support commitments, see the Screening Licence.

Base URL: https://api.crownintelligence.net. Responses are JSON unless a download format is requested. Every response reflects the compilation's current refresh; there is no separate "as of" parameter — the figure shown is live. The service can apply a per-address request limit (HTTP 429 with Retry-After; see Authentication). Rate limits and volume caps may apply to automated or systematic use; see Terms of use.

POST /api/match/<collection>

Entity matching. Send what you know about a person, company, organization or vessel and get back the closest records in a collection, each with a score from 0 to 1, a match flag and a feature-by-feature explanation of the score. This is the endpoint behind the Screening page. Query bodies are not stored.

ParameterTypeNotes
collectionpathdefault, sanctions, peps, crime or maritime.
limitintegerResults per query, up to 50. Default 5.
thresholdnumberScore from which match is true, 0 to 1. Default 0.75.
algorithmstringstandard (default) or name-only; best means the default. See Algorithms.
topicsstring[]Query string, repeatable: sanction, role.pep, debarment, reg.action.
include_dataset / exclude_datasetstring[]Query string, repeatable: register names to keep or leave out (as in datasets). Several values of one filter are OR-ed; different filters are AND-ed.
queriesobjectBody. Up to 20 named queries, each {"schema": …, "properties": {…}}. A single flat query such as {"schema":"Person","name":"…"} is also accepted and answered as q1.
schemastringPerson, Company, Organization, LegalEntity or Vessel. A record of a different type is penalised (type_mismatch).
properties.namestring[]Names to match. Required unless imoNumber is given.
properties.birthDatestring[]YYYY, YYYY-MM or YYYY-MM-DD.
properties.nationality / countrystring[]Two-letter ISO 3166 codes. Used for a person's nationality, a company's jurisdiction or a vessel's flag.
properties.imoNumberstring[]Seven-digit IMO number for vessels.
Response fieldContents
algorithm, threshold, limit, filtersThe settings that applied
responses.<key>.status, total200, or 400 with error; candidate records compared for that query
results[].score, matchScore from 0 to 1; match is true at 0.75 and above
results[].features[]feature, explanation, score, weight and, for names, matched_name
results[].id, caption, schema, urlRecord ID (use with Entity), primary name, type and the record page
results[].datasets, topics, source, list_type, programmeRegister name, risk topics, short list name, list type and programme
results[].birth_date, nationality, imo, aliasesThe record's own values, for comparison with the query
results[].merged_entity, first_seen, last_seenMerged-entity ID across registers, if any; when the record was first collected and last loaded
checked_atWhen the check ran (UTC)
FeatureWhat it measuresEffect on the score
name_matchWord-by-word alignment of the query name with the record's name and aliases (exact, then close spellings); record words missing from the query lower it slightly.Sets the base score
dob_matchBirth date, at the record's precision.+0.10 match, 0 same year, −0.25 different
country_matchNationality or country code.+0.05 match, −0.10 different
identifier_matchIMO number.At least 0.98 on a match, −0.30 different
type_mismatchThe record is a different entity type from schema.−0.20
curl -X POST "https://api.crownintelligence.net/api/match/default?limit=5" \
  -H "Content-Type: application/json" \
  -d '{"queries":{"q1":{"schema":"Person","properties":{"name":["Jane Example"],"birthDate":["1970"],"nationality":["ca"]}}}}'
import requests

body = {"queries": {"q1": {"schema": "Person", "properties": {
    "name": ["Jane Example"], "birthDate": ["1970"], "nationality": ["ca"]}}}}
r = requests.post("https://api.crownintelligence.net/api/match/default", params={"limit": 5}, json=body)
for hit in r.json()["responses"]["q1"]["results"]:
    print(round(hit["score"] * 100), hit["caption"], hit["source"])
const res = await fetch("https://api.crownintelligence.net/api/match/default?limit=5", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ queries: { q1: { schema: "Vessel",
    properties: { name: ["Example Star"], imoNumber: ["9000000"] } } } }),
});
console.log((await res.json()).responses.q1.results);

A score measures resemblance, not identity. Confirm every match against the publisher's official list before acting on it.

GET /api/algorithms

The scoring methods accepted by algorithm on Match, with each feature and its effect, the name-comparison constants, the default method and threshold, and the topics accepted by topics. See Matching algorithms.

curl "https://api.crownintelligence.net/api/algorithms"

GET /api/catalog

Every collection from the current build index: name, title, version, records, distinct entities, registers, last change, links (page, build index, statistics, and the match, search and reconcile endpoints) and the files with their sizes. Poll it and compare version to know when a collection was rebuilt.

curl "https://api.crownintelligence.net/api/catalog"

GET /api/overview

Headline totals for the whole compilation: active screening records, sanctions, PEPs, debarments, registry counts, nationalities, source-feed totals and the record-type breakdown. This is what powers the figures on the home page.

ParameterTypeNotes
None — the endpoint takes no query parameters.
curl "https://api.crownintelligence.net/api/overview"
import requests

r = requests.get("https://api.crownintelligence.net/api/overview")
print(r.json())
const res = await fetch("https://api.crownintelligence.net/api/overview");
console.log(await res.json());

GET /api/sources

The source register: one row per publisher feed reconciled into the compilation, with publisher, country, list type, cadence and last-run status. Backs the Sources page.

ParameterTypeNotes
qstringFree-text filter across source name, jurisdiction, country and list type.
list_typestringFilter by list type, e.g. SANCTION, PEP, DEBARMENT.
pageinteger1-indexed page number. Default 1.
limitintegerRows per page, up to 100. Default 50.
curl "https://api.crownintelligence.net/api/sources?list_type=SANCTION&limit=25"
import requests

r = requests.get(
    "https://api.crownintelligence.net/api/sources",
    params={"list_type": "SANCTION", "limit": 25},
)
print(r.json())
const url = new URL("https://api.crownintelligence.net/api/sources");
url.searchParams.set("list_type", "SANCTION");
url.searchParams.set("limit", "25");
const res = await fetch(url);
console.log(await res.json());

GET /api/search/<collection>

The same full-text search as /api/search, limited to one collection. Takes every /api/search parameter; results are not scored.

ParameterTypeNotes
collectionpathdefault, sanctions, peps, crime or maritime.
qstringName to search, minimum 2 characters, unless a filter is given.
other—type, list_type, nationality, dob, source, program, sort=first_seen, page, limit, as for /api/search.
curl "https://api.crownintelligence.net/api/search/sanctions?q=Jane+Example&limit=10"
import requests

r = requests.get("https://api.crownintelligence.net/api/search/sanctions", params={"q": "Jane Example", "limit": 10})
print(r.json()["total"])
const url = new URL("https://api.crownintelligence.net/api/search/sanctions");
url.searchParams.set("q", "Jane Example");
const res = await fetch(url);
console.log((await res.json()).results);

GET /api/facets

Counts that break a search down by list type, entity type, nationality (top 30) and source register (top 30). Use it to build filters next to search results. Needs q or at least one filter.

ParameterTypeNotes
qstringName to search, as for /api/search.
list_type, type, nationality, sourcestringFilters, combined with AND.
scopestringCollection: default, sanctions, peps, crime or maritime.
curl "https://api.crownintelligence.net/api/facets?q=Jane+Example&list_type=SANCTION"
import requests

r = requests.get("https://api.crownintelligence.net/api/facets", params={"q": "Jane Example"})
print(r.json()["nationality"])
const res = await fetch("https://api.crownintelligence.net/api/facets?q=Jane+Example");
console.log((await res.json()).source);

GET /api/entity/<id>

A single record by numeric id, as returned by Search or Match: source, register, name, alternate names, programme, list type, entity type, birth date and precision, nationality, IMO number, source link, first and last load, related (the same party in other registers), listings (the record and its related records as nested listings) and merged_entity_url. A merged-entity UUID in the path returns the merged entity: caption, schema, combined properties, registers, topics, referents, and nested listings and records (up to 200). A record no longer active whose merged entity is answers 308 to it. The query forms /api/entity?id= and ?entity_id= still work. Guide: The entities API.

ParameterTypeNotes
idpathRecord id from a Search or Match result (or crown-<id> from the bulk files), or a merged-entity UUID.
nestedbooleanfalse returns the record or merged entity alone.
formatstringftm: the record as a FollowTheMoney entity, as in entities.ftm.json; with nested=true, as in targets.nested.json.
entity_idstringQuery form for a merged-entity UUID (entity_id on a record, merged_entity on a match).
curl "https://api.crownintelligence.net/api/entity/379781867"
import requests

r = requests.get("https://api.crownintelligence.net/api/entity/379781867")
print(r.json()["listings"])
const res = await fetch("https://api.crownintelligence.net/api/entity/379781867");
console.log(await res.json());

GET /api/source

One source register in detail: its register entry (publisher, country, list type, status, last run), record and distinct-entity totals, first and last load, and breakdowns by entity type, country (top 60) and programme (top 50), plus its 15 most recently added records.

ParameterTypeNotes
namestringRegister name exactly as returned by /api/sources. Required.
curl "https://api.crownintelligence.net/api/source?name=OFAC%20SDN"
import requests

r = requests.get("https://api.crownintelligence.net/api/source", params={"name": "OFAC SDN"})
print(r.json()["records"])
const url = new URL("https://api.crownintelligence.net/api/source");
url.searchParams.set("name", "OFAC SDN");
console.log(await (await fetch(url)).json());

GET /api/countries

Every nationality present in active records, with a record count and a distinct-source count per nationality. Takes no parameters.

ParameterTypeNotes
None — the endpoint takes no query parameters.
curl "https://api.crownintelligence.net/api/countries"
import requests

r = requests.get("https://api.crownintelligence.net/api/countries")
print(r.json())
const res = await fetch("https://api.crownintelligence.net/api/countries");
console.log(await res.json());

GET POST /api/reconcile/<collection>

A reconciliation service for OpenRefine (Reconciliation API 0.2). Add https://api.crownintelligence.net/api/reconcile/default as a standard service in OpenRefine to match a column of names against a collection. Without queries it returns the service manifest; with them it scores each query using the same matcher as /api/match.

ParameterTypeNotes
collectionpathdefault, sanctions, peps, crime or maritime.
queriesJSONQuery string (GET) or form/JSON body (POST). Up to 20 queries: {"q0":{"query":"Jane Example","type":"Person","limit":5,"properties":[{"pid":"birthDate","v":"1970"}]}}. Property ids are those of /api/match.
responseobjectFor each query key, result: a list of candidates with id, name, score (0–100), match and type. id opens at /estate/record.html?id=.
curl -G "https://api.crownintelligence.net/api/reconcile/default" --data-urlencode 'queries={"q0":{"query":"Jane Example","type":"Person"}}'
import json, requests

q = {"q0": {"query": "Jane Example", "type": "Person"}}
r = requests.post("https://api.crownintelligence.net/api/reconcile/default", data={"queries": json.dumps(q)})
print(r.json()["q0"]["result"])
const res = await fetch("https://api.crownintelligence.net/api/reconcile/default", {
  method: "POST",
  body: new URLSearchParams({ queries: JSON.stringify({ q0: { query: "Jane Example", type: "Person" } }) }),
});
console.log(await res.json());

GET /api/programs

Sanctions and other programs grouped across active records, with the record count, distinct source-list count and the names of the contributing lists for each program.

ParameterTypeNotes
qstringFree-text filter on program name or source list name.
pageinteger1-indexed page number. Default 1.
limitintegerRows per page, up to 100. Default 50.
curl "https://api.crownintelligence.net/api/programs?q=Magnitsky"
import requests

r = requests.get(
    "https://api.crownintelligence.net/api/programs",
    params={"q": "Magnitsky"},
)
print(r.json())
const url = new URL("https://api.crownintelligence.net/api/programs");
url.searchParams.set("q", "Magnitsky");
const res = await fetch(url);
console.log(await res.json());

GET /api/collection

Summary totals for one collection type — sanctions, PEPs or debarments — with an optional scope narrowing to a specific angle such as maritime or company records within that type.

ParameterTypeNotes
typestringOne of SANCTION, PEP, DEBARMENT. Required.
scopestringOptional narrowing, e.g. sanctions, peps, crime, maritime, kyb, securities.
curl "https://api.crownintelligence.net/api/collection?type=SANCTION"
import requests

r = requests.get(
    "https://api.crownintelligence.net/api/collection",
    params={"type": "SANCTION"},
)
print(r.json())
const url = new URL("https://api.crownintelligence.net/api/collection");
url.searchParams.set("type", "SANCTION");
const res = await fetch(url);
console.log(await res.json());

GET /api/export

Streams a free download of one register's active records as CSV or newline-delimited JSON, for registers Crown has cleared for direct download. Registers not cleared for download return an error explaining that the register is available for licensed use instead.

ParameterTypeNotes
sourcestringExact register name, as shown on its Sources page row. Required.
formatstringcsv or jsonl. Default csv.
curl "https://api.crownintelligence.net/api/export?source=OFAC%20SDN&format=csv" -o ofac-sdn.csv
import requests

r = requests.get(
    "https://api.crownintelligence.net/api/export",
    params={"source": "OFAC SDN", "format": "csv"},
)
with open("ofac-sdn.csv", "wb") as f:
    f.write(r.content)
import { writeFile } from "node:fs/promises";

const url = new URL("https://api.crownintelligence.net/api/export");
url.searchParams.set("source", "OFAC SDN");
url.searchParams.set("format", "csv");
const res = await fetch(url);
await writeFile("ofac-sdn.csv", Buffer.from(await res.arrayBuffer()));

GET /downloads/collections/<collection>/<file>

Bulk files for each collection (default, sanctions, peps, crime or maritime), rebuilt after every refresh and kept at the same address. index.json lists every file with its size, row count and SHA-256 checksum, with the collection's figures, version and last change. Formats, columns and delta updates are described in Using the bulk data.

FileContents
index.jsonBuild index: version, figures and every file with checksum
targets.simple.csvOne row per record, flat table
targets.nested.jsonEach record with sanction details nested, one per line
entities.ftm.jsonFollowTheMoney entities, one per line
senzing.jsonSenzing records, one per line
statements.csvOne row per property value
names.txtEvery distinct name and alias
delta.jsonADD, MOD and DEL operations since the previous build
curl -O "https://api.crownintelligence.net/downloads/collections/sanctions/index.json"
curl -O "https://api.crownintelligence.net/downloads/collections/sanctions/targets.simple.csv"
import requests

idx = requests.get("https://api.crownintelligence.net/downloads/collections/sanctions/index.json").json()
for f in idx["files"]:
    print(f["name"], f["rows"], f["sha256"])
const idx = await (await fetch("https://api.crownintelligence.net/downloads/collections/sanctions/index.json")).json();
console.log(idx.version, idx.files.map(f => f.name));

How this data is collected and refreshed →

Need production screening volume?