Off Ramp integration

DOCS

Last updated: Sept 24th, 1:02am

Set up Off Ramp to let customers sell cryptocurrency directly from their crypto wallets using PayPal. The funds from the sale are deposited into their PayPal account in USD.

Eligibility

PayPal's Off Ramp supports the following:

  • Country: Available in all states in the US except Hawaii.
  • Cryptocurrencies: Ethereum, Bitcoin, Bitcoin Cash, Litecoin, and PYUSD.

How it works

  1. The customer logs in to their crypto wallet, selects their country, and enters the amount of cryptocurrency they want to sell.
  2. Your backend server calls the Configurations API to check if the customer is eligible to use PayPal as a payment method.
  3. Based on the Configurations API’s response, your Web3 wallet presents PayPal as payment option. The customer selects PayPal.
  4. Your backend server calls the Create Order Entry API to set up an order.
  5. Your crypto wallet launches the Off Ramp experience.
  6. The user logs in to PayPal, reviews, and approves the sell order in the PayPal window.
  7. The buyer is redirected back to your crypto wallet from the Off Ramp experience and signs the transaction.
  8. After signing the transaction, you'll get the receiver details from PayPal and initiate a transfer on the blockchain.
  9. Your backend server calls the Get Order Details API to get the status of the order.
  10. Your crypto wallet shows the status of the transaction based on PayPal's response.

Mobile flow

The,mobile,workflow,for,fiat-off-ramp,,showing,a,customer,logging,in,to,their,crypto,wallet,and,selling,cryptocurrency,through,PayPal.

Steps

The customer:

  • Logs in to their crypto wallet.
  • Enters the amount of cryptocurrency to sell.
  • Selects PayPal as the preferred way to sell, which redirects them to their PayPal account.
  • Logs in to PayPal and reviews the estimate of how much they may receive.
  • Confirms the transaction on crypto wallet which triggers the deposit of the crypto into PayPal.
  • Gets receipts through email with details of the exchange rate at which the sale was executed along with the associated fees.

API flow

The,back-end,API,flow,for,selling,crypto,currency.

Steps

A balance is added to the customer's account by identifying the eligibility of PayPal as a payment method, creating an order entry, and getting the status of an order.

  1. Call the Configuration API to show the eligibility of PayPal as a payment method.
  2. Create an order entry and returns a redirect URL to initiate the Off Ramp web flow.
  3. The customer reviews and confirms the order estimate on PayPal.
  4. Return to your platform and transfer on the blockchain
  5. Verify the status of the order.

Blockchain networks used

In the test environment, the transactions take place on the testnets. In the live environment, all cryptocurrency transactions are executed on the mainnet.

Cryptocurrencies Mainnet Testnet
Bitcoin (BTC) Bitcoin Mainnet Bitcoin Testnet
Bitcoin Cash (BCH) Bitcoin Cash Mainnet Bitcoin Cash Testnet
Litecoin (LTC) Litecoin Mainnet Litecoin Testnet
Ethereum (ETH) Ethereum Mainnet Ethereum Goerli Testnet
PayPal Stablecoin (PYUSD) Ethereum Mainnet Ethereum Goerli Testnet

To integrate this product, a PayPal representative will help you get a client ID and client secret, set up the stage environment, integrate the APIs, and go live.

1. Get client ID, client secret, and stage environment

A PayPal sales representative will help you get your client ID and client secret, which you can access through the PayPal developer dashboard. You'll need to use the client ID and client secret to get an access token to call the PayPal APIs.

The PayPal representative will also help you set up a stage environment and do a beta test after you onboard. The staging hostname is https://api.test51.stage.paypal.com.

PayPal APIs use OAuth2 to authenticate the requests. For more information, see Authentication.

2. Set up API calls

Call the APIs from your back-end server and not from the user’s device to ensure a secure connection between your system and PayPal.

The following APIs are used in this integration:

  1. POST v1/oauth2/token: Generates an access token. Use the access token in the authorization header to call other APIs. The access token expires after 8 hours.
  2. GET v1/crypto/configurations: Identifies PayPal as an eligible payment method.
  3. POST v1/crypto/order-entries: Creates an order entry in PayPal. You will be redirected to the PayPal Crypto URL which will initiate the flow on PayPal.
  4. GET v1/crypto/order-entries: Retrieves order entry details. Use this API to get the recipient address after the user has confirmed the order on the PayPal estimate screen.
  5. GET v1/crypto/orders: Get the order status after creating the order entry.

Call the Configuration API

The Configuration API returns the attributes to identify the eligibility of PayPal as a payment method. Copy the following code and modify the ACCESS-TOKEN with your access token.

