Native Payment

A native Apple Pay payment consists of three steps:

  1. Get a quote — GET /sdk-partner/native/rate with payment_method=apple.
  2. Show Apple Pay — the Apple Pay payment sheet on your website or in your application, and the merchant session validation on your backend.
  3. Send the payment — POST /sdk-partner/native-mobile-pay/mobile-pay with the encrypted payment token from Apple.

Before you start, complete the Onboarding, including the certificate setup.

Sequence Diagram

This diagram provides a detailed, step-by-step visualization of the entire flow.

Native Apple Pay — integration flow Native Apple Pay — integration flow Partner Mercuryo **Partner Backend** **Partner Backend** **Partner Backend** **Partner Backend** **Browser & OS** **Apple Servers** **Apple Servers** **Apple Servers** **Mercuryo API** **Mercuryo API** **Mercuryo Widget** User **Partner Frontend** **Partner Backend** **Browser & OS** **Apple Servers** **Mercuryo API** **Mercuryo Widget** User Partner Frontend Partner Backend Browser & OS Payment Request API Apple Servers Mercuryo API Mercuryo Widget **Partner Backend** **Partner Backend** **Partner Backend** **Partner Backend** **Browser & OS** **Apple Servers** **Apple Servers** **Apple Servers** **Mercuryo API** **Mercuryo API** **Mercuryo Widget** Step 1 — Quote Choose   amount   and   currency Request   a   quote GET   /sdk-partner/native/rate Headers: Sdk-Partner-Token, Sdk-User-IP type = buy, payment_method = apple from, to, amount, is_total, network Check   that   native   Apple   Pay is   available   for   this   user 200   —   quote quote_token, fiat_amount, fiat_currency Quote alt [Quote rejected (e.g. 403034, 403109)] Offer   another   payment   method (e.g.   the   Mercuryo   widget) Step 2 — Apple Pay Show   the   Apple   Pay   button and   Mercuryo   Terms   of   Service Click   "Pay   with   Apple   Pay" new   PaymentRequest(config) merchantCapabilities, supportedNetworks, countryCode = LT, total.label = "Pay Mercuryo (via ...)", payer name, email, billing address request.show() Initiate   session validationURL onmerchantvalidation   (validationURL) Validate   the   merchant   session POST   validationURL mTLS with the partner's Merchant Identity Certificate merchantSession merchantSession event.complete(merchantSession) Apple   Pay   payment   sheet Confirm   the   payment   (e.g.   Face   ID) Generate   the   payment   token Encrypt   with   the   Payment Processing   Certificate   key Encrypted   paymentToken PaymentResponse paymentToken, payerEmail, payerName, billingContact Step 3 — Payment paymentToken   and   user   data Base64-encode   the   paymentToken, sign   the   request   body   (X-Signature) POST /sdk-partner/native-mobile-pay/mobile-pay Headers: Sdk-Partner-Token, X-Signature pay_token = base64(paymentToken) buy_token = quote_token email, first_name, last_name, billing_address, address, ip Decrypt   the   token and   process   the   payment alt [Accepted] 200   —   status:   pending [Declined] 200   —   declined status = order_failed, error_code [KYC required] 403   (403001)   —   KYC   required init_token, init_token_type init_token,   init_token_type Open   the   widget   with init_token,   init_token_type Pass   KYC [Error] 4xx   /   5xx   —   code,   message Payment   result response.complete('success') Final status Callback   with   the   final   status (X-Signature) Verify   X-Signature 200   OK Show   the   result Payment   result

Step 1 — Get a Quote

Before initiating the Apple Pay payment sheet, request a quote from Mercuryo — it is required to execute the payment.

API Endpoint: GET /sdk-partner/native/rate

Header Required Description
Sdk-Partner-Token One of Sdk-Partner-Token or Sdk-User-Token Your partner authentication token.
Sdk-User-Token One of Sdk-Partner-Token or Sdk-User-Token The user's token from sign-in. The quote is calculated for this user and contains kyc_limits — see KYC Before Payment.
Sdk-User-IP Yes The end user's real IP address.
Parameter Required Description
type Yes Must be buy.
from Yes Source currency code (e.g., USD).
to Yes Target currency code (e.g., BTC).
amount Yes The amount in the from currency.
payment_method Yes Must be apple.
is_total Yes How to interpret amount: true if it includes the fee, false if the fee is added on top. Pass it explicitly to ensure correct calculations.
network Yes The blockchain network of the purchased currency. Pass it to determine availability and correct fees. The wallet address in the payment request must belong to this network.

