Developers

Ilzami API

Screen names against the UN Security Council Consolidated List and Kuwait's National List from your own systems: one name at a time, in batches, or continuously through ongoing monitoring. Every screening service on the Ilzami dashboard is available through the same API.

Overview

Availability

API access is included in the Advanced - Sanctions Screening plan. Whether your current plan includes it is reported as package_limits.api_key_enabled by subscription status.

Each feature is also governed by your plan, through the API exactly as on the dashboard:

FeaturePlan flagWithout it
Single-name screening, review, reports, historyAny active plan—
Batch screeningfeatures.batch_scanning403 with upgrade_required: true
Ongoing monitoringfeatures.ongoing_monitoring403 with upgrade_required: true

Authentication

Getting your API key

  1. Sign in to the dashboard as your organization's admin and open Team management.
  2. Under API access, choose Generate API key.
  3. Copy the key straight away. It is shown once. If it is lost, regenerate it: the old key stops working at that moment.

The key belongs to your organization. Your organization has one key at a time. The key is valid while your subscription is active and your plan includes API access. It is renewed with your subscription, and the admin can revoke it at any time from the same page.

Sending the key

Send the key in the X-API-Key header on every request:

curl https://ilzami.com/api/subscription-status/ \
  -H "X-API-Key: YOUR_API_KEY"
Keep the key on your servers. Never put it in a mobile app, a web page or a public repository. Anyone holding the key can screen names under your organization's plan.

Whom a request acts as

A request made with the key has your organization admin's permissions, including recording match decisions, and counts against your organization's monthly search allowance. Scans and batches run with the key are credited to Organization API key, not to a person. That is how they appear in your history, reports, exports and verification pages.

By design, the key cannot manage your team, change or pay for your subscription, or delete accounts. Those actions stay on the signed-in dashboard.

Conventions and limits

RuleValue
Similarity thresholdFixed at 75% for every customer. A threshold sent in a request is ignored.
Lists searchedAlways both: UN Security Council Consolidated List (un) and Kuwait's National List (kuwait). A lists value sent in a request is ignored.
Record typesIndividuals and entities are both screened. In a batch, a per-row type narrows that row.
Monthly allowanceEach screened name counts as one search: a single search, or each name in a batch. Shared by every member of the organization and the API key. It resets on the 1st of each month.
Batch sizeUp to 1,000 unique names per request. Files up to 10 MB (.csv or .xlsx).
Paginationpage (from 1) and page_size (1–100, default 10) where noted.

A name that cannot be screened is an error, never a clear result

If a name cannot be screened as entered (for example it is empty after cleaning, or contains no letters), the scan is still recorded with a reference number, but its status is "error" and error gives the reason. Never treat such a scan as "no match". A single-word name is screened against exact single-name listings only, and notice says so.

Errors

Errors from an endpoint carry "success": false and a human-readable message (some endpoints use error). Errors raised before the endpoint runs (a bad key, an inactive subscription, a plan without API access, a used-up allowance) carry detail instead. Download endpoints answer their own errors as plain text.

StatusMeaning
400The request is invalid, or the name could not be screened (see above).
401The key is missing, invalid or expired, or the organization is inactive. The response's detail says which.
403The subscription is not active, the plan does not include API access or the feature (upgrade_required: true), the monthly allowance is used up, or the record belongs to another organization.
404The reference number or code was not found in your organization.

Services covered

Every screening service on the Ilzami dashboard is available through the API. Civil ID card capture is not: it reads a name from a photographed card, and an integration already holds the name it screens.

Dashboard serviceAPI
Single-name screeningPOST /api/search/
Reviewing matches and recording decisionsGET /api/scan/{ref}/review/, POST /api/scan/{ref}/decisions/
PDF and CSV scan reports, verification linksPOST /api/scan/download/, /verify/{ref}/
Search history and monthly Excel exportGET /api/search-history/, GET /api/search-history/export/
Batch screening (template, upload, results, history)/api/batch/…
Ongoing monitoring (watchlist, rescans, reports)/api/monitoring/…
Plan, usage and featuresGET /api/subscription-status/
Civil ID card capture, team, billing, account deletionDashboard and app only

Account and plan

GET /api/subscription-status/

Your plan, its limits and features, this month's usage, and the fixed screening scope. Call it at start-up to decide what your integration can offer.

