Onramp API referenceBeta
Use the onramp API reference as you build the embeddable onramp.
Refer to the following developer flows when building your onramp integration.
Integrate the onramp into your application
Before you can use live mode, Stripe must approve your onramp application.
Get started
To integrate an application with the onramp:
After you onboard onto Stripe, use the Dashboard to grab your secret and publishable API keys.
Generate a
CryptoOnrampSession
server-side.On the server, expose a new API endpoint (for example,
myserver.
) that makes a call to the Stripecom/mint-onramp-session POST /v1/crypto/onramp_
endpoint. This “mints” an onramp session with Stripe that you can use with new or returning users. You need to mint one session per user.sessions Run the following command:
Command Linecurl -X POST https://api.stripe.com/v1/crypto/onramp_sessions \ -u
:sk_test_4eC39HqLyjWDarjtT1zdp7dcYou receive a response similar to the following:
{ "id": "cos_0MYvmj589O8KAxCGp14dTjiw", "object": "crypto.onramp_session", "client_secret": "cos_0MYvmj589O8KAxCGp14dTjiw_secret_BsxEqQLiYKANcTAoVnJ2ikH5q002b9xzouk", "created": 1675794053, "livemode": false, "status": "initialized", "transaction_details": { "destination_currency": null, "destination_amount": null, "destination_network": null, "fees": null, "lock_wallet_address": false, "source_currency": null, "source_amount": null, "destination_currencies": [ "btc", "eth", "sol", "usdc", "xlm" ], "destination_networks": [ "bitcoin", "ethereum", "solana", "stellar" ], "transaction_id": null, "wallet_address": null, "wallet_addresses": null } }
This endpoint returns error codes if Stripe can’t create onramp sessions. See the supportability section below to learn why this might happen. We recommend that you render the onramp component conditional when a user gets an HTTP status
200
during session creation, providing a fallback UI that can deal with session creation errors.
Use the session client_secret in the frontend
To initialize the onramp component, you need:
- Your publishable API key.
- The
client_
from your request tosecret POST /v1/crypto/onramp_
.sessions
The following code mounts an iframe on the #onramp-element
node, which hosts all of the onramp. You can use an event listener to improve your application’s functionality. For example, you can resume operation in a decentralized application (Dapp) after cryptocurrency purchases. See the frontend events for all of the events a user can subscribe to.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Crypto Onramp</title> <meta name="description" content="A demo of hosted onramp" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <script src="https://js.stripe.com/v3/"></script> <script type="text/javascript" src="https://crypto-js.stripe.com/crypto-onramp-outer.js"></script> </head> <body> <div id="onramp-element" style="max-width: 500px"> <script> const stripeOnramp = StripeOnramp(
); initialize(); // initialize onramp element with client secret function initialize() { const clientSecret = "cos_1LLgeLF5fgi2FFcAWx8RlsMT_secret_WNA1VOkwZ0bHMc9MtOuyJ4vto00EMsLP7Io"; const onrampSession = stripeOnramp.createSession({clientSecret}); onrampSession .mount("#onramp-element"); } </script> </body> </html>"pk_test_TYooMQauvdEDq54NiTphI7jx"
CryptoOnramp element renders and takes over
After the above CryptoOnramp
html element renders, the frontend client drives the interface. As the state of the session changes and we collect more details around transaction_
, the CryptoOnrampSession
object updates accordingly. Webhooks and frontend events are generated for every status transition that occurs. By using frontend event listeners, you can redirect users back to your application user flow after the onramp session completes.
(Optional) Change the appearance of the onramp
To enable darkmode, include an appearance struct in the session creation call from above.
const onrampSession = stripeOnramp.createSession({ clientSecret: clientSecret, appearance: { theme: 'dark' }, });
If you don’t specify the appearance, the onramp defaults to a light theme. You can also change the theme after the onramp renders by calling:
onrampSession.setAppearance({ theme: newTheme });
You can use branding settings to upload your logo and brand colors which automatically apply to onramp sessions created with your platform API key.
Pre-populate transaction parameters
To deliver a seamless onramp user flow, you can pre-populate some of the parameters of the onramp session. For example, a Dapp or wallet would already have a user’s wallet_
. You can achieve this during session creation as follows:
curl -X POST https://api.stripe.com/v1/crypto/onramp_sessions \ -u
: \ -d "wallet_addresses[ethereum]"="0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2" \ -d "source_currency"="usd" \ -d "destination_currency"="eth" \ -d "destination_network"="ethereum" \ -d "destination_amount"="0.1234"sk_test_4eC39HqLyjWDarjtT1zdp7dc
You receive a response similar to the following:
{ "id": "cos_0MYvnp589O8KAxCGwmWATYfA", "object": "crypto.onramp_session", "client_secret": "cos_0MYvnp589O8KAxCGwmWATYfA_secret_LhqXJi2lvbMCYhVHfrHGfUfX6009qtZPtV7", "created": 1675794121, "livemode": false, "status": "initialized", "transaction_details": { "destination_currency": "eth", "destination_amount": "0.123400000000000000", "destination_network": "ethereum", "fees": null, "lock_wallet_address": false, "source_currency": "usd", "source_amount": null, "destination_currencies": [ "btc", "eth", "sol", "usdc", "xlm" ], "destination_networks": [ "bitcoin", "ethereum", "solana", "stellar" ], "transaction_id": null, "wallet_address": null, "wallet_addresses": { "bitcoin": null, "ethereum": "0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2", "polygon": null, "solana": null, "stellar": null, "destination_tags": null } } }
We allow the following parameters to be pre-populated:
wallet_
: The suggested wallet address to deliver crypto to (the default selection on the wallet attach screen)addresses lock_
: Whether or not to lock the suggested wallet addresswallet_ address source_
: The fiat currency for the transaction (currency usd
andeur
only for now)source_
: The amount of fiat currency to use for the purchase of crypto (mutually exclusive with destination amount)amount destination_
: The default crypto network for this onramp (for example,network ethereum
)destination_
: The default cryptocurrency for this onramp session (for example,currency eth
)destination_
: The amount of cryptocurrency to purchase (mutually exclusive with the source amount)amount destination_
: An array of cryptocurrencies you want to restrict to (for example,currencies [eth, usdc]
)destination_
: An array of crypto networks you want to restrict to (for example,networks [ethereum, polygon]
)
Refer to the API reference for more details on the specific requirements and how they impact users in the onramp UI.
Pre-populate customer information
To reduce user friction during the onramp flow and increase conversion, you might want to pre-populate some of the required KYC information for the user if you’ve already collected it within your application.
Throughout the flow, users are required to provide at least:
- First name
- Last name
- Date of birth
- SSN
- Home address (country, address line 1, address line 2, city, state, postal code)
The onramp API provides the ability to pre-populate all of those fields except for SSN. To pre-populate this information, you can provide it using the customer_
parameter in the OnrampSession creation API.
Example request:
curl -X POST https://api.stripe.com/v1/crypto/onramp_sessions \ -u
: \ -d "customer_information[email]"="john@doe.com" \ -d "customer_information[first_name]"="John" \ -d "customer_information[last_name]"="Doe" \ -d "customer_information[dob][year]"=1990 \ -d "customer_information[dob][month]"=7 \ -d "customer_information[dob][day]"=4 \ -d "customer_information[address][country]"="US" \ -d "customer_information[address][line1]"="354 Oyster Point Blvd" \ -d "customer_information[address][line2]"="Apt 1A" \ -d "customer_information[address][city]"="South San Francisco" \ -d "customer_information[address][state]"="CA" \ -d "customer_information[address][postal_code]"="94080"sk_test_4eC39HqLyjWDarjtT1zdp7dc
Response:
{ "id": "cos_1MbuUeAEFtmWU4EVBFZS0gce", "object": "crypto.onramp_session", "client_secret": "cos_1MbuUeAEFtmWU4EVBFZS0gce_secret_zPsPPytwNU6mMKh1Bmz7ymXGi00ILwwyGeG", "created": 1676504072, "livemode": false, "status": "initialized", "transaction_details": { "destination_currency": null, "destination_amount": null, "destination_network": null, "fees": null, "lock_wallet_address": false, "source_currency": null, "source_amount": null, "destination_currencies": [ "btc", "eth", "sol", "usdc", "xlm" ], "destination_networks": [ "bitcoin", "ethereum", "solana", "polygon", "stellar" ], "transaction_id": null, "wallet_address": null, "wallet_addresses": null } }
We allow the following parameters to be pre-populated:
customer_
—Freeform string for the user’s emailinformation. email customer_
—Freeform string for the user’s first nameinformation. first_ name customer_
—Freeform string for the user’s last nameinformation. last_ name customer_
—Integer for the user’s birth yearinformation. dob. year customer_
—Integer for the user’s birth monthinformation. dob. month customer_
—Integer for the user’s birth dayinformation. dob. day customer_
—String of the two letter country code for the user’s country of residenceinformation. address. country customer_
—Freeform string for the user’s address line oneinformation. address. line1 customer_
—Freeform string for the user’s address line twoinformation. address. line2 customer_
—Freeform string for the user’s cityinformation. address. city customer_
—String of the two letter state code for US states (the full state name also works), for example, “CA” or “California”information. address. state customer_
—Freeform string for the user’s postal codeinformation. address. postal_ code
All of the fields are optional and you can provide any subset of them for pre-population. However, if you provide date of birth, you must also provide all of year
, month
, and day
(that is, not just one or two of the birth fields).
Handle user supportability and fraud
Stripe enforces limitations on the onramp product for both user supportability and in the event of fraud attacks.
Check user supportablity
As noted in Feature set, the onramp is only available in the United States at this time.
Pass customer_
during session creation so we can preemptively check the aforementioned limitation. The endpoint returns HTTP 400
with code=crypto_
if the customer is in a geography we can’t support (based on customer_
)
You might want to hide the onramp option from users in this case. Otherwise, our onramp UI renders in a disabled
state.
Here’s a sample request and response (400) illustrating this behavior:
curl -X POST https://api.stripe.com/v1/crypto/onramp_sessions \ -u
: \ -d "customer_ip_address"="8.8.8.8" \sk_test_4eC39HqLyjWDarjtT1zdp7dc
{ "error": { "type": "invalid_request_error", "code": "crypto_onramp_unsupportable_customer", "message": "Based on the information provided about the customer, we’re currently unable to support them." } }
Handle fraud attacks
Stripe serves as the business of record and takes on the liability for disputes and fraud. Stripe has deep expertise in risk management, but we might decide to temporarily restrict creation of onramp sessions if we detect a high risk situation (for example, if we see active attacks and exploits).
If we need to shut off the API because of an unbounded fraud attack, we’ll return the following when anyone attempts to create a new session:
curl -X POST https://api.stripe.com/v1/crypto/onramp_sessions \ -u
: \sk_test_4eC39HqLyjWDarjtT1zdp7dc
You recieve a response similar to the following:
{ "error": { "type": "api_error", "code": "crypto_onramp_disabled", "message": "The v1/crypto/onramp_sessions endpoint has been disabled temporarily. Stripe will get in contact with you about details of the outage.", "updated": 1652025690 } }
API reference
CryptoOnrampSession resource
The CryptoOnrampSession
resource looks as follows:
{ "id": "cos_1Ke0052eZvKYlo2Clh7lJ50Q", "object": "crypto.onramp_session", // One of the most important parts of the resource is going to be this // client_secret. This will be passed from the server to the client to // drive a single session using our embedded widget. "client_secret": "cos_1Ke0052eZvKYlo2Clh7lJ50Q_secret_f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8", "created": 1647449225, "livemode": true, // A hash representing monetary details of the transaction this session represents "transaction_details": { // The consumer's wallet address (where crypto will be sent to) "wallet_addresses": null | { "ethereum": "0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2", "solana": "bufoH37MTiMTNAfBS4VEZ94dCEwMsmeSijD2vZRShuV", "bitcoin": "1BuFoRu4W1usdnj1nPSfnNUgUm9BM6JtnV", "stellar": "GBUCRQX2GXV2CCPNBVB6FMXORFRNXXQMZ5RN2GMH2KZNMH7O4WON5DDN", // Mapping of assets to the destination tag where the crypto will be sent to (for supported assets) "destination_tags": null | { "xlm": "123456789" } }, // A fiat currency code "source_currency": null | "usd", "eur", // The amount of fiat we intend to onramp - excluding fees "source_amount": null | "1.01", // The selected destination_currency to convert the `source` to. // This should be a a crypto currency, currency code // If destination_currencies is set, it must be a value in that array. "destination_currency": null | "usdc", // The specific crypto network the `destination_currency` is settled on. // If destination_networks is set, it must be a value in that array. "destination_network": null | "ethereum", // If a platform wants to lock the currencies an session will support, // they can add supported currencies to this array. If left null, the experience // will allow selection of all supported destination currencies. "destination_currencies": null | ["eth", "usdc", "btc" , "xlm"], // If a platform wants to lock the supported networks, they can do so through // this array. If left null, the experience will allow selection of all // supported networks. "destination_networks": null | ["solana", "ethereum", "polygon" , "stellar"], // The amount of crypto the customer will get deposited into their wallet "destination_amount": null | "1.012345678901234567", // Details about the fees associated with this transaction // Note: The currency associated with fee is always the same as // source_currency // Note: We won't know what fees to charge until after the customer has // passed status=onboarding "fees": null | { // The cost associated with moving crypto from Stripe to the end // consumers's wallet. e.g: for ETH, this is called "gas fee", // for BTC this is a "miner's fee". "network_fee_amount": "1.23", // Stripe's cut of the transaction "transaction_fee_amount": "1.23", }, // The total amount of source currency the consumer needs to give us to // complete the transaction. Equivalent to source_amount + fees. "source_total_amount": null | "3.47", // Pointer to the on network transaction id/hash // This will only be set if the sessions hits the stauts=fulfillment_complete // and we've transferred the crypto successfully to the external wallet. // E.g: https://etherscan.io/tx/0xc2573af6b3a18e6f7c0e1cccc187a483f61d72cbb421f7166970d3ab45731a95 "transaction_id": null | "0xc2573af6b3a18e6f7c0e1cccc187a483f61d72cbb421f7166970d3ab45731a95" }, // The status of the OnrampSession. // One of = {initialized, rejected, // requires_payment, fulfillment_processing, fulfillment_complete} "status": "initialized" }
CryptoOnrampSession state machine
The status
field represents a state machine for the session with the following states:
initialized
: The application has newly minted the onramp session on the server-side, but the customer hasn’t used it yet. Sessions are in this state until the user onboards and is ready to pay.rejected
: We rejected the customer for some reason (KYC failure, sanctions screening issues, fraud checks).requires_
: The user has completed onboarding or sign-in and gets to the payment page. If they attempt payment and fail, they stay in this status.payment fulfillment_
: The customer successfully completed payment. We haven’t delivered the crypto they purchased yet.processing fulfillment_
: The customer was successfully able to pay for crypto and we have confirmed delivery.complete
CryptoOnrampSession operations
All endpoints require authentication with your API key. The authentication header is omitted in the example requests.
Applications can perform the following operations on a CryptoOnrampSession
:
- Create a session
- Get an existing session
Create Session
Endpoint: POST /v1/crypto/onramp_
Parameter name | Type (optional?) default: ? | Details |
---|---|---|
wallet_addresses | String (optional) default: null | The end customer’s crypto wallet address (for each network) to use for this transaction.
For assets that use destination tags or memos, you can nest a |
source_currency | String (optional) default: null | The default source fiat currency for the onramp session.
|
source_amount | String (optional) default: null | The default amount of fiat (in decimal) to exchange into crypto.
|
destination_networks | Array<String> (optional) default: null | The list of destination crypto networks user can choose from.
|
destination_currencies | Array<String> (optional) default: null | The list of destination cryptocurrencies a user can choose from.
|
destination_network | String (optional) default: null | The default destination crypto network.
|
destination_currency | String (optional) default: null | The default destination cryptocurrency.
|
destination_amount | String (optional) default: null | The default amount of crypto to exchange into.
|
customer_ip_address | String (optional) default: null | The IP address of the customer the platform intends to onramp. If the user’s IP is in a region we can’t support, we return an HTTP 400 with an appropriate error code. We support IPv4 and IPv6 addresses. Geographic supportability is checked again later in the onramp flow, which provides a way to hide the onramp option from ineligible users for a better user experience. |
Sample request and response:
curl -X POST https://api.stripe.com/v1/crypto/onramp_sessions \ -u
: \ -d "wallet_addresses[ethereum]"="0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2" \ -d "source_currency"="usd" \ -d "destination_currency"="eth" \ -d "destination_network"="ethereum" \ -d "destination_currencies[]"="eth" \ -d "destination_networks[]"="ethereum"sk_test_4eC39HqLyjWDarjtT1zdp7dc
{ "id": "cos_0MYvv9589O8KAxCGPm84FhVR", "object": "crypto.onramp_session", "client_secret": "cos_0MYvv9589O8KAxCGPm84FhVR_secret_IGBYKVlTlnJL8UGxji48pKxBO00deNcBuVc", "created": 1675794575, "livemode": false, "status": "initialized", "transaction_details": { "destination_currency": "eth", "destination_amount": null, "destination_network": "ethereum", "fees": null, "lock_wallet_address": false, "source_currency": "usd", "source_amount": null, "destination_currencies": [ "eth" ], "destination_networks": [ "ethereum" ], "transaction_id": null, "wallet_address": null, "wallet_addresses": { "bitcoin": null, "ethereum": "0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2", "polygon": null, "solana": null, "stellar": null, "destination_tags": null } } }
Get session
Endpoint: GET /v1/crypto/onramp_
Parameter name | Type (optional?) default: ? | Details |
---|---|---|
No supported parameters for this operation! |
Here’s an example request:
curl -X GET https://api.stripe.com/v1/crypto/onramp_sessions/cos_0MYvv9589O8KAxCGPm84FhVR \ -u
:sk_test_4eC39HqLyjWDarjtT1zdp7dc
You receive a response similar to the following:
{ "id": "cos_0MYvv9589O8KAxCGPm84FhVR", "object": "crypto.onramp_session", "client_secret": "cos_0MYvv9589O8KAxCGPm84FhVR_secret_IGBYKVlTlnJL8UGxji48pKxBO00deNcBuVc", "created": 1675794575, "livemode": false, "status": "initialized", "transaction_details": { "destination_currency": "eth", "destination_amount": null, "destination_network": "ethereum", "fees": null, "lock_wallet_address": false, "source_currency": "usd", "source_amount": null, "destination_currencies": [ "eth" ], "destination_networks": [ "ethereum" ], "transaction_id": null, "wallet_address": null, "wallet_addresses": { "bitcoin": null, "ethereum": "0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2", "polygon": null, "solana": null, "stellar": null, "destination_tags": null } } }
Validation and errors
Condition | HTTP status | Error code |
---|---|---|
We’re unable to mint new sessions because of an incident | 400 | crypto_ |
Based on the customer_ parameter, we’re unable to support the given consumer. | 400 | crypto_ or crypto_ |
Malformed customer_ is passed in to the /v1/crypto/onramp_ endpoint | 400 | customer_ |
source_ and destination_ are mutually exclusive, but the platform set both. | 400 | crypto_ |
One of destination_ and destination_ is set, but the other one isn’t | 400 | crypto_ |
The combination of destination_ and destination_ isn’t valid | 400 | crypto_ |
source_ is set, but source_ isn’t set | 400 | crypto_ |
source_ isn’t a positive number | 400 | crypto_ |
destination_ is set, but destination_ isn’t set | 400 | crypto_ |
destination_ isn’t a positive number | 400 | crypto_ |
The combination of destination_ and destination_ doesn’t have any supported currencies | 400 | crypto_ |
destination_ isn’t included in destination_ | 400 | crypto_ |
destination_ isn’t included in destination_ | 400 | crypto_ |
At least one wallet address in wallet_ is associated with a network that isn’t included in destination_ | 400 | crypto_ |
No wallet addresses were provided in wallet_ but lock_ was set to true | 400 | crypto_ |
The business hasn’t set the business_ or business_ fields. These are populated in the Dashboard under Public business name and Business website | 400 | crypto_ |
Get multiple sessions
Endpoint: GET /v1/crypto/onramp_
Fetch multiple onramp sessions at the same time using the list endpoint.
Webhooks
We send a crypto.
webhook every time the status of an onramp session changes post creation. We won’t send one when a new session is created. You can configure webhooks in the Dashboard.
The resource used by the webhook will be the CryptoOnrampSession
resource above:
{ "id": "evt_123", "object": "event", "data": { "object": { "id": "cos_0MYvv9589O8KAxCGPm84FhVR", "object": "crypto.onramp_session", "client_secret": "cos_0MYvv9589O8KAxCGPm84FhVR_secret_IGBYKVlTlnJL8UGxji48pKxBO00deNcBuVc", "created": 1675794575, "livemode": false, "status": "initialized", "transaction_details": { "destination_currency": "eth", "destination_amount": null, "destination_network": "ethereum", "fees": null, "lock_wallet_address": false, "source_currency": "usd", "source_amount": null, "destination_currencies": [ "eth" ], "destination_networks": [ "ethereum" ], "transaction_id": null, "wallet_address": null, "wallet_addresses": { "bitcoin": null, "ethereum": "0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2", "polygon": null, "solana": null, "stellar": null, "destination_tags": null } } } } }
Frontend events
Here is the list of frontend events that you can subscribe to:
// when the onramp UI is rendered { type: 'onramp_ui_loaded', payload: {session: OnrampSession}, } // when the onramp session object is updated { type: 'onramp_session_updated', payload: {session: OnrampSession}, } // for modal overlay render mode only { type: 'onramp_ui_modal_opened', payload: {session: OnrampSession}, } { type: 'onramp_ui_modal_closed', payload: {session: OnrampSession}, }
As shown above, events can be subscribed to and unsubscribed to using the standard addEventListener/removeEventListener
functions over OnrampSession. You can use '*'
to match all events.
Session persistence
You can use session persistence to help you provide notifications and keep users engaged with the onramp after fulfilling their purchase.
Advantages of session persistence
You might want to persist an onramp session across user visits in some instances. For example, when a user’s onramp session is disrupted or dropped, you could prompt them and provide ways to resume the onramp session later. Or if a user refreshes the page after completing the payment, you can retain the ability to notify them when a previous onramp purchase was fulfilled. For this reason, the OnrampSession object is stateful and stored as a server side resource. By initializing the onramp UI using a previously used OnrampSession client secret, users return to where they left off.
Session persistence configuration
A client secret is a unique identifier for the onramp session that stores the lifecycle of a session without leaking sensitive payment information. However, it exposes private information such as wallet addresses. Don’t log it, embed it in URLs, or expose it to anyone other than the customer. Make sure that you have TLS on any page that includes the client secret. If you have a Web2-like account structure, you could link OnrampSession to your user object and fetch it upon authentication. For an account-less Web3 application, it would add user friction to require the use of message signing for authentication. Privacy-preserving local storage yields an acceptable user experience.