Skip to main content

Overview

Offramps let your users convert stablecoin to fiat through a persistent payment route. The process involves two steps:
  1. Create a payment account: register the user’s bank account details as a payment account.
  2. Create an offramp payment route: set up the route that converts crypto to fiat and sends it to the payment account.
When a user sends stablecoin to the route’s deposit address, funds are automatically converted to fiat and transferred to their registered bank account. Rain supports USD offramps over ACH and wire, and MXN offramps over SPEI. See MXN offramps for the differences.

Before you begin

Make sure you have:
  • API access to the payment accounts and payment routes endpoints.
  • User bank account details: the destination bank account information (account number, routing number, and beneficiary details, or a CLABE for MXN).
  • A stablecoin source: users need stablecoin on a supported chain to offramp.

Restrictions

Offramp payment routes are subject to the same restrictions & availability rules as any other payment route, plus Rain’s Payments compliance checks. Rain also screens each deposit into a payment route and checks it against your program’s partner-managed limits. A deposit that Rain holds for review shows the transfer status pending_review until Rain releases or returns it.

Key concepts

Payment accounts

A payment account is a stored representation of a user’s bank account or other fiat destination. Once created, you can use it as a destination for both payment routes (persistent offramps) and transfers (one-time international payments via quotes). Payment accounts let you:
  • Pre-validate bank account details before creating transfers.
  • Reuse the same destination across multiple payment routes or transfers.
  • Track payments associated with specific accounts.
For offramps, you create an externalFiatAccount type payment account containing the user’s bank details.

Payment routes

An offramp payment route creates a persistent pipe from crypto to fiat:
  • Source: stablecoin on a supported chain.
  • Destination: a payment account, the user’s bank account.
When you create an offramp payment route, Rain generates a depositAddress containing an onchain wallet address. Any stablecoin sent to this address is automatically converted to fiat and transferred to the payment account.

API flow

Action / API callExternal / networkWebhook Rain sends you
UserProvides bank details
1PartnerPOST /payment-accounts
2RainReturns payment account
3PartnerPOST /payment-routes
4RainReturns route with depositAddress
5PartnerProvides deposit address
6UserSends stablecoin to deposit address
7RainConverts to fiat
8BankReceives fiat transfer
9WebhooktransactionTransfer
The steps above, in text:

Step 1: create a payment account

Before creating an offramp payment route, you must register the user’s bank account as a payment account. Call POST /payment-accounts with the externalFiatAccount type. See Register a bank account for the full request, response, supported fields, and the first-party/third-party distinction for the account owner.

Step 2: create an offramp payment route

Once you have a payment account, create an offramp payment route by calling POST /payment-routes. See Create an offramp payment route for the full request, response, and field reference.
Refund address requiredThe refundAddress field is mandatory when creating an offramp payment route. Set this to a valid onchain address where stablecoin can be returned if a transaction cannot be completed. Funds may be returned due to:
  • Destination bank account issues (closed account, invalid details, account restrictions).
  • Partner-managed limits being exceeded.
  • Compliance or regulatory holds.
  • Failed fiat transfers rejected by the receiving bank.
If you don’t provide refundAddress, Rain rejects the payment route creation request. Make sure the refund address is a wallet you control and can receive the source stablecoin on the specified chain.
Address format requirementsThe refund address must match the expected format for the source rail:
  • EVM chains (Ethereum, Base, Polygon, Arbitrum, Optimism, Avalanche): must be a valid EVM address starting with 0x followed by 40 hexadecimal characters (for example, 0x1234567890abcdef1234567890abcdef12345678).
  • Solana: must be a valid Solana address in base58 format (32-44 characters).
If the address doesn’t match the source rail format, the request fails.
The response’s depositAddress is unique to this payment route. Only send the specified source currency (for example, USDC on Base) to this address. Rain doesn’t process or return other tokens automatically, so sending them may result in loss of funds.

MXN offramps

MXN offramps follow the same two steps as USD offramps, with MXN as the destination currency and SPEI as the rail. The refund address, deposit address, webhooks, and transfer transactions work as described on this page. Only the payment account and the route’s destination differ.

Payment account