{
  "success": true,
  "data": {
    "member": {"email": "admin@example.com", "is_admin": true, "organization_name": "Example Co.",
               "authorities": {"single_search": true, "batch_upload": true, "update_monitoring": true,
                               "notification_emails": true, "make_decisions": true}},
    "subscription": {"package_name": "Advanced - Sanctions Screening", "period": "yearly",
                     "status": "active", "start_date": "2026-01-01T09:00:00+00:00",
                     "end_date": "2027-01-01T09:00:00+00:00", "is_active": true},
    "package_limits": {"monthly_limit": 3000, "web_users_limit": 5, "api_key_enabled": true},
    "features": {"batch_scanning": true, "id_capture": false,
                 "ongoing_monitoring": true, "monitoring_names_limit": 500},
    "screening": {"threshold": 75, "lists": ["un", "kuwait"]},
    "usage": {"current_month_searches": 412, "remaining_searches": 2588,
              "total_searches": 9120, "team_members": 4}
  }
}

Name screening

POST /api/search/ counts 1 search

Screen one name against both lists. The scan is stored and gets a reference number.

FieldType
search_termstring, requiredThe full name, in Latin or Arabic script. name is accepted as an alias.
curl -X POST https://ilzami.com/api/search/ \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"search_term": "John Michael Smith"}'
{
  "success": true,
  "data": {
    "reference_number": "5f0c2a8e-3b1d-4c7a-9a55-0e8f1d2b7c41",
    "search_term": "John Michael Smith",
    "threshold": 75,
    "sanctions_lists_scanned": ["UN Security Council Consolidated List", "Kuwait's National List"],
    "matches": [ { "name": "…", "similarity": 88, "list name": "…", "…": "…" } ],
    "total_matches": 1,
    "status": "completed",          // or "error": the name was NOT screened
    "error": null,
    "notice": null,                 // set for single-word names
    "single_name": false,
    "timestamp": "2026-10-11T08:15:02.114+00:00",
    "timestamp_display": "11 Oct 2026, 11:15 (Kuwait time)",
    "conducted_by": "Organization API key",
    "review": { "status": "pending", "total": 1, "decided": 0, "matches": [ … ] }
  },
  "subscription_info": {"package_name": "…", "monthly_limit": 3000, "searches_used": 413,
                        "remaining_searches": 2587, "subscription_end_date": "…"}
}

When status is "error", the response is 400 with message explaining why the name was not screened. The scan is still recorded and counted.

Match review and decisions

Every match is reviewed by recording a decision: false positive (a different person) or true match (the same person). A scan's review status is no_match, pending, cleared (every match a false positive), true_match or error.

GET /api/scan/{reference_number}/review/

One stored scan with its current review state, including decisions made by colleagues. Works for single scans and for each name of a batch.

Each item of data.review.matches has key (use it to record a decision, for example "un:KPi.033"), name, record_type, similarity, fields (the list record's details), differs_options (what can be marked as different for this record) and decision (the decision in force, or null).

POST /api/scan/{reference_number}/decisions/

Record a decision on one match. Decisions are append-only: to change one, post again. The earlier record stays in the audit log. Returns 201 with the scan as it now stands. For a name in a batch, the response also includes data.batch, the batch's updated counts.

FieldType
match_keystring, requiredThe match's key from the review.
decisionstring, requiredfalse_positive or true_match
what_differsarrayRequired for false_positive: one or more keys from that match's differs_options, from date_of_birth, place_of_birth, nationality, id_number, country, address, other.
notestring, requiredYour reasoning, up to 2,000 characters.
curl -X POST https://ilzami.com/api/scan/5f0c2a8e-3b1d-4c7a-9a55-0e8f1d2b7c41/decisions/ \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"match_key": "un:KPi.033", "decision": "false_positive",
       "what_differs": ["date_of_birth", "nationality"],
       "note": "Customer born 1990, Kuwaiti national; listed person born 1961."}'

Reports and verification

POST /api/scan/download/

The scan report as a file, built from the stored scan, with the decisions recorded on it.

FieldType
reference_numberstring, requiredThe scan's reference number.
formatstringpdf (default) or csv
curl -X POST https://ilzami.com/api/scan/download/ \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"reference_number": "5f0c2a8e-3b1d-4c7a-9a55-0e8f1d2b7c41", "format": "pdf"}' \
  -o report.pdf

GET /verify/{reference_number}/ public

The public verification page for a scan, the page the report's QR code opens. Share it with auditors. It needs no key. /verify/{reference_number}/pdf/ returns the same scan as a PDF.

Search history

GET /api/search-history/

Stored scans, newest first, paginated. Names from a batch that had no match are left out, since the batch keeps them.

Query
scopeorganization for everyone's scans. The default, member, returns the admin's own scans, which includes every API scan.
daysOnly the last N days.
statuspending, true_match, cleared or no_match.
exclude_batch1 to leave out batch scans entirely.
include_matches1 to include each scan's stored matches.
page, page_sizePagination (page size 1–100, default 10).

Response: data (rows with reference_number, search_term, status, total_matches, review, is_batch, batch_reference, member_email (who ran it, or Organization API key), via_api, timestamp, …), status_counts and pagination.

