Skip to main content
Your backend creates the order, the Meld SDK presents it, and settlement arrives by webhook. The integration is the same for every provider: one create call, one mount, the same callbacks and webhooks. The provider only changes what you set up once and what the customer needs before the order.

Providers

Eligibility tells you what a provider still needs for a given customer, so you don’t have to hardcode the column above.

Stripe

  • Credentials. In production, Stripe orders run on your own Stripe account. Stripe onboards it for its embedded crypto onramp and registers your app as a trusted application. Then add your Stripe keys to your Meld account as in provider setup, together with the Link OAuth client ID, client secret and headless API version Stripe gives you, and point a Stripe webhook for crypto.onramp_session.updated at the webhook URL the Meld dashboard shows for the integration. In sandbox, Meld provides the Stripe integration: see Headless testing.
  • Link. Stripe signs the customer in to Link with the email on the Meld customer, and sends the one-time code to the phone on that Link account.
  • Identity. Stripe runs its own KYC, and the SDK fills it from Unified KYC, so the customer only types their SSN. Meld doesn’t refuse a Stripe order without Unified KYC, but the customer then fills in Stripe’s forms by hand. Stripe can also ask for an ID document or a selfie, depending on the amount and its own risk checks.
  • Cards. CREDIT_DEBIT_CARD runs the same flow, with Stripe collecting the card. It needs no Apple setup.

Coinbase

  • Merchant of record. Coinbase takes the payment on its own checkout, and the SDK opens Coinbase’s Apple Pay sheet from it. You need no Apple setup.
  • Before the order. Verify the email and phone with serviceProvider: "COINBASEPAY", and record the customer’s acceptance of Coinbase’s agreements. Both are in Eligibility.
  • Limits. Coinbase caps each customer weekly and over their lifetime. Over the lifetime cap, the order is refused with CUSTOMER_NOT_PAYMENT_READY until the customer completes the limitUpgrade process.
  • Quote. Send walletAddress on the headless quote, so Coinbase prices the same checkout the order uses.
  • Settlement. Meld creates the transaction once Coinbase reports the payment, usually a minute or more after onPaymentSubmitted. An order the customer never pays sends no webhook.
  • Sandbox. Sandbox covers everything up to creating the order. The current SDKs can’t present a sandbox Coinbase order (it ends in PRESENTATION_FAILED), so test the sheet in production with a small order.

Before you begin

  1. Create the customer, and give them what the provider needs before the order (see Providers)
  2. Configure webhooks
  3. Do the Apple setup below, once per provider that needs it

Apple Developer setup

Mercuryo, Banxa and Stripe need a merchant identifier and a payment processing certificate. Coinbase needs neither. You will need:
  • An Apple Developer account with admin rights on your team
  • The payment processing CSR, which your Meld representative provides. For Stripe, see Stripe’s certificate
  • Xcode, to add the capability and regenerate provisioning profiles
1

Create a merchant identifier

A merchant identifier names your app to Apple Pay. It lives under your Apple Developer account, not Meld’s.
  1. Go to Certificates, Identifiers & Profiles
  2. Click Identifiers in the sidebar, then +
  3. Select Merchant IDs, then Continue
  4. Enter a description and an identifier — it must start with merchant. (e.g. merchant.com.yourcompany.yourapp)
  5. Click Continue, review, then Register
If your app already has a merchant identifier, reuse it, unless another processor’s certificate is on it. See Supporting more than one provider.Give your Meld representative the identifier for each environment you use. Meld configures it on your account, and your orders carry it to the SDK. Send it well before your first order in that environment.
2

Create a payment processing certificate

This certificate is what the Apple Pay token is encrypted to. It must be created from a CSR Meld provides — never generate your own for this step, because the processor holds the matching private key.Once you have the .certSigningRequest file from your Meld representative:
  1. Go to Certificates, Identifiers & Profiles
  2. Click Identifiers, filter by Merchant IDs, and select the one from Step 1
  3. Under Apple Pay Payment Processing Certificate, click Create Certificate
  4. Upload the .certSigningRequest file Meld provided
  5. Click Continue, then Download to save the .cer file
  6. Send the .cer file back to your Meld representative
