Skip to main content
At the end of this page, you will have moved fiat to crypto for a Sumvin user — the ramp is part of Atomic Money, Sumvin’s payments, ramps, cards, and settlement layer. The ramp transaction reaches completed, and the destination wallet holds the new balance. The final read:

Prerequisites

  • A KYC-verified Sumvin user with a deployed Safe. Run Stand up an account first if you do not have one.
  • A Platform API JWT and your x-juno-orgid header — see Authentication.
  • Base URL https://api.sumvin.com/v0.
  • Sandbox test card details — available from your account manager for non-production flows.
The user does not re-verify inside the Meld widget. Sumvin shares their existing KYC outcome with Meld on the first ramp call. See KYC passthrough.
1

Quote the buy

Quote what an amount of fiat will buy. You send the triplet from_asset, to_asset, chain_id — direction is inferred from which side is fiat. The response ranks live quotes from the service providers that serve the user’s country and payment method, with fees, exchange rate, and the destination amount broken out.GET /v0/ramp/quotes — List ramp quotes.
curl "https://api.sumvin.com/v0/ramp/quotes?source_amount=100&from_asset=USD&to_asset=SEI&chain_id=1329&country_code=US" \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>"
Response: 200 OK
{
  "quotes": [
    {
      "from_asset": "USD",
      "to_asset": "SEI",
      "chain_id": 1329,
      "source_amount": "100",
      "destination_amount": "99.85",
      "exchange_rate": 1.0015,
      "total_fee": "2.49",
      "network_fee": "0.25",
      "transaction_fee": "2.24",
      "partner_fee": "0.00",
      "payment_method_type": "CREDIT_DEBIT_CARD",
      "service_provider": "MOONPAY",
      "country_code": "US",
      "ramp_score": 87,
      "low_kyc": false,
      "is_swap": false
    }
  ],
  "_links": {
    "self": { "href": "/v0/ramp/quotes" },
    "sessions": { "href": "/v0/ramp/sessions", "method": "POST" }
  }
}
Quotes carry a ramp_score — higher means a better combined rate, fee, and success likelihood. Narrow the list by passing payment_method_type if you want a single rail (CREDIT_DEBIT_CARD, ACH, SEPA, APPLE_PAY, GOOGLE_PAY, BANK_TRANSFER, LOCAL_BANK_TRANSFER, BACS).
chain_id always describes the crypto leg. Discover the rampable (symbol, chain_id) pairs in Supported valuesSEI on Sei (1329) is the first launch chain; ETH, USDC, and EURC on Base (8453) are also live today.
2

Create a ramp session

Take the quote the user selected and create a session. The session returns a hosted widget URL — that is what the user opens to pay.Pass wallet_address as the settlement destination. Crypto lands there when the transaction settles.POST /v0/ramp/sessions — Create a ramp session.
curl -X POST https://api.sumvin.com/v0/ramp/sessions \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>" \
  -H "Content-Type: application/json" \
  -d '{
    "source_amount": "100",
    "from_asset": "USD",
    "to_asset": "SEI",
    "chain_id": 1329,
    "wallet_address": "0x9f8e7d6c5b4a39281726354091827364501928a7",
    "country_code": "US",
    "payment_method_type": "CREDIT_DEBIT_CARD",
    "service_provider": "MOONPAY"
  }'
Response: 201 Created
{
  "session": {
    "id": "ses_7b3e21",
    "widget_url": "https://widget.meld.io/?token=...",
    "service_provider_widget_url": "https://buy.moonpay.com/...",
    "token": "eyJhbGciOiJSUzI1NiJ9...",
    "external_session_id": "b2b8f5a0-4e9f-4f7a-9d2c-1a3e5b7c9d0e"
  },
  "_links": {
    "self": { "href": "/v0/ramp/sessions", "method": "POST" },
    "quotes": { "href": "/v0/ramp/quotes" },
    "transactions": { "href": "/v0/ramp/transactions" }
  }
}
403 Forbidden on this call means the user has not completed KYC. Check GET /v0/kyc/status and route the user through KYC before retrying.
3

Open the widget for the user

Navigate the user to widget_url. Render it in an iframe, a popup, or as a full-page redirect — whichever matches your UX.
// Redirect approach
window.location.href = session.widget_url;

// iframe approach
<iframe
  src={session.widget_url}
  allow="camera; payment"
  style={{ width: "100%", height: "700px", border: 0 }}
