FreezeRadar Developers · v1

Asynchronous freeze-risk intelligence API

Business customers can submit wallet and transaction screenings, poll a result, and receive signed completion events. Results are explainable risk signals — not legal advice, AML certification, an ownership assertion, or an instruction to block a payment.

Authentication

Use a Business API key in the Authorization Bearer header. Create and revoke keys from the Developer Console.

Async workflow

Create a screening, retain its id, then poll the result URL or wait for a signed webhook.

Signed delivery

Every webhook includes an event id, Unix timestamp and HMAC-SHA256 signature.

Getting started

Overview

The FreezeRadar Business API mirrors the same freeze-risk analysis used in the app. Every screening is asynchronous: a create call returns immediately with a job id, and the result becomes available once analysis finishes — via polling or a signed webhook event.

Quickstart

No API key needed for this one — it hits a public endpoint. Run it now and you have a real result in under a minute:

cURL
curl "https://freezeradar.com/api/sanctions/check?address=TBZefVsyQpzzxc2WSCLbZBECvxVdzGqdtC"
Response · 200 OK
{
  "ok": true,
  "data": {
    "address": "TBZefVsyQpzzxc2WSCLbZBECvxVdzGqdtC",
    "chain": "tron",
    "sanctioned": true,
    "matches": [
      { "source": "OFAC", "entityName": "CHEIL CREDIT BANK", "entitySlug": "cheil-credit-bank-ea8e1b0944" }
    ]
  }
}

That address is a real, currently-sanctioned entity (see it on /sanctions). For the Business API below you'll need a key from the Developer Console, or try every public endpoint with your own address in the playground.

Authentication

Send Authorization: Bearer <API_KEY> over HTTPS on every request. Keys are account-owned and shown only once when created. Store them in a server-side secret manager; never place them in browser code, mobile apps, or public repositories.

Invalid, revoked, or absent keys return 401 UNAUTHORIZED. Business feature or quota restrictions return a safe error without internal provider details.

Response · 401 Unauthorized
{
  "ok": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "A valid Business API key is required."
  }
}

Versioning & stability

Business API endpoints below are relative to https://freezeradar.com/api/v1. Public endpoints live outside the version prefix (/api/sanctions/check, etc.) since they mirror the free site rather than a versioned contract. The current Business API version is v1.

  • Breaking changes ship under a new version prefix (/api/v2) — v1 keeps working.
  • A new optional field on a response is not a breaking change; do not fail on unrecognized fields.
  • A deprecated field or endpoint is announced here and in the changelog with a removal date at least 90 days out.

API reference

Create an address screening

POST
/api/v1/address-screenings

Accepts the same address, chain, optional asset list, and optional scan mode as the FreezeRadar app. Returns immediately with an id and QUEUED status.

ParameterTypeDescription
addressrequiredstringWallet address to screen.
chainrequiredethereum | tron | bsc | polygon | solana | base | arbitrum | optimism | avalancheChain the address belongs to.
assetsoptional(USDT | USDC | PAXG | XAUt)[]Restrict analysis to specific freezeable assets. Defaults to full coverage.
scanModeoptionalSTANDARD | DEEPDEEP performs a more thorough, slower analysis. Defaults to STANDARD.
cURL
curl -X POST https://freezeradar.com/api/v1/address-screenings \
  -H "Authorization: Bearer fr_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0x…",
    "chain": "ethereum",
    "assets": ["USDT"],
    "scanMode": "STANDARD"
  }'
Response · 200 OK
{
  "ok": true,
  "data": {
    "id": "scan_job_id",
    "status": "QUEUED",
    "resultUrl": "/api/v1/screenings/scan_job_id"
  }
}

Create a transaction screening

POST
/api/v1/transaction-screenings

Screens a specific on-chain transaction. Coverage is returned only where the underlying chain provider can prove a supported freezeable-asset transfer.

ParameterTypeDescription
chainrequiredethereum | tron | bsc | polygon | solana | base | arbitrum | optimism | avalancheChain the transaction belongs to.
transactionHashrequiredstringThe transaction hash to analyze.
policyIdoptionalstringApply an existing risk policy's thresholds to the verdict.
cURL
curl -X POST https://freezeradar.com/api/v1/transaction-screenings \
  -H "Authorization: Bearer fr_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "chain": "ethereum",
    "transactionHash": "0x…",
    "policyId": "cl…"
  }'