GET /api/search-history/export/?month=YYYY-MM

One calendar month of your organization's single-name scans as an Excel workbook, with review status, decisions and verification links. The default is the current month.

Batch screening plan feature

Screen up to 1,000 names in one synchronous request. Each name counts as one search. A batch larger than your remaining allowance is refused as a whole, before anything is screened. Every name gets its own reference number, verification link and PDF.

GET /api/batch/template/

The blank Excel template (name, type and optional date of birth per row). Results come back in the same workbook.

POST /api/batch/upload/ counts 1 search per name

Send names in any combination of these fields. Duplicate names are screened once.

FieldType
entriesarray (JSON)Objects with name (required), type (individual or entity) and dob. Best for system integrations.
namesstringNames separated by new lines.
filefile (multipart)The filled-in template, .xlsx or .csv.
curl -X POST https://ilzami.com/api/batch/upload/ \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"entries": [
        {"name": "John Michael Smith", "type": "individual", "dob": "1984-03-12"},
        {"name": "Gulf Trading Company", "type": "entity"}
      ]}'

# or with a file
curl -X POST https://ilzami.com/api/batch/upload/ \
  -H "X-API-Key: YOUR_API_KEY" -F "file=@customers.xlsx"

Response data: reference_code, total_names, names_with_matches, total_matches, names_with_errors, names_clear, names_limited, truncated (more than 1,000 names were sent), review (the batch's review summary) and names (each name with its status: match, clear or error, its matches and its own reference_number). Also subscription_info with your remaining allowance.

To record decisions on a batch match, use that name's reference_number with the decision endpoint.

GET /api/batch/history/

Your organization's 25 most recent batches, with status_counts. Filter with ?status=needs_review or ?status=reviewed. Add ?reference_code=… to get one batch's full results, in the same shape as the upload response.

POST /api/batch/download/

A batch's results as a file. Body: reference_code (required) and format: xlsx (default, the screening report with a PDF link per name) or csv.

Ongoing monitoring plan feature

Keep a watchlist of your customers. Ilzami rescreens the whole list whenever the UN or Kuwait list changes, and when you upload a new version. Each run is a monitoring scan with its own reference code. Members of your team with notification emails turned on are alerted when a run finds matches. Monitoring rescans do not count against the search allowance. The plan sets how many names the list may hold.

GET /api/monitoring/status/

names_limit, available_lists, list (the watchlist in force: version, name_count, uploaded_at, uploaded_by…, or null) and scans (the 50 most recent runs).

GET /api/monitoring/template/

The blank watchlist template, sized to your plan's name limit.

POST /api/monitoring/upload/

Upload (or replace) the watchlist as multipart/form-data with file (the template, .xlsx or .csv). The file is checked against the name limit before anything changes, so a rejected upload leaves the current list in force. The earlier version is kept. An initial scan starts right away. Its result appears under /api/monitoring/scans/ shortly after.

curl -X POST https://ilzami.com/api/monitoring/upload/ \
  -H "X-API-Key: YOUR_API_KEY" -F "file=@watchlist.xlsx"

GET /api/monitoring/list/

The watchlist in force with every entry as Ilzami read it (data.list.entries).

GET /api/monitoring/list/download/

The watchlist in force as an Excel workbook.

GET /api/monitoring/scans/

The 50 most recent monitoring scans: reference_code, status, trigger_key (list_update when a sanctions list changed, list_upload, list_change when you replaced the watchlist, manual), triggered_by, total_names, names_with_matches, total_matches, names_with_errors, started_at, completed_at, alert_sent_at. Add ?reference_code=… for one scan with its full results.

POST /api/monitoring/download/

One monitoring scan as the Excel monitoring report. Body: reference_code.

Public endpoints

GET /api/packages/ public

The plans on offer, with prices, limits and included features. No key needed.

Full example

Onboarding check in Python: screen a customer, stop on an error, and keep the reference and PDF as evidence.

import os, requests

BASE = "https://ilzami.com"
session = requests.Session()
session.headers["X-API-Key"] = os.environ["ILZAMI_API_KEY"]

r = session.post(f"{BASE}/api/search/", json={"search_term": "John Michael Smith"}, timeout=30)
scan = r.json()["data"]

if scan["status"] == "error":
    # The name was NOT screened. Never treat this as clear.
    raise RuntimeError(scan["error"])

ref = scan["reference_number"]
print("Matches:", scan["total_matches"], "Review:", scan["review"]["status"])
print("Verify:", f"{BASE}/verify/{ref}/")

pdf = session.post(f"{BASE}/api/scan/download/", json={"reference_number": ref, "format": "pdf"})
open(f"ilzami-{ref}.pdf", "wb").write(pdf.content)

Support

Questions about the API, or need a feature your integration depends on? Write to support@techween.net.