On- and Off-Ramp Redirect Guide (1.6.0)

About

On- and Off-Ramp — integrated via Redirect — allows you to create a widget for buying and selling crypto currencies. Unverified users can buy crypto up to EUR 699.

Where Mercuryo Operates

Mercuryo is operational and allows end-users from all countries, except for the following list. The below details are used to identify whether end-user’s country is from non-operational list:

  1. End-user's IP address.
  2. End-user’s card issuer country.
  3. Documents provided for passing KYC procedure which verify end-user’s country of residence.

Note that the Off-Ramp operations are available in selected countries.

Compatibility

Use Mercuryo wrappers for iOS and Android to add the widget to your mobile app.

Card Payments

Mercuryo accepts Mastercard and Visa.

Mobile Payment Services

Apple Pay

WebView Custom Tab
Safari Fully Compatible Incompatible
Google Chrome Incompatible Incompatible
Chromium Browsers Incompatible Incompatible

Google Pay

WebView Custom Tab
Safari Fully Compatible Fully Compatible
Google Chrome Fully Compatible Fully Compatible
Chromium Browsers Fully Compatible Fully Compatible

Note the list of countries where Google Pay is supported for payments on websites and apps. Also, keep in mind the list of countries where Mercuryo operates.

Testing

Start with the Sandbox environment to:

  • Walk through the scenarios.
  • Test endpoints.
  • Test the transaction operation.

To access the Sandbox environment, ask your integration manager to give you credentials and whitelist all your IP addresses for using with the Sandbox environment.

Testnets

Testnet Address Supported Cryptocurrency
BTC Testnet msBE6aCaAesegu4VzbQW3L5xWBL8vi15Q7 Bitcoin
ETH Sepolia 0xA14691F9f1F851bd0c20115Ec10B25FC174371DF Ethereum (ETH) and USDT

Sandbox URLs

  • Dashboard https://sandbox-dashboard.mrcr.io.
  • Widget https://sandbox-exchange.mrcr.io.
  • API Host https://sandbox-api.mrcr.io.

Sandbox Payment Card Details

  • Card Number 4111 1111 1111 1111.
  • Expiration Date any future date.
  • CVV 321.
  • Cardholder Name name + surname.
  • Enter hint in the additional window.

Widget Creation

To start using the On- and Off-Ramp widget, get dashboard credentials, sign in, and set up your widget. You will need the widget ID and signature parameters to enable buying and selling crypto.

To create a widget, go to Widgets > Add Widget.

Enter https://exchange.mercuryo.io in the Domain URL field. Leave no symbols or backspaces after the https://exchange.mercuryo.io URL. The widget won’t work properly and you’ll see the widget.mercuryo.io refused to connect message.

Widget Parameters

The On- and Off-Ramp widget uses these URL parameters. These parameters can fill in up to 90% of the information and the user will have to enter only numbers.

Blockchain Wallet Signature

Use the signature parameter to protect your widget ID and parameters against the forgery. The signature parameter is always required. A signature is generated using this algorithm: signature = sha512(address+secret). There is no space between address and secret.

Steps:

  1. Go to Widgets and select your widget. Find Secret Key at the bottom.
  2. Paste the address and secret — addresssecret — into the SHA512 calculator to generate a signature.
  3. Append the signature to the widget URL.

Example:

The signature is verified before the 3-D Secure step. If the signature is invalid, the Signature is invalid message will be displayed. The user won't be able to complete the operation.

Integrating On-Ramps using Custom Tab on Android

Custom Tabs present effective solution for apps like yours, particularly when it comes to Google Pay integration. They are not just about aesthetics or user experience; they are mainly about functionality, specifically enabling Google Pay to work seamlessly within your app.

Here's a Kotlin code snippet to illustrate how you can launch our exchange URL, "https://exchange.mercuryo.io", within a Custom Tab:

kotlinCopy codeval url = "https://exchange.mercuryo.io"
val intent = Builder().build()
intent.launchUrl(requireContext(), Uri.parse(url))