Response · 200 OK
{
  "ok": true,
  "data": {
    "id": "screening_id",
    "status": "QUEUED",
    "resultUrl": "/api/v1/screenings/screening_id"
  }
}

A transaction that is valid but has no supported asset coverage, or cannot be assessed for that chain, returns 422 and releases its reserved quota.

Get a screening result

GET
/api/v1/screenings/{id}

Returns the latest job state for either screening type. Possible statuses are QUEUED, RUNNING, COMPLETED, and FAILED. Do not treat QUEUED or RUNNING as a final result.

cURL
curl https://freezeradar.com/api/v1/screenings/scan_job_id \
  -H "Authorization: Bearer fr_live_…"
Response · wallet screening
{
  "ok": true,
  "data": {
    "id": "scan_job_id",
    "status": "COMPLETED",
    "resultUrl": "/scan/wallet_scan_id",
    "walletScanId": "wallet_scan_id",
    "errorMessage": null,
    "scan": {
      "id": "wallet_scan_id",
      "overallRisk": 34,
      "riskCategory": "MEDIUM",
      "confidenceScore": 81,
      "accessMode": "SUMMARY",
      "scanMode": "STANDARD",
      "analyzedAt": "2026-08-05T02:10:00.000Z",
      "summary": "MEDIUM risk driven by 1-hop exposure to issuer-blacklisted address.",
      "scoreDrivers": [
        {
          "findingType": "ONE_HOP_SANCTIONS_EXPOSURE",
          "title": "1-hop exposure to issuer-blacklisted address",
          "contribution": 62,
          "confidence": 86,
          "direction": "INCREASE",
          "detail": "This wallet received 20,000 USDT across 1 transfer 12 days ago with TQ86… — 0.45% of tracked volume, which is blacklisted on-chain by the token issuer."
        }
      ]
    }
  }
}
Response · transaction screening
{
  "ok": true,
  "data": {
    "id": "screening_id",
    "status": "COMPLETED",
    "verdict": "CLEAR",
    "riskCategory": "LOW",
    "overallRisk": 12,
    "chain": "ethereum",
    "transactionHash": "0x…",
    "resultUrl": "/api/v1/screenings/screening_id",
    "completedAt": "2026-08-05T02:10:00.000Z",
    "errorMessage": null,
    "result": { "findings": [], "transferCoverage": "…", "policyVersion": null }
  }
}

Transaction results include verdict (CLEAR / REVIEW / BLOCK), riskCategory, findings, transfer coverage, and the policy version when one was used. Responses never include raw evidence blobs.

Public API · no key, IP rate-limited

Sanctions check

GET
/api/sanctions/check

Direct sanctions-list matches for an address. 20 requests/minute per IP.

ParameterTypeDescription
addressrequiredstringAddress to check.
chainoptionalstringAuto-detected from the address format if omitted (includes bitcoin, sanctions-only).
cURL
curl "https://freezeradar.com/api/sanctions/check?address=TBZefVsyQpzzxc2WSCLbZBECvxVdzGqdtC&chain=tron"

Widget check

GET
/api/widget/check

Blacklist and sanctions status only — no score, no findings. Same endpoint the embeddable widget calls. 30 requests/minute per IP.

cURL
curl "https://freezeradar.com/api/widget/check?address=TLXDJUauN4vgN75tJtCbXiAm4mQaDTmTNY"
Response · 200 OK
{
  "ok": true,
  "data": {
    "address": "TLXDJUauN4vgN75tJtCbXiAm4mQaDTmTNY",
    "chain": "tron",
    "blacklisted": true,
    "sanctioned": false
  }
}

Stats

GET
/api/stats

Global and per-chain freeze totals, revalidated hourly. No rate limit beyond normal fair use.

cURL
curl "https://freezeradar.com/api/stats"
Response · 200 OK
{
  "ok": true,
  "data": {
    "totalFrozenUsd": 1284930221,
    "totalFreezeEvents": 41823,
    "blockedWallets": 39012,
    "largestFreeze": {
      "chain": "tron",
      "walletAddress": "T…",
      "assetSymbol": "USDT",
      "observedValueUsd": 62000000,
      "occurredAt": "2026-03-11T14:02:00.000Z"
    },
    "newBans30d": 612,
    "released": 1103,
    "burned": 47,
    "lostFunds": 18200000,
    "byChain": { "tron": 28110, "ethereum": 9822 },
    "byAsset": { "USDT": 39900, "USDC": 1500 },
    "coverageByChain": [
      { "chain": "tron", "status": "OK", "lastSyncedAt": "2026-08-27T09:00:00.000Z" }
    ],
    "lastUpdatedAt": "2026-08-27T09:00:00.000Z"
  }
}