Meld passes it to the processor. Wait for confirmation before going further — payments fail until the processor holds it.
3

Configure Xcode

  1. Open your project in Xcode and select your app target
  2. Go to the Signing & Capabilities tab
  3. Click + Capability and select Apple Pay
  4. Under the Apple Pay capability, click + and add the merchant identifier from Step 1
  5. Regenerate provisioning profiles
On React Native, the Expo config plugin does this for you — pass the same merchant identifier.
Certificate expiry. Apple payment processing certificates expire every 25 months. When yours approaches expiry, repeat Step 2 — Meld will provide a fresh CSR. An expired certificate fails every payment.

Supporting more than one provider

Use one merchant identifier per processor. Apple encrypts a merchant identifier’s tokens to a single payment processing certificate, so two processors cannot share one. If you offer Apple Pay through two providers, run the setup once for each, with its own identifier. Your app’s Apple Pay entitlement must hold every identifier: add each in Step 3, or list each in the Expo plugin’s merchantIds. The sheet does not open for an identifier the entitlement lacks.

Stripe’s certificate

Stripe decrypts the token, so the certificate comes from a CSR issued by the Stripe account the order runs on:
  • Production: your Stripe account. Download the CSR from the Stripe Dashboard’s iOS certificate settings, and upload the .cer file Apple returns to Stripe, not to Meld.
  • Sandbox: Meld’s Stripe sandbox. Your Meld representative gives you the CSR, and you send them the .cer file.
Use a separate merchant identifier for each environment. Until Meld has configured it, Stripe Apple Pay orders in that environment fail with 400 PAYMENT_METHOD_NOT_SUPPORTED.

Registering your domain — web only

On the web there is no native sheet: the button renders on your origin, so that origin has to be registered with the provider before Apple will let it present one. Registration is not self-serve. Contact your Meld representative with the domains you need registered — Meld brokers each one with the provider, so allow for a round trip per domain, and do it before you plan to go live. Every domain you serve the button from needs its own registration, staging included. Native-only integrations skip this entirely.

Flow overview

An Apple Pay purchase, with the system sheet presented over the app

Your servers handle the order and never see payment credentials. The SDK presents whatever the order carries: the sheet itself, the provider’s own SDK, or the provider’s checkout.

1. Quote, then check eligibility

Every order starts here, not just the first one. Get a quote with integrationMode=HEADLESS. It prices the order and names the providers that can take it. Name the chain with destinationNetworkCode on the quote request, and send the same value on the order. Then check eligibility for the provider you picked, and collect whatever is outstanding before you create the order.

2. Create the order

Endpoint: POST /crypto/order/headless/onramp Headers: Meld-Version: 2026-05-01, X-Idempotency-Key: <uuid>
Carry the quote’s values through unchanged, and send the customer’s public IP as clientIpAddress. Creating the order charges nothing. Response, for this Mercuryo order. ... marks values elided here:
paymentMethodResponseDetails and headlessPresentation depend on the provider: a Stripe order carries a bootstrap for Stripe’s SDK, and a Coinbase order a link to Coinbase’s checkout. You don’t read them. Return the whole order to your client verbatim, and don’t log it: it carries short-lived credentials for this order.

3. Present the sheet

Check the device can pay before you offer the button, then hand the order to the SDK.
On React Native and iOS, pass the Apple Pay inputs for every Apple Pay order. They carry what the sheet shows that the order does not, and they must match the order’s amount and currency. On the web there is nothing to pass: the provider’s component draws the button. A native sheet draws nothing into your view. On React Native, keep the component mounted anyway: see Mount the order. onCancel fires when the user dismisses the sheet. Return them to the amount screen. Every onError code, and whether a payment may exist, is in Error codes. Stripe and Coinbase run only in an iOS app. Check Meld.capabilities before you offer the button.

4. Settlement

onPaymentSubmitted means the user authorised the payment. Authorisation is not settlement. Unmount when it fires and move the user to your own processing screen. Credit them when Meld’s TRANSACTION_CRYPTO_COMPLETE webhook reaches your backend. No SDK event tells you the money moved.

Errors on order creation

Errors use the standard envelope. Unless the table says otherwise, nothing was charged.

Troubleshooting


Test in sandbox

See Headless testing.