Receiving a stablecoin payment (pay-in)

Receive stablecoins in a stablecoin Internal Account by sharing a unique blockchain address with the sender.

Modern Treasury represents inbound transfers as Incoming Payment Details (IPDs), the same object it uses for inbound fiat payments.

Example use cases:

  • Add stablecoins as a payment method in your Checkout experience
  • Receive stablecoins from an international sender

Get your receiving address details

Each stablecoin Internal Account has one unique blockchain address. External parties can send stablecoins directly to this address.

Specify the address type to provision with requested_account_number_types when creating the account. The account is created in pending_activation, and the provisioned address appears in account_details after the internal_account.activated webhook.

Get your account's blockchain address from the Internal Account object:

curl --request GET \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/internal_accounts/<STABLECOIN_INTERNAL_ACCOUNT_ID>

Use the account_details in the response to find your blockchain address:

{
  "id": "<STABLECOIN_INTERNAL_ACCOUNT_ID>",
  "object": "internal_account",
  "live_mode": true,
  "party_name": "Acme Payments Inc.",
  "party_address": null,
  "account_details": [
    {
      "id": "ce594f58-041c-44be-bcdb-714d9e690d78",
      "object": "account_detail",
      "live_mode": true,
      "account_number": "0x9bE868839163E128971Bb6AE045e172Fa806E805",
      "account_number_safe": "E805",
      "account_number_type": "ethereum_address",
      "discarded_at": null,
      "created_at": "2026-04-29T00:56:58Z",
      "updated_at": "2026-04-29T00:56:58Z"
    }
  ],
  "routing_details": [],
  "name": "Acme Payments USDC Account",
  "metadata": {},
  "legal_entity_id": "<ORGANIZATION_ENTITY_ID>",
  "currency": "USDC",
  "status": "active",
  "created_at": "2026-04-29T00:56:58Z",
  "updated_at": "2026-04-29T00:56:58Z"
}

Send the address to your counterparty. Modern Treasury records each inbound transfer as a transaction on your stablecoin Internal Account.

Track the incoming payment

Subscribe to Incoming Payment Detail webhooks to track the inbound transfer:

  • incoming_payment_detail.created — the transfer has been detected on the network.
  • incoming_payment_detail.completed — the transfer has finalized on chain and the funds are available in your stablecoin Internal Account.
{
  "event": "created",
  "data": {
    "id": "<INCOMING_PAYMENT_DETAIL_ID>",
    "object": "incoming_payment_detail",
    "internal_account_id": "<STABLECOIN_INTERNAL_ACCOUNT_ID>",
    "type": "stablecoin",
    "amount": 100000,
    "direction": "credit",
    "status": "pending",
    "currency": "USDC"
  }
}

Wait for incoming_payment_detail.completed before you treat the balance as final. Completed on-chain transfers cannot be reversed.

For the full IPD object and webhook reference, see Incoming Payment Details.

Test in Sandbox

Call the Simulate Incoming Payment Detail endpoint to simulate a stablecoin IPD. Webhook events fire in the same order as Production, so you can validate your event-driven logic end to end.

See Supported stablecoins & blockchain networks before you create the counterparty.