Example request:

GET /v1.6/sdk-partner/native/rate?type=buy&from=USD&to=BTC&amount=300&payment_method=apple&is_total=true&network=BITCOIN
Sdk-Partner-Token: YOUR_SDK_PARTNER_TOKEN
Sdk-User-IP: 203.0.113.42

Example response:

{
    "status": 200,
    "data": {
        "quote_token": "eyJ...",
        "currency": "BTC",
        "amount": "0.00234398",
        "fiat_amount": "300.00",
        "fiat_currency": "USD",
        ...
    }
}
  • quote_token — store it, you send it as buy_token in the payment request in Step 3.
  • Show the Apple Pay button only if you received a quote.

Quote Rejected

If native Apple Pay can't be used for this user, the quote request is rejected. Don't show the Apple Pay button — switch to the Mercuryo widget flow instead, so the purchase isn't lost:

Code Meaning
403034 The user's country isn't supported.
403109 Apple Pay is not available for this user.
{
    "status": 403,
    "code": 403109,
    "message": "This payment method is not available for current user."
}

Terms of Service

The payment is processed entirely on your side, without redirecting the user to the Mercuryo widget, so you MUST obtain the user's consent to Mercuryo's Terms of Service before the payment. This is a mandatory compliance requirement. Display a link to Mercuryo's Terms of Service either before initiating Apple Pay or on the Apple Pay screen.

For users from the United States, you must also display a link to Coinme's Terms of Service, in addition to Mercuryo's.

Example text (non-US users):

By continuing you accept Mercuryo Terms of Service and Privacy Policy

Example text (US users):

By continuing you accept Coinme Terms of Service, Mercuryo Terms of Service and Privacy Policy

Instead of hardcoding the links, you can get the current Terms of Service links for the user via GET /widget/terms, passing the user's ip_address and/or country. The response returns the relevant set of links: only Mercuryo's for non-US users, or both Mercuryo's and Coinme's for US users.

Step 2 — Show Apple Pay

Your frontend creates and displays the Apple Pay payment request, and your backend validates the merchant session with Apple. The modern and recommended way to integrate Apple Pay on the Web is the W3C standard Payment Request API.

Official documentation:

Payment Processing Disclosure

According to Apple's requirements, you MUST clearly indicate that the payment is processed through Mercuryo. This must be visible to the user on the Apple Pay payment sheet.

Example: "Pay Mercuryo (via [Your Company Name])"

Create the payment request

When the user clicks the "Pay with Apple Pay" button, your frontend creates an ApplePayPaymentRequest or PaymentRequest. The request MUST ask for all the user information that Mercuryo requires for processing, with the following values:

Parameter Value Reference
merchantCapabilities "supports3DS", "supportsCredit", "supportsDebit" ApplePayMerchantCapability
supportedNetworks "masterCard", "visa" supportedNetworks, Supported Networks
countryCode "LT" countryCode
currencyCode fiat_currency from the quote currencyCode
total.amount fiat_amount from the quote, exactly as returned ApplePayLineItem.amount
total.label Shows that the payment is processed through Mercuryo, e.g. "Pay Mercuryo (via [Your Company Name])" — see Payment Processing Disclosure ApplePayLineItem.label
requiredBillingContactFields Payer name, payer email and billing address requiredBillingContactFields

The amount and currency on the payment sheet MUST be exactly the fiat_amount and fiat_currency from the quote — don't round or recalculate them. Otherwise, the payment request is rejected with 400310. In the W3C Payment Request API, set them in total.amount.value and total.amount.currency.

The email, name and billing address the user provides on the payment sheet MUST be passed to Mercuryo in the payment request in Step 3.

Example PaymentRequest configuration:

const paymentRequest = {
    // ... your countryCode, currencyCode, total, etc.
    "requiredBillingContactFields": [
        "postalAddress",
        "name",
        "email"
    ],
    // Note: If using W3C Payment Request API, use options:
    // requestPayerName: true,
    // requestPayerEmail: true,
    // requestBillingAddress: true
    // requestShipping: false
    // ... other Apple Pay configuration
};

Your frontend then handles the onmerchantvalidation event by calling your backend to get a valid merchantSession. After the user authorizes the payment, your frontend receives the encrypted paymentToken.