The asset_symbol in the response can be one of the following:

    1* `ETH`: Etherium
    2* `PYUSD`: PayPal Stablecoin
    3* `BTC`: Bitcoin
    4* `BCH`: Bitcoin cash
    5* `LTC`: Litecoin

    Sample request

      1curl -v -k -X GET 'https://api-m.paypal.com/v1/crypto/configurations' \
      2 -H 'Authorization: Bearer ACCESS-TOKEN' \
      3 -H 'Content-Type: application/json'

      Sample response

        1HTTP status code: 200 OK
        2HTTP Headers:
        3"Content-Type": "application/json"
        4"paypal-debug-id": "566b15ad83c4f"
        5
        6Response payload:
        7{
        8 "configurations": [
        9 {
        10 "intent": "OFFRAMP",
        11 "country_codes": [
        12 "US"
        13 ],
        14 "asset_symbols": [
        15 "ETH",
        16 "PYUSD",
        17 "BTC",
        18 "BCH",
        19 "LTC"
        20 ],
        21 "attributes": {
        22 "channels": [
        23 "APP",
        24 "WEB",
        25 "EXTENSION"
        26 ],
        27 "currency_codes": [
        28 "USD"
        29 ],
        30 "regions": {
        31 "includes": {
        32 "include_all": true
        33 },
        34 "excludes": {
        35 "regions": [
        36 "HI"
        37 ]
        38 }
        39 }
        40 }
        41 },
        42 {
        43 "intent": "TOPUP",
        44 "country_codes": [
        45 "US"
        46 ],
        47 "asset_symbols": [
        48 "ETH",
        49 "PYUSD",
        50 "BTC",
        51 "BCH",
        52 "LTC"
        53 ],
        54 "attributes": {
        55 "channels": [
        56 "WEB"
        57 ],
        58 "currency_codes": [
        59 "USD"
        60 ],
        61 "regions": {
        62 "includes": {
        63 "include_all": true
        64 },
        65 "excludes": {
        66 "regions": [
        67 "HI"
        68 ]
        69 }
        70 },
        71 "min_limit": {
        72 "value": "5",
        73 "currency_code": "USD"
        74 },
        75 "max_limit": {
        76 "value": "10000",
        77 "currency_code": "USD"
        78 }
        79 }
        80 }
        81 ],
        82 "last_update_time ": "2023-02-25T01:20:00.000Z"
        83}

        Call the Order-Entry API

        This API creates an order entry in the crypto system that is used to create an order.

        Copy the following code and modify it as follows:

        • Set the asset_symbol to one of the following:

          • ETH: Etherium
          • PYUSD: PayPal Stablecoin
          • BTC: Bitcoin
          • BCH: Bitcoin cash
          • LTC: Litecoin
        • Replace ACCESS-TOKEN with your access token.

        • Set intent to OFFRAMP.

        Sample request

          1curl -v -k -X POST 'https://api-m.paypal.com/v1/crypto/orders-entries' \
          2 -H 'PayPal-Request-Id: RequestID123' \
          3 -H 'Authorization: Bearer ACCESS-TOKEN' \
          4 -H 'Content-Type: application/json' \
          5 -d '{
          6 "intent": "OFFRAMP",
          7 "asset_symbol": "ETH",
          8 "country_code": "US",
          9 "region": "CA",
          10 "asset_quantity": "0.01",
          11 "sender": {
          12 "type": "BLOCKCHAIN_ADDRESS",
          13 "id": "0xb794f5ea0ba39494ce839613fffba74279579268"
          14 },
          15 "partner": {
          16 "redirect_url": "/metamask/dashboard",
          17 "channel": "WEB"
          18 }
          19 }'

          Sample Response

            1HTTP status code: 201 Created
            2HTTP Headers:
            3"Content-Type": "application/json"
            4"paypal-debug-id": "566b15ad83c4f"
            5
            6Response payload:
            7{
            8 "id": "BCZXXK2PVTFDB",
            9 "intent": "OFFRAMP",
            10 "asset_symbol": "ETH",
            11 "country_code": "US",
            12 "region": "CA",
            13 "asset_quantity": "0.054",
            14 "sender": {
            15 "type": "BLOCKCHAIN_ADDRESS",
            16 "id": "0xb794f5ea0ba39494ce839613fffba74279579268"
            17 },
            18 "partner": {
            19 "redirect_url": "/metamask/dashboard",
            20 "channel": "WEB"
            21 },
            22 "token": "73895b68-1f45-11ed-861d-0242ac120002",
            23 "redirect_url": "https://www.paypal.com/myaccount/crypto/ETH/offramp/ingress?token=73895b68-1f45-11ed-861d-0242ac120002",
            24 "create_time": "2020-01-17T01:20:00.000Z"
            25 }

            Call the Get Order Entry API

            This API returns the Order Entry response with the receiver address details.

            The asset_symbol in the response can be one of the following:

              1* `ETH`: Etherium
              2* `PYUSD`: PayPal Stablecoin
              3* `BTC`: Bitcoin
              4* `BCH`: Bitcoin cash
              5* `LTC`: Litecoin

              Sample request

                1curl -v -k -X GET 'https://api-m.paypal.com/v1/crypto/order-entry?token=73895b68-1f45-11ed-861d-0242ac120002' \
                2 -H 'Authorization: Bearer ACCESS-TOKEN' \
                3 -H 'Content-Type: application/json'

                Sample response

                  1HTTP status code: 200 OK
                  2HTTP Headers:
                  3"Content-Type": "application/json"
                  4"paypal-debug-id": "566b15ad83c4f"
                  5
                  6Response payload:
                  7{
                  8 "order_entries": [
                  9 {
                  10 "id": "BCZXXK2PVTFDB",
                  11 "intent": "OFFRAMP",
                  12 "asset_symbol": "ETH",
                  13 "country_code": "US",
                  14 "region": "CA",
                  15 "asset_quantity": "0.054",
                  16 "sender": {
                  17 "type": "BLOCKCHAIN_ADDRESS",
                  18 "id": "0xb794f5ea0ba39494ce839613fffba74279579268"
                  19 },
                  20 "receiver": {
                  21 "type": "BLOCKCHAIN_ADDRESS",
                  22 "id": "0xa894f5ea0ba39494ce839613fffba74279579255"
                  23 },
                  24 "partner": {
                  25 "order_id": "10000001",
                  26 "redirect_url": "/metamask/dashboard",
                  27 "channel": "WEB"
                  28 },
                  29 "crypto_transaction": {
                  30 "transaction_hash": "f9bdcec15188150b0be44e1de4183e234541f4f96f24db86a03463e8a35213ed",
                  31 "nonce": "1",
                  32 "transaction_sign_time": "2023-01-17T01:20:00.000Z",
                  33 "broadcast_time": "2023-01-17T01:21:00.000Z"
                  34 },
                  35 "token": "73895b68-1f45-11ed-861d-0242ac120002",
                  36 "redirect_url": "https://www.paypal.com/myaccount/crypto/ETH/offramp/ingress?token=73895b68-1f45-11ed-861d-0242ac120002",
                  37 "create_time": "2020-01-17T01:20:00.000Z"
                  38 }
                  39 ]
                  40 }

                  Call the Get Orders API

                  This API returns the order status. For more information about calling the Get Orders API, see Reference.

                  The asset_symbol in the response can be one of the following:

                    1* `ETH`: Etherium
                    2* `PYUSD`: PayPal Stablecoin
                    3* `BTC`: Bitcoin
                    4* `BCH`: Bitcoin cash
                    5* `LTC`: Litecoin

                    Sample request

                      1curl -v -k -X GET 'https://api-m.paypal.com/v1/crypto/orders?order_entry_id=BCZXXK2PVTFDB' \
                      2 -H 'Authorization: Bearer ACCESS-TOKEN' \
                      3 -H 'Content-Type: application/json'

                      Sample response

                        1HTTP status code: 200 OK
                        2HTTP Headers:
                        3"Content-Type": "application/json"
                        4"paypal-debug-id": "566b15ad83c4f"
                        5
                        6Response payload:
                        7{
                        8 "orders": [
                        9 {
                        10 "id": "59L91489E3426142J",
                        11 "intent": "OFFRAMP",
                        12 "partner": {
                        13 "order_id": "10000001",
                        14 "channel": "WEB"
                        15 },
                        16 "type": "SELL",
                        17 "status": "COMPLETED",
                        18 "asset_symbol": "ETH",
                        19 "links": [
                        20 {
                        21 "href": "https://www.paypal.com/myaccount/activities/details/59L91489E3426142J",
                        22 "rel": "about"
                        23 }
                        24 ],
                        25 "token": "73895b68-1f45-11ed-861d-0242ac120002",
                        26 "offramp_summary": {
                        27 "amount_breakdown": {
                        28 "total": {
                        29 "currency_code": "USD",
                        30 "value": "100.00"
                        31 },
                        32 "net": {
                        33 "currency_code": "USD",
                        34 "value": "98.50"
                        35 },
                        36 "fee": {
                        37 "currency_code": "USD",
                        38 "value": "1.50"
                        39 }
                        40 },
                        41 "asset_quantity": {
                        42 "asset_symbol": "ETH",
                        43 "quantity": "0.054"
                        44 },
                        45 "asset_exchange_rate": {
                        46 "fiat_amount": {
                        47 "currency_code": "USD",
                        48 "value": "1867.00"
                        49 },
                        50 "asset_quantity": {
                        51 "asset_symbol": "ETH",
                        52 "quantity": "1.00"
                        53 }
                        54 },
                        55 "receiver": {
                        56 "type": "BLOCKCHAIN_ADDRESS",
                        57 "id": "0xb794f5ea0ba39494ce839613fffba74279579268"
                        58 },
                        59 "transaction_hash": "f9bdcec15188150b0be44e1de4183e234541f4f96f24db86a03463e8a35213ed"
                        60 },
                        61 "create_time ": "2022-02-25T01:20:00.000Z",
                        62 "update_time": "2022-02-25T01:20:00.000Z"
                        63 }
                        64 ]
                        65 }

                        3. Go live

                        Configure your live account to go live with your integration.

                        1. Set up live account

                        Create a new PayPal business account to act as your partner account.

                        When you have your PayPal business account set up, create a REST App and generate a client ID and client secret as follows:

                        1. Log in to the Developer Dashboard with your live PayPal business account credentials.
                        2. Go to Apps & Credentials and select Create App.
                        3. Provide an app name, select sandbox developer account, and then Create App.
                        4. Toggle to Live on the top right and copy the client ID and client secret.
                        5. After you create the live account REST app, send the following configuration details to your PayPal integration engineer:
                          • Business account email address for your live PayPal account.
                          • Client ID of the REST app created for the live business account.

                        It can take 5 business days to get an account configured after you send your information to a PayPal integration engineer. You will be notified when the configuration is done.

                        1. Change integration credentials to live credentials

                        After your live account is configured, update your code to use the live account credentials and call the live PayPal APIs.

                        1. Verify integration

                        Before your PayPal integration can go live, PayPal will verify the integration in a live environment. We will tell you when the live testing can begin. Provide PayPal with the email addresses of all the engineers who will be testing the integration.

                        As part of this production integration verification, we will ask for:

                        • The test PayPal transaction IDs in live and to make sure all use cases are tested.
                        • The seller PayPal email IDs of all the people who will be involved in the live testing.
                        • The test cases and screenshots of the completed testing.
                        • You to follow the transaction limits recommended by PayPal for each buyer. For example, $100 per user.
                        • You to ensure that NY residents are not allowed to participate in production testing. Your integration can go live when you've followed these steps and PayPal approves your integration.

                        Reports

                        Use reports and error cases to ensure your integration is properly set up. There are 2 types of reports:

                        1. Daily Transactions Report

                        Shares details of every transaction daily for an in-depth analysis. This report is available 1 day after data is collected.

                        Details included:

                        • Asset Symbol
                        • Crypto Address
                        • Chain-ID, fiat_amt
                        • Fiat_amt_usd
                        • Crypto_amt_out
                        • Crypto_fiat_amt_out
                        • Currency_code
                        • Asset_exchange_rate
                        • Transaction_Fee
                        • Blockchain_Transaction_Fee
                        • Partner_Fee
                        • Status
                        • Channel
                        • Order_Type
                        • Country

                        2. Monthly Revenue Share Report

                        Highlights total transaction volume and associated revenue share based on a negotiated rate. Typically available within the first few days of every month.

                        Details included:

                        • Transaction type count
                        • Volume
                        • Fee
                        • Revshare
                        • Crypto ID
                        • Country

                        Polling the Get Orders API

                        Polling can start only after you start the transfer on the blockchain.The status starts out as INITIATED. After PayPal receives the deposit, the status changes to PENDING. When the sale is completed, the status changes to COMPLETED.

                        Error cases

                        1. If an order is stuck in pending

                        This case is for orders with status=PENDING.

                        Start by polling every 10 seconds, then doubling the time up to 24 hours. If the status is still PENDING after an hour, it means that the blockchain is congested or there is a system issue.

                        1. GET Orders API returns an HTTP 500.

                        An HTTP 500 status indicates an issue with PayPal's servers. Start by polling every 10 seconds, then doubling the time up to 24 hours to allow the system to recover. PayPal will address these issues as soon as possible.

                        Security guidelines

                        Follow these guidelines when integrating Off Ramp.

                        Desktop implementation

                        Open the PayPal experience on desktop for the web or browser extensions in a new browser window or tab.

                        Mobile implementation

                        Use SFSafariViewController for iOS and Chrome Custom Tab for Android devices to open the PayPal experience on mobile. These frameworks are required for secure interactive web experiences, support privacy protection, and are the approved frameworks mandated by the PayPal security team. PayPal does not allow iFrames or WebViews. 

                        Server-side interaction

                        Only call APIs from your back-end server and not from the customer's device to ensure a secure connection between your system and PayPal's system.