One advantage of using Custom Tabs is that the URL stays consistent with WebView integration. This helps to maintain a unified user experience, but more importantly, it ensures that critical functionalities like Google Pay work without any glitches.

Custom Tabs also offer some customization options, although they may not be the primary concern in this context. You can change the toolbar color, set custom enter and exit animations, and make other adjustments. For example:

kotlinCopy codeval customTabsIntent = CustomTabsIntent.Builder()
   .setToolbarColor(Color.BLUE)
   .build()
customTabsIntent.setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left)
customTabsIntent.setExitAnimations(this, R.anim.slide_in_left, R.anim.slide_out_right)

While Custom Tabs integration might feel like a necessary step rather than an optional enhancement, our data does indicate a positive outcome. Custom Tab integration can lead to higher conversion rates for mobile payment options. It's a way to ensure that the desired functionalities, especially Google Pay, are working correctly.

In conclusion, integrating Custom Tabs with our exchange URL is a practical move to ensure that Google Pay operates smoothly within your app. Though it may feel like a forced solution, it comes with benefits that align with the current trends in mobile commerce. Please contact your integration manager to discuss further how this integration can best serve your specific needs.

Callbacks

Mercuryo sends callbacks when the transaction status changes. Set up a callback URL to receive callbacks.

Steps

  1. Sign in the Dashboard.
  2. Go to Widgets.
  3. Select a widget.
  4. Fill in the field Callback URL.

Go to Widget Callbacks to browse callbacks, resend a callback, and send a test callback.

Callback Body

{
   "data":{
      "id":"0ab3f70c72c0f5056",
      "fee":"11.80",
      "card":{
         "number":"1111"
      },
      "rate":"25756.99",
      "type":"buy",
      "user":{
         "email":"sf@mercuryo.io",
         "phone":"+3570000000",
         "uuid4":"b5086805-4b83-4415-8a00-5c1ad43210b6",
         "country_code":"de"
      },
      "amount":"0.00148310",
      "status":"paid",
      "currency":"BTC",
      "created_at":"2023-09-07 07:32:33",
      "updated_at":"2023-09-07 07:32:46",
      "fiat_amount":"50.00",
      "partner_fee":"0.00",
      "created_at_ts":1694071953,
      "fiat_currency":"USD",
      "updated_at_ts":1694071966,
      "payment_method":"card",
      "card_masked_pan":null,
      "merchant_transaction_id":"123"
   }
}

Callback Signature

The sign key is used for checking the callback signature. When the transaction status changes, the merchant receives a request with transaction data from Mercuryo. If you use callbacks, you can set up the signature check.

You can check the signature by generating a hash with the HMAC sha256 algorithm and a key from the Sign Key field in the Dashboard. Check the X-Signature HTTP header against the generated hash.

Transactions

Buy

  1. new: a new transaction was created.
  2. pending: standing by for 3-D Secure or descriptor verification.
  3. cancelled: a transaction was canceled usually due to the timeout.
  4. paid: the money deposited from a payment card.
  5. order_failed: a transaction was rejected by a bank.
  6. order_scheduled: the money is held on the card, standing by for the KYC verification; if the verification fails, the money will be returned.
  7. order_verified_not_complete: the verification is successful, an order was queued on an exchange.
  8. failed_exchange: Mercuryo failed to exchange for various reasons.
  9. descriptor_failed: the user entered an invalid descriptor three times.

Sell

  1. new: a new transaction was created.
  2. pending: a transaction in progress.
  3. succeeded: the money transferred to the card.
  4. failed: a transaction failed.

Deposit

  1. new: a new transaction was created.
  2. pending: a transaction in progress.
  3. completed: the money transferred to Mercuryo.
  4. failed: a transaction failed.

Withdraw

  1. new: a new transaction was created.
  2. pending: a transaction in progress.
  3. completed: the money transferred to the user address.
  4. failed: a transaction failed.

KYC

Know Your Customer (KYC) procedures are indispensable for financial institutions to verify their clients and keep business on the safe side.

