# Detecting USDT and USDC Freezes Before You Credit a Deposit

Detect USDT and USDC freezes before crediting deposits. Combine webhook address monitoring with pre-credit AML screening across 35+ networks including Tron.

*Published 2026-09-16*

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 35+ networks so you detect risk before the balance moves.

The US Department of Justice moved to [forfeit roughly 61 million dollars in Tether (USDT)](https://cointelegraph.com/news/us-doj-seeks-61m-usdt-forfeiture-iranian-oil) 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](https://cryptoapis.io/blockchains/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](https://cryptoapis.io/products/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](https://cryptoapis.io/products/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](https://cryptoapis.io/products/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 35+ networks. 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.

---

More on the [Crypto APIs blog](https://cryptoapis.io/blog), or see the [products](https://cryptoapis.io/products) this is built on.
