Guide: Periodic Rescreening
Re-screen your entire user base on a regular schedule to catch addresses that are added to sanctions lists after onboarding.
Why rescreen
Sanctions lists are updated frequently — OFAC publishes updates multiple times per week. A wallet that was clean at onboarding may be added to a list months later. Most jurisdictions expect ongoing monitoring, not just point-in-time checks.
Common schedules: daily for high-risk segments, weekly for the full user base. Match your frequency to your regulatory requirements and quota.
Quota planning
Batch rescreening consumes quota at 1 request per address. Before scheduling, estimate:
# Quota estimate
active_users = 5000
rescreen_frequency = 4 # times per month (weekly)
quota_needed = active_users * rescreen_frequency
# = 20,000 requests/month → Growth plan (100k/month) is appropriate
# Check your current usage
curl https://anchorapi.dev/api/v1/usage \
-H "Authorization: Bearer $SCREENING_API_KEY"Rescreening script
import os
import time
import requests
SCREENING_API_KEY = os.environ["SCREENING_API_KEY"]
BASE_URL = "https://anchorapi.dev/api/v1"
BATCH_SIZE = 100 # Max per API call
def screen_batch(addresses: list[dict]) -> dict:
response = requests.post(
f"{BASE_URL}/screen/batch",
headers={"Authorization": f"Bearer {SCREENING_API_KEY}"},
json={"addresses": addresses},
timeout=30,
)
response.raise_for_status()
return response.json()
def get_active_wallets(db_conn) -> list[dict]:
"""
Return all active user wallets from your database.
Each row should have: user_id, wallet_address, chain
"""
cursor = db_conn.cursor()
cursor.execute("""
SELECT user_id, wallet_address, chain
FROM user_wallets
WHERE status = 'active'
ORDER BY user_id
""")
return cursor.fetchall()
def rescreen_all_users(db_conn):
"""
Re-screen every active wallet. Call this on a cron schedule (e.g., weekly).
Consumes 1 quota unit per wallet address.
"""
wallets = get_active_wallets(db_conn)
flagged = []
errors = []
for i in range(0, len(wallets), BATCH_SIZE):
batch = wallets[i : i + BATCH_SIZE]
addresses = [
{"address": w["wallet_address"], "chain": w["chain"]}
for w in batch
]
try:
result = screen_batch(addresses)
except requests.exceptions.HTTPError as e:
errors.append({"batch": i // BATCH_SIZE, "error": str(e)})
continue
for wallet, screening in zip(batch, result["results"]):
# Log every result for audit trail
log_rescreen_event(
user_id=wallet["user_id"],
address=screening["address"],
chain=screening["chain"],
level=screening["level"],
score=screening["score"],
labels=[l["label"] for l in screening["labels"]],
scoring_version=screening["scoring_version"],
)
if screening["level"] in ("CRITICAL", "HIGH"):
flagged.append({
"user_id": wallet["user_id"],
"address": screening["address"],
"level": screening["level"],
"labels": [l["label"] for l in screening["labels"]],
})
# Respect rate limits between batches — 100ms between calls
time.sleep(0.1)
# Alert compliance team with all newly flagged accounts
if flagged:
send_rescreen_alert(flagged)
return {"screened": len(wallets), "flagged": len(flagged), "errors": len(errors)}Scheduling options
# crontab entry — run weekly on Sunday at 2am UTC
0 2 * * 0 /usr/bin/python3 /app/scripts/rescreen.py >> /var/log/rescreen.log 2>&1What to do with flagged addresses
When a previously-clean address appears flagged in rescreening:
- Suspend withdrawals to and from that wallet immediately.
- Alert your compliance team with the full screening result and user context.
- Do not alert the user until your compliance team has reviewed the case.
- Document the date of detection — regulators may ask when you identified the risk.
- File a SAR if required under applicable law.