Detecting USDT and USDC Freezes Before You Credit a Deposit

Detecting USDT and USDC Freezes Before You Credit a Deposit

Crypto APIs Team

Sep 16, 2026 • 5 min

TL;DR — Stablecoin issuers can freeze USDT and USDC balances on Ethereum, Tron, and other chains at any moment, often on request from law enforcement. If your exchange or PSP credits a deposit that later gets frozen, the loss lands on you. This shows how to combine webhook-driven address monitoring with pre-credit AML screening across 20+ chains so you detect risk before the balance moves.

The US Department of Justice moved to forfeit roughly 61 million dollars in Tether (USDT) tied to Iranian oil proceeds. Tether has frozen sanctioned addresses on demand many times before, and Circle can do the same with USD Coin (USDC). For deposit platforms, a freeze is not a price event. It is an operational one. The tokens exist on-chain until the issuer blacklists the address, and after that they cannot be moved.

The problem

You run deposit infrastructure at an exchange, a payment service provider (PSP), or a custody platform. A customer sends USDT on Tron to a deposit address you generated. Your backend sees the transfer confirm, credits the internal balance, and lets the customer trade or withdraw. Then Tether blacklists the source or the receiving address in a smart-contract call. The tokens are stuck. You have already credited the customer. The shortfall is yours.

The gap is timing. Most deposit flows credit on confirmation count alone. They never check whether the sending address, the receiving address, or the funds themselves carry sanctions exposure before the internal ledger updates. By the time a chargeback or a forfeiture order arrives, the credit is spent.

What you need

  • A way to watch deposit addresses in real time across the chains you support — Ethereum, Tron, Polygon, Arbitrum, Base, Solana, and others where USDT and USDC circulate.
  • Token-transfer event subscriptions, not just native-coin transfers. USDT and USDC are contract tokens, so you need blockchain events that fire on ERC-20 and TRC-20 movements.
  • An AML screening step keyed on the address, returning a risk band and sanctions categories.
  • A hold state in your ledger. This is the hard part. Your credit logic must support pending, screened, and cleared as distinct states — not a single confirmed flag.
  • An HTTPS endpoint that accepts webhook callbacks and returns quickly. Slow consumers cause retries and duplicate processing.

Be honest about scope. Screening tells you an address is flagged. It does not predict a freeze that has not happened yet. What it buys you is the ability to hold a deposit that touches a sanctioned counterparty before you credit it, which is where most freeze exposure originates.

How it works

First, subscribe a deposit address to confirmed token transfers. This registers a webhook that fires when a TRC-20 or ERC-20 transfer to your address confirms. You pass the callback URL and the address you want to watch.

POST https://rest.cryptoapis.io/blockchain-events/tron/mainnet/address-tokens-transactions-confirmed
X-API-Key: <your key>
Content-Type: application/json

{
  "context": "deposit-watch-9f2",
  "data": {
    "item": {
      "address": "TXYZ...destinationDepositAddress",
      "callbackUrl": "https://your-backend.example/webhooks/token-in",
      "allowDuplicates": false
    }
  }
}

When the transfer confirms, the webhook posts to your callbackUrl. Do not credit yet. Take the sending address from the payload and run it through AML screening. This endpoint is GET, with the address in the path and no request body.

GET https://rest.cryptoapis.io/aml/addresses/TSourceAddressFromWebhook
X-API-Key: <your key>

A clean sender returns a low risk band with no categories:

{
  "apiVersion": "2024-12-12",
  "requestId": "6aa3c48d2f6f68835e3dbf05",
  "data": {
    "item": {
      "isFlagged": false,
      "riskScore": 0,
      "riskBand": "low",
      "severity": "none",
      "categories": [],
      "sources": []
    }
  }
}

A flagged sender carries categories and a higher band. Here isFlagged is true, riskBand is high, and categories names the exposure:

{
  "apiVersion": "2024-12-12",
  "requestId": "6aa3c4642f6f68835e3dbd6c",
  "data": {
    "item": {
      "blockchain": "ethereum",
      "isFlagged": true,
      "riskScore": 80,
      "riskBand": "high",
      "severity": "high",
      "categories": ["malicious", "sanctions"],
      "sources": [{
        "provider": "graphsense",
        "label": "tornado.cash",
        "categories": ["malicious"],
        "severity": "high",
        "listingTimestamp": 1784210009,
        "sanctionPrograms": []
      }]
    }
  }
}

Your credit logic reads riskBand and categories. Low band with no sanctions category moves the deposit to cleared and credits the customer. Anything in the high or severe band, or any address carrying a sanctions category, stays on hold and routes to manual review. The same verify address screening works across the chains where these stablecoins live, so one decision path covers Ethereum, Tron, and the EVM layer-2s.

You can also screen the deposit transaction itself with GET /aml/transactions/{blockchain}/{transactionHash}, which returns flaggedAddresses for the counterparties in that transfer. Use it when you want the whole transaction graph checked, not just the immediate sender.

What to watch for

Optional AML fields are omitted, never null. Read isFlagged and riskBand defensively. Do not assume attribution or sources exist on a clean response — they will be absent.

Confirmed does not mean final on every chain. On EVM chains, credit only after your required confirmation depth. A freeze can also land after your credit, since blacklisting is an issuer action outside your control. Screening the sender before crediting reduces exposure to funds that already carry sanctions ties; it cannot pre-empt a future freeze on a currently clean address.

Handle webhook retries. Set allowDuplicates to false and make your consumer idempotent on the transaction hash. A slow or failing endpoint triggers redelivery, and a non-idempotent handler will double-credit.

Screen once per deposit, not on every read, to stay within your plan limits. Cache the screening result against the deposit record. Re-screen only on withdrawal if your policy requires a fresh check.

Distinguish severity from risk band. An address can sit at severity: info with categories that do not warrant a hold. Define your hold thresholds explicitly rather than blocking on any non-empty categories array.

Token freezes on USDT and USDC are a standing operational risk for anyone crediting stablecoin deposits at scale. The combination of Blockchain Events for real-time token-transfer webhooks and AML screening before the ledger updates gives your team a defined hold-and-clear path across 20+ chains. Start on the free tier, no credit card required, and wire the hold state into your deposit flow before the next forfeiture order names an address you already credited.

Infrastructure optimized for growth

35+

Networks Supported

25ms

Avg Processing Time

25,000+ rq/s

Enterprise-ready

100+ TB

of Big Data

Related articles

Share