KYC procedures help Mercuryo fight financial crime. Therefore, it prevents mixing your users’ funds with illegal funds of bad actors and perpetrators of any sort. Identity verification is a legal obligation to be compliant with AML/CFT laws. Mercuryo is strongly committed to the highest industry standards of clients' security, which requires protecting the integrity of the entire financial system.

Find out more about the requirements for the US and Russia.

SumSub is the major KYC procedure provider of Mercuryo.

Identity Verification

These documents can be acceptable identity verification:

  • Passport.
  • ID card.
  • Driving license.

The document must have:

  • Full name.
  • MRZ code.
  • Citizenship.
  • Date of birth.
  • Document number.
  • Issuing authority.
  • Date of issue.

Meet these requirements:

  • The document must be unexpired.
  • The document must be scanned or photographed.
  • All the corners and sides of the document must be visible.
  • All the information must be clear and readable.

Integration

There are three cases for integrating KYC procedures depending on your user onboarding:

  1. If you don’t implement any KYC procedures.
  2. If you implement SumSub KYC procedures.
  3. If you implement other KYC procedures.

Contact your account manager if you have any questions regarding KYC procedures.

Standard

If you don’t implement any KYC procedures, we provide the SumSub interface to do KYC verification directly in Mercuryo.

There is a standard flow when a user does the KYC procedures directly in the widget. See the identity verification requirements above.

SumSub Share Token

If you have already integrated SumSub KYC procedures, you can share your SumSub applicants with Mercuryo using the share token. The SumSub share token is used by Mercuryo to share applicants and complete the KYC procedures. So, the users won’t have to do the verification twice. See how it works.

Make sure that your applicant’s documents are up-to-date before sharing an applicant using the share token. Mercuryo can accept the share token only once due to the SumSub architecture. The Sandbox environment requires approving users manually.

Steps

  1. Use https://api.sumsub.com/resources/accessTokens/-/shareToken to generate the share_token parameter value.
  2. The applicantId and forClientId=Mercuryo parameters are required. Enter the generated value in the widget URL.
    1. Example: https://exchange.mercuryo.io/?share_token=[value].

Submit Documents

Manually send us users’ documents.

Send us users’ scanned documents. The documents you send us are Base64-encrypted. We verify the user after receiving the documents and then a user is given a KYC status. Still, the users will have to do the liveness test in the SumSub interface.

Submitting documents is a part of the silent sign-up.

Silent Authentication

The silent authentication is a tool that makes signing in Mercuryo easier for users.

The silent authentication allows for skipping the authentication in the widget: just pass the token in the URL, so that the user doesn't have to enter credentials.

You have to ask the user to agree to the Terms of Service on your front end to share the user data with Mercuryo.

You have to allow Mercuryo to use the user data for the registration and with third parties.

There are two cases of the silent authentication depending on your user onboarding:

  1. If you don’t implement any KYC procedures: Silent Sign-Up.
  2. If you implement SumSub KYC procedures: Silent Sign-Up + SumSub KYC.

Silent Sign-Up

For users without a Mercuryo account.

The Sdk-Partner-Token header is required. Contact your integration manager to get the header.

Required parameters for POST /sdk-partner/sign-up:

  1. email.
  2. accept.

Steps

  1. Use POST /sdk-partner/sign-up to get init_token and init_token_type.
    1. init_token expires after the first time it was passed or after one hour.
  2. Pass the init_token and init_token_type parameters in the URL.
  3. Redirect the user to the widget.
    1. Redirect example: https://exchange.mercuryo.io/?init_token_type=sdk_partner_authorization&init_token=0a25dd714163a9006.

Silent Sign-Up + SumSub KYC

Sign up verified users and share them with Mercuryo using SumSub share token.

The Sdk-Partner-Token header is required. Contact your integration manager to get the header.

Required parameters for POST /sdk-partner/sign-up:

  1. email.
  2. accept.
  3. share_token.

