Overview
Offramps let your users convert stablecoin to fiat through a persistent payment route. The process involves two steps:- Create a payment account: register the user’s bank account details as a payment account.
- Create an offramp payment route: set up the route that converts crypto to fiat and sends it to the payment account.
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 statuspending_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.
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.
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
Step 1: create a payment account
Before creating an offramp payment route, you must register the user’s bank account as a payment account. CallPOST /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 callingPOST /payment-routes.
See Create an offramp payment route
for the full request, response, and field reference.
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
0xfollowed by 40 hexadecimal characters (for example,0x1234567890abcdef1234567890abcdef12345678). - Solana: must be a valid Solana address in base58 format (32-44 characters).
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 withcurrency 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 withdestination.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
UseGET /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.
Manage payment routes
UseGET /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:- Crypto received: Rain detects the incoming stablecoin transfer. Deposits under 2.00 of the source token don’t create a transfer.
- Transfer created: Rain creates a transaction of type
transferand sends atransactionTransferwebhook with actioncreated. - Conversion: Rain converts stablecoin to fiat.
- Fiat transfer: Rain sends funds to the user’s bank account via the specified rail.
- Transfer completed: the transfer settles, and Rain sends a
transactionTransferwebhook with actioncompleted.
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 atransfer transaction that you can query via
the Transactions API. Filter
by type=transfer to see all transfer transactions.
Example transfer transaction response:
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
- Validate bank details early: create payment accounts during user onboarding to catch errors before the user attempts to offramp.
- Use nicknames: assign meaningful nicknames to payment accounts for easy identification.
- Monitor webhooks: set up webhook handlers to track transfer status in real time.
- 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.