/>
Meld hosts the payment capture, any step-up authentication (3DS, 2FA), and the on-chain delivery leg. The user stays inside the widget for the whole flow.
4

Poll the transaction for settlement

Once the user submits the payment, Meld creates a transaction against the user’s record. List their ramp transactions to watch it progress.Internal status moves pendingprocessingcompleted. meld_status carries the provider-side state in parallel — useful for debugging a stuck transaction.GET /v0/ramp/transactions — List ramp transactions.
curl "https://api.sumvin.com/v0/ramp/transactions" \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>"
Response: 200 OK
{
  "transactions": [
    {
      "id": "txn_9a7d2f",
      "status": "completed",
      "meld_status": "SETTLED",
      "transaction_type": "CRYPTO_PURCHASE",
      "from_asset": "USD",
      "to_asset": "SEI",
      "chain_id": 1329,
      "source_amount": "100",
      "destination_amount": "99.85",
      "service_provider": "MOONPAY",
      "payment_method_type": "CREDIT_DEBIT_CARD",
      "created_at": "2026-04-24T14:02:11Z",
      "updated_at": "2026-04-24T14:07:45Z",
      "is_swap": false
    }
  ],
  "_links": {
    "self": { "href": "/v0/ramp/transactions" },
    "quotes": { "href": "/v0/ramp/quotes" }
  }
}
Sandbox settlements typically land in under 2 minutes. Production card payments settle in 5–15 minutes depending on the service provider. Poll on a 5–10 second interval while the widget is open, then back off.
The list endpoint’s optional status query parameter filters against provider-side state, not the internal lifecycle — pass an uppercase Meld value such as PROCESSING or SETTLED if you want a filter. For most polling flows, list without a filter and match against internal status on the client. Fetch one transaction directly with GET /v0/ramp/transactions/{transaction_id} for a detail view.
5

Verify the crypto arrived

Once status is completed, the destination wallet holds the new balance. Read the wallet’s assets to confirm:GET /v0/wallets/{wallet_id}/assets — List wallet assets.
The fiat purchase has settled on chain. The user holds the destination asset in their Sumvin wallet.

Status reference

Internal status is the lifecycle field you should drive UI from. meld_status is the provider-side mirror — useful when you need to surface richer intermediate state (for example, step-up auth) to the user.
Internal statusMaps from meld_status
pendingPENDING_CREATED, PENDING
processingPROCESSING, SETTLING, ONRAMP_SETTLED, TWO_FA_REQUIRED, TWO_FA_PROVIDED
completedSETTLED, COMPLETED
failedFAILED, DECLINED, ERROR, CANCELLED, VOIDED
cancelledREFUNDED

Common failure modes

SymptomCauseWhat to do
Quotes list is emptyNo service provider supports the pair for that country and amount.Widen the country, drop the payment_method_type filter, or try a smaller source_amount.
POST /v0/ramp/sessions returns 403 ForbiddenThe user has not completed KYC.Check GET /v0/kyc/status and route the user through KYC.
POST /v0/ramp/sessions returns 400 Bad Request with RAMP_INVALID_PAIR, RAMP_UNKNOWN_ASSET, or RAMP_UNSUPPORTED_ASSETThe (from_asset, to_asset, chain_id) triplet does not name a valid Sumvin asset, or the pair is not currently rampable.Verify the pair against Supported values and retry with a rampable pair.
POST /v0/ramp/sessions returns 502 Bad Gateway with RAMP_PROVIDER_ERRORMeld rejected the request — most often an amount below the provider minimum, or a provider outage.Re-quote, pick a different service_provider, and retry.
Transaction stays pending past 30 minutesThe user abandoned the widget, or the provider rejected the payment outside the session.Create a fresh session. The old one is a no-op.
status is completed but balance has not appearedChain indexer is still catching up.Wait 30–60 seconds and re-read GET /v0/wallets/{id}/assets.

Sell and off-ramp

The same endpoint handles the reverse direction — swap from_asset and to_asset so crypto is the source and fiat the destination. chain_id stays the same (it always describes the crypto leg). The resulting transaction comes back with transaction_type: "CRYPTO_SELL". See Meld off-ramp for the settlement model.

What’s next

  • Meld overview — how ramp composes with KYC passthrough and bank linking.
  • Ramp sessions — conceptual model behind sessions, scopes, and settlement.
  • Meld off-ramp — the crypto-to-fiat direction.