Register the beneficiary’s Mexican bank account with currency set to mxn, rail set to mx_spei, and a clabeNumber (the account’s 18-digit CLABE) instead of accountNumber and routingNumber. Set beneficiaryType to individual or business and provide the matching name fields, as described in Register a bank account. MXN/SPEI accounts don’t need bankAccountType, beneficiaryAddress, bankName, or bankAddress. See Payment account details for the full field list.

Payment route

Create the route with destination.currency set to mxn, destination.rail set to mx_spei, and destination.address referencing the payment account. Send the refundAddress as for any offramp. Optionally, set transferMessage. On MXN offramps, this memo surfaces as the reference on the outgoing SPEI transfer to the beneficiary’s bank account. On every payment route, the memo can be up to 23 characters, and only ASCII letters, numbers, and spaces are allowed. destination.referenceId is a deprecated alias for the same value. If you send both, transferMessage takes precedence. Once the route is active, stablecoin sent to its depositAddress is converted and sent to the user’s bank account over SPEI. MXN payment routes can’t be updated after creation, and a PATCH returns 422. To change one, delete it and create a new one.

Manage payment accounts

Use GET /payment-accounts, GET /payment-accounts/{paymentAccountId}, and DELETE /payment-accounts/{paymentAccountId} to list, retrieve, and remove payment accounts. See Manage payment accounts for the full request and response examples.
Deleting a payment account doesn’t delete the payment routes that reference it, but those routes can no longer pay out. Delete the payment route first, then delete the payment account.

Manage payment routes

Use GET /payment-routes, GET /payment-routes/{paymentRouteId}, PATCH /payment-routes/{paymentRouteId}, and DELETE /payment-routes/{paymentRouteId} to list, retrieve, update, and remove offramp payment routes. Only transferMessage, refundAddress, and senderFees can change, and MXN routes can’t be updated. See Manage payment routes for the full request and response examples.

What happens when crypto is deposited

When a user sends stablecoin to the deposit address:
  1. Crypto received: Rain detects the incoming stablecoin transfer. Deposits under 2.00 of the source token don’t create a transfer.
  2. Transfer created: Rain creates a transaction of type transfer and sends a transactionTransfer webhook with action created.
  3. Conversion: Rain converts stablecoin to fiat.
  4. Fiat transfer: Rain sends funds to the user’s bank account via the specified rail.
  5. Transfer completed: the transfer settles, and Rain sends a transactionTransfer webhook with action completed.

Webhooks

Rain sends webhooks through the transfer lifecycle: There is no separate failure webhook. A returned transfer, including a bank return after completed, arrives as updated with status refunded; see Refund reasons. See Money Movement Webhooks for how a transfer moves through these events, and the transfer object reference for the full webhook payload schema.

Transfer transaction

Each successful offramp creates a transfer transaction that you can query via the Transactions API. Filter by type=transfer to see all transfer transactions. Example transfer transaction response:
To list the transfer transactions for a specific user, see View a virtual account’s transactions.

Settlement times

After crypto is received, fiat transfer times vary by rail:

Cutoff times

ACH and wire processing is subject to banking cutoff times. Rain processes transfers initiated after the cutoff on the next business day.
ACH and wire cutoff times apply on US business days only. ACH and wire transfers initiated on weekends or US federal holidays are processed on the next business day. SPEI transfers aren’t affected.

Supported configurations

Source (crypto)

Destination (fiat)

MXN offramps are enabled per program. Contact your Rain representative to turn them on.
Rain regularly adds additional currencies and rails. Contact your Rain representative for the latest supported configurations.

Error handling

Errors return the HTTP status, its reason, and a message. Schema validation errors also carry "code": "FST_ERR_VALIDATION".

Payment account errors

Payment route errors

Best practices

  1. Validate bank details early: create payment accounts during user onboarding to catch errors before the user attempts to offramp.
  2. Use nicknames: assign meaningful nicknames to payment accounts for easy identification.
  3. Monitor webhooks: set up webhook handlers to track transfer status in real time.
  4. Handle failures gracefully: fiat transfers can fail due to bank issues. Implement retry logic and user notifications.

What’s next

Payment accounts

See the full request, response, and field reference for registering a bank account.

Payment routes

See the full request, response, and field reference for creating a payment route.

Set up onramps

Enable fiat deposits into crypto.

Partner-managed limits

Set limits on onramp and offramp volume and handle deposits that exceed them.

Set up webhooks

Receive transfer notifications as they happen.