Export Screening API
One screening contract at the edge.
The public API is hosted at
https://exportscreening.datasourceapi.com. CCA Workers
should use a Cloudflare service binding instead of the public
hostname. Both paths execute the same validation, freshness gates,
and deterministic scoring code.
Responses identify the active source release, matching name,
score version, and supporting fields. The service returns
INCOMPLETE with HTTP 503 rather than a false no-match
when a required source is missing, stale, or unavailable.
Public HTTPS
HTTP API
POST/api/v1/screen
Submit a name, exact identifier, or both. Screening inputs are
accepted only in the request body and responses are
private, no-store. Every response includes source
details in data.sources, a summary in
data.freshness, and the
X-Data-Freshness /
X-Data-Verified-At headers.
const response = await fetch(
"https://exportscreening.datasourceapi.com/api/v1/screen",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: "Example Trading Company",
entityType: "organization",
country: "AE",
threshold: 0.82
})
}
);
const envelope = await response.json();
Operational endpoints
GET /api/v1/status- readiness and source age.GET /api/v1/health- health-check alias.GET /api/v1/sources- public-safe source inventory.GET /openapi.json- OpenAPI 3.1 contract.
CCA Workers
Call over a service binding
Add the API Worker as a binding in the calling Worker's
wrangler.jsonc. This keeps traffic on Cloudflare's
network and requires no public DNS hop, API key, or cookies.
{
"services": [
{
"binding": "EXPORT_SCREENING",
"service": "cca-export-control-api"
}
]
}
The fleet-compatible HTTP form uses a synthetic, fully qualified internal URL. The hostname is not routed publicly; the binding dispatches directly to the target Worker.
const response = await env.EXPORT_SCREENING.fetch(
new Request("https://exportscreening.internal/api/v1/screen", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Request-ID": requestId
},
body: JSON.stringify({
name: "Example Trading Company",
country: "AE"
})
})
);
if (response.status !== 200 && response.status !== 503) {
throw new Error(`screening failed: ${response.status}`);
}
const envelope = await response.json();
Preferred internal API
Typed Worker RPC
The default Worker entrypoint exposes screen(input)
and status(). Current Cloudflare Workers can invoke
those methods directly through the same service binding.
const result = await env.EXPORT_SCREENING.screen({
name: "Example Trading Company",
identifiers: [
{ kind: "SWIFT/BIC", value: "EXAMPLE123" }
],
threshold: 0.82,
limit: 20
});
if (result.decision === "INCOMPLETE") {
throw new Error(result.incompleteReasons.join("; "));
}
Cross-repository consumers should use the HTTP binding above,
which wrangler types generates as a
Fetcher and which stays synchronized with OpenAPI.
Direct RPC is appropriate when the consumer imports the target
Worker class or a shared fleet contract so TypeScript can model
Service<ScreeningApi>.
Provenance
Sources and freshness
The initial required source is the International Trade Administration's U.S. Consolidated Screening List. It combines Commerce, State, and Treasury lists including SDN, Entity List, Denied Persons, Unverified List, ITAR Debarred, and related programs.
A scheduled Cloudflare Workflow checks every six hours. Exact raw bytes are stored under immutable SHA-256 R2 keys before parsing. A release becomes visible only after record, alias, and identifier counts reconcile and the source's active-release pointer is changed atomically inside its D1 shard.
Safe interpretation
Decision semantics
-
POTENTIAL_MATCHmeans one or more candidates met the requested threshold and require human review. -
NO_MATCHmeans no candidate met the threshold while every required source was current and queryable. It is not an export authorization. -
INCOMPLETEmeans the service refused to issue a no-match result because required coverage was stale, missing, or unavailable.