Steps

  1. Use POST /sdk-partner/sign-up to get init_token and init_token_type.
    1. init_token expires after the first time it was passed or after one hour.
  2. Pass the init_token and init_token_type parameters in the URL.
  3. Redirect the user to the widget.
    1. Redirect example: https://exchange.mercuryo.io/?init_token_type=sdk_partner_authorization&init_token=0a25dd714163a9006.

Silent Sign-In

For already registered users.

The Sdk-Partner-Token header is required. Contact your integration manager to get the header.

Steps

  1. Use POST /sdk-partner/login to get init_token and init_token_type.
    1. init_token expires after the first time it was passed or after one hour.
  2. Pass the init_token and init_token_type parameters in the URL.
  3. Redirect the user to the widget.
    1. Redirect example: https://exchange.mercuryo.io/?init_token_type=sdk_partner_authorization&init_token=0a25dd714163a9006.

On-Ramp. Crypto Purchase.

Buying crypto with fiat money using a payment card.

Steps

  1. Use GET /lib/currencies to get available currencies.
  2. Use GET /public/card-countries to get available countries.
  3. Use GET /public/data-by-ip to check user's location.
  4. Use GET /public/currency-limits to get user limits.
  5. Use GET /widget/buy/rate to see the transaction total.
  6. Use GET /sdk-partner/transactions to get the transaction status.
  7. Redirect the user to your widget. Also, you can preselect parameters from this table.
    1. Example: the user buys USDT with EUR 200. The URL is https://exchange.mercuryo.io/?fiat_currency=EUR&currency=USDT&fiat_amount=200.

Off-Ramp. Crypto Sell.

Selling crypto for fiat money and withdrawing funds to a payment card.

The user must be signed in and verified (valid KYC). Mercuryo won’t complete the transaction if the verification is expired.

Selling crypto is disabled for a newly created widget. Contact your integration manager to enable this feature.

EUR and USD are the only available currencies for selling crypto.

Steps

  1. Use GET /lib/currencies to get available crypto currencies.
  2. Use GET /public/card-countries to get available countries.
  3. Use GET /public/data-by-ip to check user's location.
  4. Use GET /public/currency-limits to get user limits.
  5. Use GET /widget/sell/rate to see the transaction total.
  6. Use GET /sdk-partner/transactions to get the transaction status.
  7. Redirect the user to your widget. Also, you can preselect parameters from this table.
    1. Example: the user sells USDT 200 for EUR. The URL is https://exchange.mercuryo.io/?fiat_currency=EUR&currency=USDT&amount=200&type=sell.

Customization

To customize the Mercuryo Widget, follow these instructions in Figma.

Customize the appearance: put a theme name at the end of this URL https://exchange.mercuryo.io/?theme=THEME_NAME.

Themes

  1. exmo
  2. bitx
  3. btc_alpha
  4. xzen
  5. ch
  6. savl
  7. spatium
  8. now_payments
  9. invity
  10. phemex
  11. lumi
  12. trustwallet
  13. roobee
  14. kickex
  15. quantfury
  16. simpleswap
  17. 1inch
  18. digifinex
  19. mycelium
  20. coinstats
  21. advantechLight
  22. advantechDark
  23. swapspace
  24. tonkeeper
  25. bitpapa
  26. bitpapaDark
  27. czixlight
  28. czixdark
  29. swapspace2
  30. 3commas_light
  31. 3commas_dark
  32. 3commas_web_dark
  33. 3commas_web_light
  34. unionbtc arctic
  35. dark_ch
  36. light_ch
  37. white_market
  38. exolix
  39. grapherex_light
  40. grapherex_dark
  41. haru_light
  42. haru_dark

To get Mercuryo fonts, download this archive.

To get Mercuryo logos, download this archive.

Helper

/lib/currencies

Get supported currencies

Responses
200

OK

403

Forbidden

500

Internal server error

get/lib/currencies
Response samples
application/json
{}

/public/card-countries

Get countries with card payment available

Responses
200

OK

403

Forbidden

500

Internal server error

get/public/card-countries
Response samples
application/json
{
  • "data": [
    ],
  • "status": "200"
}

Limits by currencies

Parse widget limits from antifraud and map it

Request
query Parameters
widget_id
required
string