Validate the merchant session

Your backend must expose an endpoint that your frontend calls during the onmerchantvalidation event. This endpoint:

  1. Receives the validationURL from your frontend.
  2. Makes a POST request to that URL using your Merchant Identity Certificate to authenticate with Apple's servers.
  3. Returns the resulting merchantSession object to your frontend.

Your frontend then confirms the merchant with event.complete(merchantSession), and Apple Pay shows the payment sheet for the user's confirmation.

Step 3 — Send the Payment

Once your frontend has the encrypted paymentToken, your backend sends it along with the other transaction details to Mercuryo's native processing endpoint.

API Endpoint: POST /sdk-partner/native-mobile-pay/mobile-pay

Header Required Description
Sdk-Partner-Token Yes Your partner authentication token.
X-Signature Yes The HMAC-SHA256 signature of the request body — see Signature.
Content-Type Yes application/json

Request Body

Field Type Description
pay_token string Required. The encrypted paymentToken received from Apple Pay, base64-encoded.
buy_token string Required. quote_token from the quote in Step 1.
email string Required. The user's email address, obtained from the Apple Pay payment sheet.
first_name string Required. The user's first name.
last_name string Required. The user's last name.
billing_address object Required. The user's billing address from the Apple Pay payment sheet, see the mapping below.
address string Required. The user's wallet address for the purchased crypto, in the network of the quote.
ip string Required. The user's IP address — the same end-user IP address you sent as Sdk-User-IP in the quote.
merchant_transaction_id string Optional. Your identifier for the transaction.

Mapping from the Apple Pay payment response. Apple returns the user's data in the ApplePayPaymentContact object (billingContact). Map its fields to the request as follows:

Request field ApplePayPaymentContact field
email emailAddress (or payerEmail in the W3C Payment Request API)
first_name givenName
last_name familyName
billing_address.country_code countryCode
billing_address.street_line_1 addressLines[0]
billing_address.street_line_2 addressLines[1]
billing_address.state_code administrativeArea
billing_address.city locality
billing_address.zip_code postalCode

Example request:

POST /v1.6/sdk-partner/native-mobile-pay/mobile-pay
Content-Type: application/json
Sdk-Partner-Token: YOUR_SDK_PARTNER_TOKEN
X-Signature: SIGNATURE
{
    "pay_token": "eyJwYXltZW50RGF0YSI6...",
    "buy_token": "eyJ...",
    "email": "user@example.com",
    "first_name": "John",
    "last_name": "Doe",
    "billing_address": {
        "country_code": "US",
        "street_line_1": "Asden Ct",
        "street_line_2": "123",
        "state_code": "OH",
        "city": "Reynoldsburg",
        "zip_code": "43068"
    },
    "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
    "ip": "203.0.113.42",
    "merchant_transaction_id": "your-order-123"
}

Success Response

The response returns the initial status of the transaction:

{
    "status": 200,
    "data": {
        "id": "28a3c125a28075453",
        "status": "pending"
    }
}

status: pending — the transaction has been accepted and is being processed. Close the Apple Pay sheet with a success indicator (response.complete('success')). The final status is delivered via Callbacks.

KYC Required

If the user has to pass KYC, the response is 403001 with a token to open the Mercuryo widget:

{
    "status": 403,
    "code": 403001,
    "message": "KYC verification needed.",
    "data": {
        "id": "0fcabca3a43709674",
        "status": "pending",
        "init_token": "0fcabca4c19121633",
        "init_token_type": "type_sdk_silent_sub"
    }
}

data.status is pending for non-US users and order_failed for US users. See KYC During Payment for how to hand the user over to the widget. To avoid this step, the user can pass KYC in advance — see KYC Before Payment.

Declined Payment

A payment declined by the card issuer or the payment provider returns HTTP 200 with status: order_failed:

{
    "status": 200,
    "data": {
        "id": "28a3c125a28075453",
        "status": "order_failed",
        "error_code": "insufficient_funds"
    }
}

Show the user that the payment failed and offer to try again with another card.

3D Secure Required

If the card requires 3D Secure, the response is 422001 — 3D Secure isn't supported in native Apple Pay:

{
    "status": 422,
    "code": 422001,
    "message": "3D Secure is not supported for this payment method."
}

Ask the user to pay with another card, or switch to the Mercuryo widget flow, so the purchase isn't lost.