Events feed

GET
/api/events

Paginated freeze events, or pass since to poll for new ones. Backs the /events page.

cURL
curl "https://freezeradar.com/api/events?chain=tron&range=24h"

Assets

GET
/api/assets

The freezeable-asset registry: which assets are freezeable on which chain, and the mechanism used.

cURL
curl "https://freezeradar.com/api/assets?chain=tron"

Chains

GET
/api/chains

Every chain FreezeRadar tracks.

cURL
curl "https://freezeradar.com/api/chains"
Response · 200 OK
{
  "ok": true,
  "data": [
    { "value": "ethereum", "label": "Ethereum" },
    { "value": "tron", "label": "Tron" },
    { "value": "bitcoin", "label": "Bitcoin (sanctions check only)" }
  ]
}

Webhooks

Events

Select events in the Business Developer Console. Payloads are JSON and include id, type, createdAt, and data.

EventFires when
screening.completedA transaction screening has a final result.
freeze-state.changedA priority issuer monitor observed a direct state change.
risk.alert.createdA related priority-monitor alert was created.

Verifying signatures

Every delivery includes these headers. The signature is sha256= plus an HMAC-SHA256 of the timestamp, a dot, and the raw request body, using the webhook secret shown at creation.

HeaderDescription
x-freezeradar-eventThe event type, e.g. screening.completed.
x-freezeradar-timestampUnix timestamp the delivery was signed at.
x-freezeradar-signaturesha256=<hmac> over `${timestamp}.${rawBody}`.
Node.js — verify signature
import { createHmac, timingSafeEqual } from "node:crypto";

const signed = `${timestamp}.${rawBody}`;
const expected =
  "sha256=" +
  createHmac("sha256", webhookSecret).update(signed).digest("hex");

if (!timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
  throw new Error("Invalid FreezeRadar signature");
}
Python — verify signature
import hashlib
import hmac

signed = f"{timestamp}.{raw_body}"
expected = "sha256=" + hmac.new(
    webhook_secret.encode(), signed.encode(), hashlib.sha256
).hexdigest()

if not hmac.compare_digest(signature, expected):
    raise ValueError("Invalid FreezeRadar signature")

Verify the signature against the raw body before parsing. Deduplicate on event id. Reject stale timestamps according to your replay window. Return any 2xx response to acknowledge delivery.

A non-2xx or timed-out response is retried up to 5 times with exponential backoff (roughly 2, 4, 8, then 16 minutes apart, 10s timeout per attempt), then marked FAILED. Retries are not guaranteed to arrive in order — an older event can be redelivered after a newer one — so order events by their x-freezeradar-timestamp header, not by arrival time.

Reference

Errors & rate limits

StatusMeaning
400Invalid request shape or invalid chain/address/hash.
401Missing, invalid, or revoked API key.
403Business entitlement is unavailable (including after plan downgrade), or an account limit is reached.
404Screening id does not belong to the authenticated account.
422Transaction is valid but has no supported asset coverage, or cannot be assessed for that chain.
429Rate limit exceeded — 60/min and 600/hour per API key. Respect Retry-After.
503Rate limiting temporarily unavailable; the Business API fails closed until Redis recovers.
5xxA temporary safe failure. Retry with exponential backoff.

Every Business API and rate-limited public response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix seconds) — read these instead of guessing your remaining budget.

Usage is account-scoped. Keys remain hashed at rest but are rejected on use unless the account still has an active Business entitlement. A transaction screening that cannot start because it is invalid, unsupported, or provider-unavailable releases its reserved transaction quota. Bridge-trace and graph-explorer entitlements are plan flags for product gating; they are not exposed as separate public /api/v1 endpoints yet.

Integration checklist

Before you ship

Keep keys and webhook secrets server-side.

Poll until a final status or verify signed webhooks.

Store evidence and coverage alongside your own decision.

Use a human review path for high-risk or incomplete results.

Do not represent FreezeRadar output as a legal determination or automatic freeze prediction.

Need higher limits or a custom policy?

Reach out and we'll help you scope a Business plan for your volume.

Contact us