Native Payment
A native Apple Pay payment consists of three steps:
- Get a quote —
GET /sdk-partner/native/ratewithpayment_method=apple. - Show Apple Pay — the Apple Pay payment sheet on your website or in your application, and the merchant session validation on your backend.
- Send the payment —
POST /sdk-partner/native-mobile-pay/mobile-paywith 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.
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 asbuy_tokenin 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:
- Receives the
validationURLfrom your frontend. - Makes a
POSTrequest to that URL using your Merchant Identity Certificate to authenticate with Apple's servers. - Returns the resulting
merchantSessionobject 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.