API Reference
Screen names against the OFAC SDN list. Every response carries a confidence score, a recommended action, and an Ed25519-signed receipt you can verify offline.
Introduction
The Sigeel API is a REST API that screens individual and entity names against the US Treasury OFAC Specially Designated Nationals (SDN) list. It returns ranked matches with a 0–100 confidence score, a recommended action, and a cryptographically signed receipt — so every lookup becomes an audit artifact.
Base URL
https://api.sigeel.com
Content type
application/json
Data source
OFAC SDN · rebuilt monthly
Typical latency
~50–150 ms warm
Authentication
Authenticate every request with your API key in the X-API-Key header. Keys are prefixed sk_live_ for production and sk_test_ for sandbox.
X-API-Key: sk_live_your_api_key_here
Never expose your key in client-side code. Keys grant full access to your account's quota. If a key is compromised, rotate it immediately from your dashboard — old keys are revoked instantly.
Rate limits
Limits are applied per API key. When you exceed your limit the API returns 429 Too Many Requests with a Retry-After header (seconds).
| Tier | Monthly quota | Rate limit | Overage |
|---|---|---|---|
| Free | 100 | 5 / min | Blocked |
| Starter | 1,000 | 30 / min | $0.01 / call |
| Pro | 10,000 | 100 / min | $0.01 / call |
| Ultra | 50,000 | 300 / min | $0.01 / call |
| Enterprise | 250,000 | 600 / min | $0.01 / call |
Quickstart
One request. One response. Signed and verifiable.
curl -X POST https://api.sigeel.com/screen \
-H "X-API-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{"name": "Victor Bout", "min_score": 70}'
/screen
Screen a name against the OFAC SDN list. Returns ranked matches with scores, recommended actions, and a signed receipt.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | required | The name to screen. 2–500 chars. Any language. Diacritics, inverted order, and punctuation are normalized automatically. |
min_score |
number | optional | Return only matches with score ≥ this value. Range 0–100. Default 50. |
limit |
integer | optional | Max matches returned. Range 1–50. Default 10. |
entity_type |
string | optional | Filter by "individual", "entity", or "vessel". Default: all. |
Example request
curl -X POST https://api.sigeel.com/screen \
-H "X-API-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Victor Bout",
"min_score": 70,
"limit": 5
}'
Example response 200 OK
{
"body": {
"query": "Victor Bout",
"normalized_query": "victor bout",
"match_count": 1,
"matches": [{
"score": 93.1,
"primary_name": "BOUT, Viktor Anatoljevitch",
"matched_name": "viktor anatoljevitch bout",
"matched_on": "primary",
"entity_type": "individual",
"sdn_id": "12345",
"programs": ["SDGT", "UKRAINE-EO13662"],
"recommended_action": "manual_review",
"aliases": [
"BOUT, Victor",
"BUTT, Viktor",
"BOUT, Viktor Anatolyevich"
]
}],
"list": {
"source": "OFAC SDN",
"entity_count": 19457,
"variant_count": 44074,
"built_at": "2026-10-01T00:00:00Z"
},
"usage": {
"month_to_date": 142,
"quota": 10000,
"overage": 0
}
},
"signature": {
"alg": "Ed25519",
"key_id": "pk_2026_10",
"public_key_b64": "MCowBQYDK2VwAyEA…",
"signature_b64": "9f2a…",
"signed_at": "2026-10-19T14:32:01Z"
}
}
Response fields
| Field | Type | Description |
|---|---|---|
body.query | string | The original name as submitted. |
body.normalized_query | string | Normalized form used for matching (lowercase, diacritics stripped, punctuation removed). |
body.match_count | integer | Number of matches in this response. |
body.matches | array | Array of Match objects, ranked by score descending. |
body.list | object | Metadata about the SDN list build used for this screening. |
body.usage | object | Quota usage: month_to_date, quota, overage. |
signature | object | Ed25519 signature over canonical JSON of body. See verification. |
/pubkey
Returns the current Ed25519 public key used to sign responses. Use this to verify any receipt offline. Public — no auth required.
{
"alg": "Ed25519",
"key_id": "pk_2026_10",
"public_key_b64": "MCowBQYDK2VwAyEA3x8Z...",
"valid_from": "2026-10-01T00:00:00Z",
"rotates_at": "2027-01-01T00:00:00Z"
}
Key rotation happens quarterly. Old keys remain valid for verification of previously-signed receipts. Match key_id from a receipt to select the right key.
/health
Liveness and readiness check. Public — no auth required.
{
"status": "ok",
"list_loaded": true,
"entity_count": 19457,
"list_built_at": "2026-10-01T00:00:00Z",
"uptime_s": 1843221
}
Match object
Each item in body.matches is a Match object.
| Field | Type | Description |
|---|---|---|
score | number | 0–100 confidence. See interpretation. |
primary_name | string | The primary name on the SDN record, in OFAC's official format. |
matched_name | string | The exact alias or primary name that produced this match (normalized). |
matched_on | string | "primary" or "alias". |
entity_type | string | "individual", "entity", or "vessel". |
sdn_id | string | OFAC SDN number. Use to cross-reference with Treasury's own records. |
programs | string[] | Sanctions programs (e.g. "SDGT", "UKRAINE-EO13662"). |
recommended_action | string | "escalate", "manual_review", or "clear". |
aliases | string[] | All known aliases for this SDN record. |
Score interpretation
Scores are calibrated so you can act on them consistently. The recommended_action field encodes the same thresholds so you don't have to hard-code them.
| Score | Recommended action | Meaning |
|---|---|---|
| 95 – 100 | escalate | Strong match. Treat as potential SDN hit — halt and escalate through your compliance process. |
| 70 – 94 | manual_review | Possible match. Route to a human reviewer with the full SDN record. |
| < 70 | clear | Below threshold. Only returned if min_score is set lower than 70. |
A "clear" result does not confirm someone is unsanctioned — it means no candidate exceeded the score threshold against the current list.
Receipt verification
Every response is signed with Ed25519 over a canonical JSON representation of the body. This means you can prove months later that a specific screening happened, with exactly these results, against a specific SDN build — without trusting our servers.
Canonical form
- JSON keys sorted lexicographically (byte order).
- No whitespace between tokens:
{"a":1,"b":2}. - UTF-8 encoded, no BOM.
- Numbers serialized per ECMAScript
Number.prototype.toString(no trailing zeros, no+sign).
Verify in code
import json, base64
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
def verify_receipt(receipt, public_key_b64):
body = receipt["body"]
sig = base64.b64decode(receipt["signature"]["signature_b64"])
pub = base64.b64decode(public_key_b64)
canonical = json.dumps(
body, sort_keys=True, separators=(",", ":"),
).encode("utf-8")
Ed25519PublicKey.from_public_bytes(pub).verify(sig, canonical)
return True
Error codes
All errors return JSON: { "error": { "code": "...", "message": "..." } }
{
"error": {
"code": "invalid_api_key",
"message": "API key is missing or invalid."
}
}
| HTTP | Code | Description |
|---|---|---|
| 400 | invalid_request | Malformed JSON or missing required field. |
| 401 | invalid_api_key | Missing or invalid X-API-Key. |
| 403 | key_suspended | Key exists but has been suspended (e.g. payment issue). |
| 422 | validation_failed | Field is present but invalid (name too short, min_score out of range, etc.). |
| 429 | rate_limit_exceeded | Too many requests. Check Retry-After header. |
| 429 | quota_exhausted | Free tier quota used up. Upgrade to continue. |
| 500 | internal_error | Unexpected server error. Retry with exponential backoff. |
| 503 | list_unavailable | SDN list is being rebuilt. Typically resolves within 60 seconds. |
Best practices
- →Set min_score to 70 or higher in production. Lower thresholds surface weak matches that waste reviewer time.
- →Screen on the exact name given to you, unmodified. Sigeel does all normalization. Pre-normalizing loses signal.
- →Store the full receipt envelope, not just the matches. The signature +
list.built_atis your audit artifact. - →Verify signatures on ingest if you're building an audit pipeline. It costs microseconds and closes the loop.
- →Retry 5xx with exponential backoff. Do not retry 4xx. Do respect
Retry-Afteron 429. - →Cache the pubkey for 24 hours. It rotates quarterly. Match
key_idon receipts to select the right one. - →Treat results as input to a human decision, not a final determination. See the compliance disclaimer on the home page.
Changelog
- Added
entity_typefilter toPOST /screen. body.usagenow includesoverage.
- Added
matched_onfield to Match objects. - Improved alias normalization for Cyrillic transliterations.
- Ed25519 signing on every response. Backwards-compatible: signature is an additive field.
- Added
GET /pubkeyendpoint.
- Initial public release.
POST /screenandGET /health.