Migrating from the Service Provider API to the Network Partner API
This guide is for teams who already integrated White-Label discovery against the legacy Service Provider API (/service-providers/properties/* and /service-providers/limits/*) and need to move to the new Network Partner API (/network-partner/*).
It maps every legacy discovery call to its replacement, shows the before/after request and response for each, and lists the behavioral changes to watch for.
Only discovery moved. The three transaction endpoints are unchanged — you do not need to touch them:
POST /payments/crypto/quotePOST /crypto/session/widgetGET /payments/transactions/{transactionId}
Authorization: BASIC {apiKey} on every request, against https://api-sb.meld.io (sandbox) or https://api.meld.io (production). Network Partner routes carry per-method limits as of Meld-Version: 2026-02-03.What changed at a glance
- Everything is category-scoped. Each discovery call now takes a
category— for the retail ramp that isCRYPTO_ONRAMP(buy) orCRYPTO_OFFRAMP(sell). The legacy endpoints were direction-agnostic; the new ones return results for one direction at a time. - One currencies endpoint. The separate
fiat-currenciesandcrypto-currenciesendpoints merged into a singlesupported/currenciescall, switched bytype=FIAT|CRYPTO. - Limits moved into routes. There is no standalone limits endpoint. Per-(partner, payment-method)
min/maxnow live onsupported/routes, alongside the partners and rails that serve a currency pair — so limits are now direction-aware. - Response shapes changed. Several fields were renamed and a few were added or dropped (see each section below).
- Routes are ordered by direction. The
source/destinationpath segments follow the flow direction, not “fiat then crypto” (see Routes).
Endpoint mapping
| Legacy endpoint (removed) | New endpoint |
|---|---|
GET /service-providers/properties/countries | GET /network-partner/supported/countries?category={CATEGORY} |
GET /service-providers/properties/defaults/by-country | GET /network-partner/defaults/{country}/{category} |
GET /service-providers/properties/fiat-currencies | GET /network-partner/supported/currencies?category={CATEGORY}&country={c}&type=FIAT |
GET /service-providers/properties/crypto-currencies | GET /network-partner/supported/currencies?category={CATEGORY}&country={c}&type=CRYPTO |
GET /service-providers/properties/payment-methods | GET /network-partner/supported/payment-methods?category={CATEGORY}&country={c}¤cyCode={f} |
GET /service-providers/limits/fiat-currency-purchases | GET /network-partner/supported/routes/{category}/{country}/{source}/{destination} |
1. Countries
- Now requires
category(CRYPTO_ONRAMPorCRYPTO_OFFRAMP). The supported set can differ by direction, so call it once per direction you offer. countryName→name, and aflagemoji is now included.states[]is no longer returned here. Collect the US state in your own UI and pass it as thesubdivisionquery param on Routes.
2. Country defaults
- Country and category are now path params (
/defaults/{country}/{category}), not acountries=query list. - The response is a single object (or
null), no longer an array — drop thecountryDefaults[0]indexing. defaultCurrencyCode→currencyCode,defaultPaymentMethods→paymentMethods.
3. Currencies
The two legacy endpoints are now one, switched bytype.
- One endpoint for both sides — pass
type=FIATortype=CRYPTO.categoryandcountryare required. - The legacy crypto list was returned under a
cryptoCurrencieswrapper; both fiat and crypto now return a singlecurrencieswrapper. currencyName→name;networkCode→chainCode;networkNameis dropped.- New fields:
decimalPlaces(use it for client-side formatting),symbol, andcontract(token contract address) to disambiguate tokens on the same chain. - Optional filters:
network(e.g.ETHEREUM,SOLANA),partner,paymentType,providerCurrencyCode.
For off-ramp, swap the category to
CRYPTO_OFFRAMP: the type=CRYPTO list is what the user can sell, and type=FIAT is what they can receive.4. Payment methods
After — response (bare array)
- Now requires all three of
category,country, andcurrencyCode(the fiat code — pay-with for buy, payout for sell). The legacy call keyed only offfiatCurrencies. - Returns a bare array (not an object wrapper).
5. Limits and routes
This is the biggest structural change. The standalone limits endpoint is gone; limits now live on the route that serves a given currency pair, so they arrive together with the partners and rails that actually support that pair.- Limits are read from
route.paymentMethods[].limitsfor the chosen partner + method, not from a global map keyed by currency. minAmount→min,maxAmount→max; thelimits.currencyCodetells you which currency the bounds are expressed in (on-ramp: the fiat paid; off-ramp: the fiat received).- Limits are now direction-aware — a buy route and a sell route for the same pair can have different
min/max. - Path order follows direction:
- On-ramp:
.../CRYPTO_ONRAMP/{country}/{fiat}/{crypto}(source = fiat). - Off-ramp:
.../CRYPTO_OFFRAMP/{country}/{crypto}/{fiat}(source = crypto).
- On-ramp:
- Optional query params:
partners,paymentMethod,paymentType, andsubdivision(the US state that legacycountries.states[]used to carry).
Migration checklist
Add a category to every discovery call
Decide the direction per screen —
CRYPTO_ONRAMP for buy, CRYPTO_OFFRAMP for sell — and thread it through every /network-partner/* call.Repoint and rename the endpoints
Swap each legacy path for its replacement using the mapping table, and update the response field names (
countryName→name, defaultCurrencyCode→currencyCode, currencyName→name, networkCode→chainCode, minAmount/maxAmount→min/max).Merge the currency calls
Replace
fiat-currencies and crypto-currencies with a single supported/currencies call parameterized by type=FIAT|CRYPTO, and read from the currencies wrapper.Move limit validation onto routes
Delete calls to
/service-providers/limits/*. Read min/max from route.paymentMethods[].limits, and order the route source/destination by direction.Handle the new edge cases
Treat a
null defaults response and an empty 200 [] from routes as expected states, and send the canonical method id (never the display name) as paymentMethodType.What stays the same
POST /payments/crypto/quote,POST /crypto/session/widget, andGET /payments/transactions/{transactionId}are unchanged.Authorization: BASIC {apiKey}auth and the sandbox/production base URLs are unchanged.- The overall flow — discover → quote → create session → launch the provider widget → track the transaction — is unchanged.
Next steps
Full Integration Guide
The complete
/network-partner/* reference plus the end-to-end on-ramp and off-ramp flows.Quickstart
Run a sandbox buy and sell in about 30 minutes.