Widget ID

from
required
string

Currency from

to
required
string

Currency to

type
string

Direction type

is_total
boolean

Is total

amount
number

Amount

Responses
200

OK

get/public/currency-limits
Response samples
application/json
{
  • "code": 0,
  • "data": {
    },
  • "message": "string",
  • "status": 0
}

Get geo data for IP

Get geo data for IP

Request
query Parameters
ip
required
string

IP address

Responses
200

OK

get/public/data-by-ip
Response samples
application/json
{
  • "data": {
    },
  • "status": 0
}

Get rates endpoint

Get rates endpoint

Request
query Parameters
widget_id
required
string

Widget ID

use_partner_fee
boolean

Use partner fee

use_fee
boolean

Use fee

flatten_result
boolean

Flatten result

is_amount_without_fee
boolean

Is Amount Without Fee

network
required
string

Network layer-2

Responses
200

OK

get/public/rates
Response samples
application/json
{
  • "data": {
    },
  • "status": 0
}

/sdk-partner/transactions

Transactions for sdk partners

Securitysdk-partner-token
Request
query Parameters
merchant_transaction_id
string

Merchant transaction id

date_start
string

Unix Timestamp search from

date_end
string

Unix Timestamp search end

status
string

Transaction status

limit
string
Default: "50"

Limit of rows max 50, min 5

offset
string

Type of client

Responses
200

Get transactions

401

401000: Authorization failed

403

Error codes:
* 403007: Transaction lock error. Please contact support;
* 403020: IP is blacklisted;
* 403026: Resource is unavailable. Please contact support;

500

500001: Various reasons, check the message field

get/sdk-partner/transactions
Response samples
application/json
{
  • "data": [
    ],
  • "next": "string",
  • "prev": "string",
  • "status": "200",
  • "total": "100"
}

Sell

/public/convert

Get off-ramp conversion rates

Request
query Parameters
from
required
string

Currency to convert from

to
required
string

Currency to convert to

type
required
string

Conversion type (buy/sell)

amount
required
string

Amount to convert

widget_id
required
string

Widget id

is_total
boolean
Default: "true"

Is passed amount with fee

payment_method
string

Payment method. Available: card, volt, apple, google

address
string

User wallet address. Available only if feature enabled for widget

ip_address
string

User IP address. Feature must be enabled for widget.

card_type
string

Card payment system. Feature must be enabled for widget. Note that parameter can be used only with ip_address

country
string

User country. Feature must be enabled for widget. Note that ip_address takes precedence over country

Responses
200

OK

400

Error codes:
* 400001: Validation error, check the data field;
* 400005: Amount off limits

403

Forbidden

500

Internal server error

get/public/convert
Response samples
application/json
{
  • "data": {
    },
  • "status": "200"
}

/public/currencies-sell

Get fiat and crypto currencies available for sell operation

Responses
200

OK

403

Forbidden

500

Internal server error

get/public/currencies-sell
Response samples
application/json
{
  • "data": [
    ],
  • "status": "200"
}

/widget/sell/rate

Get currency sell rate

Request
query Parameters
from
required
string

Currency to convert from

to
required
string

Currency to convert to

type
required
string

Transactions type

amount
required
string

Amount to convert

is_total
boolean
Default: "true"

Is passed amount with fee

widget_id
required
string

Widget id

network
string

Cryptocurrency network

payment_method
string
Default: "card"

Payment method for fees and kyc

Enum: "card" "fiat_card" "sepa"
Responses
200

OK

400

Error codes:
* 400001: Validation error, check the data field;
* 400005: Amount off limits

403

Forbidden

500

Internal server error

get/widget/sell/rate
Response samples
application/json
{
  • "data": {
    },
  • "status": "200"
}

Buy

/public/currencies-buy

Get fiat and crypto currencies available for buy operation

Responses
200

OK

403

Forbidden

500

Internal server error

get/public/currencies-buy
Response samples
application/json
{
  • "data": [
    ],
  • "status": "200"
}

/widget/buy/rate

Get currency rate

