API Documentation for Sanctions Screening
The OfacScanner API v1 is a JSON REST API that screens names, runs batches, adds records to monitoring and reports list versions. You authenticate with a Bearer key, retry safely with an Idempotency-Key and receive signed webhooks.
What the OfacScanner API does
The API lets your own systems run the same screening as the OfacScanner console. Call it when a user signs up, before a payout or a wire leaves, or when a shipment is booked. Every call is matched against the current version of each list in your plan, and the answer tells you which version was used so you can keep it as evidence.
All requests go to https://ofacscanner.com/api/v1 over HTTPS, take JSON bodies and return JSON. Times are ISO 8601 in UTC. Live keys work on the Scale and Enterprise plans, and sandbox keys work on every account. Read the overview of real time sanctions screening for integration patterns.
Authentication with Bearer keys
Create keys in the app under Developers. Send the key in the Authorization header as Bearer ofs_live_... for live calls or Bearer ofs_test_... for the sandbox. A key is shown once and stored only as a hash, so keep it in your secret store.
Sandbox keys return the same deterministic answer for the same input and never use checks. Live keys screen against real list data and count each screening as one check in your billing period.
Safe retries with Idempotency-Key
Add an Idempotency-Key header of up to 191 characters to any POST call. If a network error hides the answer, send the same request again with the same key. Within 24 hours you get the saved response with the header Idempotent-Replayed: true, and no second check is used.
The same key with a different body returns 422 idempotency_conflict, and a call still running under that key returns 409 idempotency_in_progress. A good key is your own customer or payment id plus the action, such as onboarding-cus-1042.
/api/v1/screen
Screen one name
Screens one person, company, vessel or aircraft against every list your plan covers and returns the risk rating, the top candidates and the list versions used. Add monitor true to keep watching the subject after this call.
| Field | Description |
|---|---|
namestring, required |
Full name, 2 to 500 characters. Any script works, transliteration is automatic. |
typestring |
any, person, individual, organization, company, vessel or aircraft. Default any. |
countrystring |
Country of residence, nationality or registration. Raises the score when it fits. |
dobstring |
Date of birth such as 1971-04-12 or a year. Lowers the score when it does not fit. |
referencestring |
Your own id for the customer or payment, returned in results and webhooks. |
identifiersarray of strings |
Up to 10 identifiers such as passport, IMO or tax numbers. |
sensitivitystring |
strict (95), balanced (85) or broad (75). Default is your workspace threshold. |
monitorboolean |
Also add the subject to ongoing monitoring. Needs monitoring in your plan. |
Request
curl https://ofacscanner.com/api/v1/screen \
-H "Authorization: Bearer ofs_live_your_key" \
-H "Idempotency-Key: onboarding-cus-1042" \
-H "Content-Type: application/json" \
-d '{
"name": "Northwind Freight Ltd",
"type": "organization",
"country": "Panama",
"reference": "cus_1042",
"monitor": true
}'
Response
{
"object": "screening",
"id": "scr_8Kf2xQ7wLm",
"livemode": true,
"channel": "api",
"reference": "cus_1042",
"query": { "name": "Northwind Freight Ltd", "type": "organization", "country": "Panama" },
"result": "clear",
"risk_rating": "clear",
"top_score": 41.2,
"threshold": 85,
"sensitivity": "balanced",
"matches_count": 0,
"matches": [],
"list_versions": [
{ "list": "ofac_sdn", "version_id": 1, "published_at": "2026-10-09T00:00:00+00:00" },
{ "list": "ofac_cons", "version_id": 2, "published_at": "2026-09-14T00:00:00+00:00" }
],
"monitoring": { "record_id": 881, "status": "active" },
"duration_ms": 84,
"created_at": "2026-10-11T09:14:03+00:00"
}
/api/v1/screenings/{id}
Retrieve a screening
Returns a screening from your workspace by its id, with the same fields as the screen call. Use it to rebuild evidence or to show a past result in your own back office.
| Field | Description |
|---|---|
idpath |
The id returned by POST /screen, a batch result or a webhook. |
Request
curl https://ofacscanner.com/api/v1/screenings/scr_8Kf2xQ7wLm \
-H "Authorization: Bearer ofs_live_your_key"
Response
{
"object": "screening",
"id": "scr_8Kf2xQ7wLm",
"result": "clear",
"risk_rating": "clear",
"top_score": 41.2,
"list_versions": [ ... ],
"evidence_hash": "9f2c..."
}
/api/v1/batch
Screen a batch
Queues up to 10,000 records in one call and answers with 202 at once. Poll GET /batch/{id} or listen for the batch.completed webhook. Each record counts as one check. For larger files use CSV upload in the app, up to 100,000 rows per file.
| Field | Description |
|---|---|
recordsarray, required |
1 to 10,000 objects with the same fields as POST /screen. |
monitorboolean |
Add every record to ongoing monitoring. |
open_casesboolean |
Open a case for each possible match. Default true. |
sensitivitystring |
strict, balanced or broad for the whole batch. |
Request
curl https://ofacscanner.com/api/v1/batch \
-H "Authorization: Bearer ofs_live_your_key" \
-H "Idempotency-Key: payouts-2026-10-11" \
-H "Content-Type: application/json" \
-d '{
"records": [
{ "name": "Maria Lopez", "type": "person", "dob": "1988", "reference": "sel_77" },
{ "name": "Example Vessel Star", "type": "vessel", "reference": "shp_3" }
],
"monitor": true
}'
Response
{
"object": "batch",
"id": 57,
"status": "pending",
"rows": 2,
"processed": 0,
"clear": 0,
"review": 0,
"match": 0,
"skipped": 0,
"livemode": true,
"results_url": "https://ofacscanner.com/api/v1/batch/57"
}
/api/v1/monitor
Add a record to monitoring
Saves a subject for ongoing monitoring. After every list update OfacScanner re-screens it against the new entries and sends a monitoring.alert webhook when it now matches. Re-screening does not use your monthly checks.
| Field | Description |
|---|---|
name and the other fieldssame as POST /screen |
Send the same subject data you would screen. |
Request
curl https://ofacscanner.com/api/v1/monitor \
-H "Authorization: Bearer ofs_live_your_key" \
-H "Content-Type: application/json" \
-d '{ "name": "Northwind Freight Ltd", "type": "organization", "reference": "cus_1042" }'
Response
{
"object": "monitored_record",
"id": 881,
"livemode": true,
"status": "active",
"name": "Northwind Freight Ltd",
"reference": "cus_1042",
"last_result": "clear",
"last_top_score": 41.2,
"last_screening_id": "scr_8Kf2xQ7wLm",
"created_at": "2026-10-11T09:14:03+00:00"
}
/api/v1/lists
List sources and versions
Returns every list with its issuing authority, official source, current version, publish date, the time of our last check and whether your plan includes it.
Request
curl https://ofacscanner.com/api/v1/lists \
-H "Authorization: Bearer ofs_live_your_key"
Response
{
"object": "list",
"data": [
{
"list": "ofac_sdn",
"name": "OFAC Specially Designated Nationals and Blocked Persons List",
"authority": "Office of Foreign Assets Control, U.S. Department of the Treasury",
"jurisdiction": "US",
"source_url": "https://sanctionslist.ofac.treas.gov/",
"included_in_plan": true,
"version_id": 1,
"published_at": "2026-10-09T00:00:00+00:00",
"checked_at": "2026-10-11T09:01:32+00:00",
"entries": 19416
}
]
}
Errors and rate limits
Errors return a JSON body with a machine readable type and a human message, for example {"error": {"type": "plan_required", "message": "..."}}. Validation errors add a fields object.
| Status | Type | When it happens |
|---|---|---|
| 400 | invalid_request_error |
The Idempotency-Key is longer than 191 characters. |
| 401 | authentication_error |
The Bearer key is missing, malformed or revoked. |
| 402 | usage_limit_reached |
No checks left in this billing period. Checks reset with the next period or right after an upgrade. |
| 403 | plan_required |
A live key on a plan without the API, batch or monitoring feature. |
| 404 | not_found |
The id does not exist in your workspace. |
| 409 | idempotency_in_progress |
A request with the same Idempotency-Key is still running. |
| 422 | invalid_request_error or idempotency_conflict |
A field failed validation, or the Idempotency-Key was used with a different body. |
| 429 | rate limit |
More than 600 requests a minute on a live key, or 120 on a sandbox key. |
Webhooks signed with HMAC
Add an endpoint URL in the app and choose its events: screening.completed, batch.completed, case.created and monitoring.alert. Webhooks are part of Growth and higher. Each delivery is a POST with a JSON event and the header OfacScanner-Signature: t=<unix time>,v1=<signature>.
The signature is HMAC SHA-256 of the timestamp, a dot and the raw body, keyed with the endpoint secret. Compute it yourself, compare in constant time and reject events older than 5 minutes. Answer with any 2xx status. Failed deliveries are retried, and the event id lets you ignore a repeat. See how alerts fit ongoing sanctions monitoring.
Event body
{
"id": "evt_01JA9Q3Y7D2K8M4N6P0R2S4T6V",
"type": "monitoring.alert",
"created": "2026-10-11T09:31:12+00:00",
"livemode": true,
"data": {
"object": "monitoring_alert",
"id": 412,
"reason": "new_match",
"result": "likely",
"top_score": 93.5,
"record": { "id": 881, "name": "Northwind Freight Ltd", "reference": "cus_1042" },
"screening_id": "scr_9Hd3kP2vQa",
"case_id": 57,
"list": "ofac_sdn",
"list_version_id": 8,
"list_published_at": "2026-10-11T00:00:00+00:00",
"created_at": "2026-10-11T09:31:12+00:00"
}
}
Verify the signature in Python
import hmac, hashlib, time
def verify(secret: str, raw_body: bytes, header: str) -> bool:
parts = dict(p.split('=', 1) for p in header.split(','))
t, sig = parts['t'], parts['v1']
if abs(time.time() - int(t)) > 300:
return False
expected = hmac.new(secret.encode(), f'{t}.'.encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, sig)
API questions
Another question? Write to [email protected].
Which plan includes the API?
Does a sandbox call use my monthly checks?
How fast is a screening call?
Can I retry a request safely?
How do I know which list version a result used?
Test the API with a sandbox key
Create an account, add a sandbox key under Developers and send your first request. Move to Scale when you are ready for live screening.
Results support your compliance decisions, and the final decision stays with your team. OfacScanner is not affiliated with OFAC or the U.S. Department of the Treasury.