Provider availability. Mercuryo is live today. Additional providers are launching soon.
Platform: Apple Pay is iOS-only. On Android, and on iOS devices without Apple Pay, fall back to your card or hosted checkout flow.
How it works
- Your backend creates a headless order with your secret API key and receives a short-lived
sessionToken. - Your app presents the native Apple Pay sheet with PassKit.
- On authorization, your app posts the encrypted Apple Pay token to Meld’s process endpoint, authenticated with the
sessionTokenonly. Your API key never ships in the app binary. - Settlement is confirmed asynchronously to your backend via webhooks.
Before you begin
Meld account
- A Meld API key with payment access (start in sandbox, promote to production for go-live).
- Headless onramps enabled on your account, with Mercuryo enabled as a provider and native Apple Pay enabled for your target corridors.
WHITELABEL_NOT_ENABLED (HTTP 403).
Base URLs
Send
Meld-Version: 2026-05-01 (or later) on every request. Some endpoints in this guide require it, and sending it everywhere keeps response shapes consistent.
API compatibility. New fields may appear in responses without a version bump. Use flexible JSON parsing and do not reject unknown properties.
Supported corridors
- Mercuryo native Apple Pay does not process US or GB users, and it does not accept US or GB-issued cards. Use a supported corridor (for example EUR to BTC in France, or CAD corridors).
- Direct onramps only. Routes that swap into the destination asset are not eligible.
- Cards: Visa and Mastercard.
Apple Developer setup (one-time)
You need your own Apple Merchant ID and an Apple Pay Payment Processing certificate issued against a certificate signing request (CSR) that Meld provides.1
Create a Merchant ID
In Apple Developer, go to Certificates, Identifiers & Profiles → Identifiers → + → Merchant IDs and register a reverse-DNS, globally-unique ID such as
merchant.com.yourcompany.app.2
Enable Apple Pay on your App ID
Under Identifiers → your App ID → Capabilities, tick Apple Pay Payment Processing, click Configure, select your Merchant ID, and save.
“In-App Purchase” is a different capability, used for digital goods sold through Apple. It does nothing for Apple Pay.
3
Request the CSR from Meld
Ask your Meld representative for the Apple Pay Payment Processing CSR (a
.certSigningRequest file) tied to your merchant ID.4
Issue the certificate
In Apple Developer, go to Identifiers → Merchant IDs → your merchant ID → Apple Pay Payment Processing Certificate → Create Certificate. Answer No to the China-mainland question, upload Meld’s CSR, and download the issued
.cer.5
Return the .cer to Meld
Meld pairs the certificate with the private key held by the processor and registers your merchant ID on your account.
6
Add the app entitlement
In Xcode, open your app target’s Signing & Capabilities tab, add + Apple Pay, and include your merchant ID. This adds the
com.apple.developer.in-app-payments entitlement. Regenerate provisioning profiles afterwards.Who does what
Step 1 — Customer setup (once per user)
Every purchase needs a Meld customer that is KYC-approved and has an email on its Meld record. Mercuryo provisions its own customer record automatically on the first order using that email and the approved verification. There is no separate registration call, but if either prerequisite is missing the order fails.1a. Create the customer (with email)
Request body
- Get-or-create is keyed on
externalId. Reposting with the sameexternalIdreturns the existing customer and fills in any fields (such asemail) that were previously blank, without overwriting existing values. nameis a nested object, not top-levelfirstName/lastNamefields.- The response includes the Meld
id(this is thecustomerId). Store it against your user record.
1b. Run KYC (Meld-hosted)
There is no provider widget in a headless flow, so identity verification runs through Meld’s unified KYC:Request body
Response
url for the user (an in-app browser is fine) and let them complete verification.
- If KYC was already initiated for this customer, the
POSTreturns HTTP 409. CallPATCH /accounts/customers/{customerId}/kyc/initiatewith the same body to fetch a fresh URL for the existing verification. - KYC statuses:
PENDING,APPROVED,REJECTED,EXPIRED.
1c. Wait for approval
There are two ways to know a customer is approved:- Webhook (recommended). Subscribe to
CUSTOMER_KYC_STATUS_CHANGE. The payload includescustomerId,serviceProvider,status, andstatusUpdatedAt. - Poll. Call
GET /accounts/customers/{customerId}with theMeld-Versionheader. The response then includesserviceProviderCustomers, and the customer is ready when theSUMSUBentry showskyc.status: "APPROVED". Without the version header the response omits KYC information entirely.
email field, so you can verify both prerequisites in a single call.
Step 2 — Check corridor eligibility (optional)
Meld-Version: 2026-05-01:
Request body
serviceProvider: "MERCURYO", paymentMethodType: "APPLE_PAY", and integrationMode: "HEADLESS" means the corridor is catalog-eligible, and it gives you the live rate and fees to display.
Step 3 — Create the order (your backend)
Create the order when the user taps Buy, not ahead of time. The order embeds a live Mercuryo quote and the session token expires after about 30 minutes. A pre-created order can go stale before the user authorizes.Request body
Response (201 Created)
sessionToken— short-lived (roughly 30 minutes) token the app uses to authenticate the process call. Safe to hand to the device: it is scoped to this order only.merchantTransactionId— echo it back verbatim on the process call.merchantIdentifier— your merchant ID as configured on your Meld account. May be omitted if it is not configured; in that case your app should fall back to the merchant ID it already knows from its own entitlement.
Idempotency. Retrying with the same
X-Idempotency-Key after a success returns HTTP 200 with the original body (no duplicate order). A retry while the first request is still in flight returns HTTP 425 (Too Early). Retry shortly or mint a new key. Each user-initiated new attempt should use a fresh key and a fresh externalOrderId.POST /api/apple-pay-order) that injects customerId and returns the order JSON to your app. The secret API key never reaches the device.
Step 4 — Present the Apple Pay sheet (your app)
Use PassKit directly. The exact request configuration matters. These values are what Mercuryo expects:Swift (PassKit)
- Gate the button with
PKPaymentAuthorizationController.canMakePayments()and use Apple’sPKPaymentButtonfor the button itself (required for App Store review and Human Interface Guidelines compliance). - Merchant validation happens on-device. There is no merchant-validation network call in the native flow.
- React Native and Expo apps wrap this in a small native module. The configuration is identical.
Step 5 — Process the payment (your app)
In the delegate’sdidAuthorizePayment, post the encrypted token to Meld. This call is authenticated by the session token from the order, not your API key.
Request body
Response (200 OK)
Interpreting the result — read this twice
Treat the payment as accepted when the HTTP status is 200 anddata.status is one of:
status value) is a failure: complete the sheet with .failure and show an error.
Whatever the outcome, an accepted payment means “processing,” not “success.” Show a processing state; funds are only confirmed by webhook (Step 6).
Swift (delegate)
Step 6 — Settlement (your backend)
Settlement is always confirmed server-side via webhooks, never from the app’s process response. Subscribe to the transaction lifecycle events:
The payload includes
paymentTransactionId, paymentTransactionStatus, customerId, externalCustomerId, transactionType, and headlessOrderId. Correlate on headlessOrderId (the order id from Step 3) or on your externalOrderId via the transaction.
You can also poll (with Meld-Version: 2026-05-01):
GET /payments/transactions?customerIds={customerId}— list a customer’s transactions.GET /payments/transactions/{transactionId}— one transaction.
PENDING, AUTHORIZED, SETTLING, SETTLED, DECLINED, CANCELLED, REFUNDED, and FAILED.
Error reference
Errors return a consistent shape:Order creation (POST /crypto/order/headless/onramp)
Payment processing (POST /crypto/session/mercuryo/apple-pay/process)
Testing
- Real device required. The iOS Simulator cannot produce a usable Apple Pay token.
- Sign into the device with an Apple sandbox tester and add an Apple test card to Wallet.
- Use a sandbox Meld customer that is KYC-approved with an email on the record, and a non-US, non-GB corridor (for example EUR to BTC,
countryCode: "FR"). - Tap Buy. The native sheet opens directly, you authorize, and the process call returns
pending(success). Show “processing.” - Simulate settlement in sandbox with
POST /payments/mock/headless/simulateand body{ "externalOrderId": "order-123" }. Your webhook receives theSETTLINGthenSETTLEDtransitions.