Request
query Parameters
from
required
string

Currency to convert from

to
required
string

Currency to convert to

type
required
string

Transactions type

amount
required
string

Amount to convert

is_total
boolean
Default: "true"

Is passed amount with fee

widget_id
required
string

Widget id

network
string

Cryptocurrency network

payment_method
string

Payment method. Available: card, volt

address
string

User wallet address. Available only if feature enabled for widget

card_bin
string

User card bin

card_id
string

Mercuryo card id

ip_address
string

User IP address. Feature must be enabled for widget.

card_type
string

Card payment system. Feature must be enabled for widget. Note that parameter can be used only with ip_address

country
string

User country. Feature must be enabled for widget. Note that ip_address takes precedence over country

Responses
200

OK

400

Error codes:
* 400001: Validation error, check the data field;
* 400005: Amount off limits

403

Forbidden

500

Internal server error

get/widget/buy/rate
Response samples
application/json
{
  • "data": {
    },
  • "status": "200"
}

/widget/mobile-pay/rate

Get currency rate

Request
query Parameters
from
required
string

Currency to convert from

to
required
string

Currency to convert to

type
required
string

Transactions type

amount
required
string

Amount to convert

is_total
boolean
Default: "true"

Is passed amount with fee

widget_id
required
string

Widget id

network
string

Cryptocurrency network

payment_method
required
string

Mobile payment method

Enum: "Apple" "Google"
address
string

User wallet address. Available only if feature enabled for widget

Responses
200

OK

400

Error codes:
* 400001: Validation error, check the data field;
* 400005: Amount off limits

401

Can't get rates data

403

Forbidden

500

Internal server error

get/widget/mobile-pay/rate
Response samples
application/json
{
  • "data": {
    },
  • "status": "200"
}

Feedback

/public/feedback

Send feedback

Request
Request Body schema: application/json
required

email user

string
Responses
200

OK

400

Error codes:
* 400001: Validation error, check the data field;

500

Internal server error

post/public/feedback
Request samples
application/json
"example@example.com"
Response samples
application/json
{
  • "data": [ ],
  • "status": "200"
}

User

/sdk-partner/login

Login user

Securitysdk-partner-token
Request
Request Body schema: application/json
required

JSON Body

email
string

SDK user's email. Field is required unless phone or user_uuid4 is provided

phone
string

SDK user's phone number. Field is required unless phone or user_uuid4 is provided

user_uuid4
string

SDK user's uuid. Field is required unless email or phone is provided

Responses
200

OK

401

401000: Authorization failed

403

Error codes:
* 403007: Transaction lock error. Please contact support;
* 403020: IP is blacklisted;
* 403031: Login failed. Check the message field;

404

User is not found

405

405000: Method Not Allowed

500

Internal server error

post/sdk-partner/login
Request samples
application/json
{
  • "email": "someemail@gmail.com",
  • "phone": "+1234567890",
  • "user_uuid4": "ea159262-3aec-42e8-9cda-f2e5dcba576a"
}
Response samples
application/json
{
  • "data": {
    },
  • "status": "200"
}

/sdk-partner/sign-up

Sign-up user

Securitysdk-partner-token
Request
Request Body schema: application/json
required

JSON Body

accept
required
boolean

accept

email
string

SDK user's email. Field isrequired unless phone is provided

language_code
string

ISO 639-1 standard language codes, defaults to en-US

share_token
string

SumSub share token

Responses
200

OK

401

401000: Authorization failed

403

Error codes:
* 403007: Transaction lock error. Please contact support;
* 403020: IP is blacklisted;
* 403031: Sign-up failed. Check the message field;

405

405000: Method Not Allowed

500

Internal server error

post/sdk-partner/sign-up
Request samples
application/json
{
  • "accept": "true",
  • "email": "someemail@gmail.com",
  • "language_code": "en-US",
  • "share_token": "_act-sbx-16a1bb3a-a43a-40ec-97fb-1771e487b5c2"
}
Response samples
application/json
{
  • "data": {
    },
  • "status": "200"
}