> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sumvin.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Use Sigil to instant on-ramp

> Quote a buy, open a hosted ramp session, and settle crypto into a user's wallet.

<Snippet file="product-term-disambiguation.mdx" />

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:

* [`GET /v0/ramp/transactions/{transaction_id}`](/api-reference/ramp/get-a-ramp-transaction) — Fetch the settled ramp transaction.

## Prerequisites

* A KYC-verified Sumvin user with a deployed Safe. Run [Stand up an account](/guides/quickstarts/stand-up-account) first if you do not have one.
* A Platform API JWT and your `x-juno-orgid` header — see [Authentication](/authentication).
* Base URL `https://api.sumvin.com/v0`.
* Sandbox test card details — available from your account manager for non-production flows.

<Info>
  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](/products/ramps/kyc-passthrough).
</Info>

<Steps>
  <Step title="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`](/api-reference/ramp/get-ramp-quotes) — List ramp quotes.

    <CodeGroup>
      ```bash curl theme={null}
      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>"
      ```

      ```typescript TypeScript theme={null}
      const params = new URLSearchParams({
        source_amount: "100",
        from_asset: "USD",
        to_asset: "SEI",
        chain_id: "1329",
        country_code: "US",
      });
      const res = await fetch(
        `https://api.sumvin.com/v0/ramp/quotes?${params}`,
        {
          headers: {
            "x-juno-jwt": process.env.SUMVIN_JWT!,
            "x-juno-orgid": process.env.SUMVIN_ORG_ID!,
          },
        },
      );
      const { quotes } = await res.json();
      ```

      ```python Python theme={null}
      import httpx
      import os

      res = httpx.get(
          "https://api.sumvin.com/v0/ramp/quotes",
          headers={
              "x-juno-jwt": os.environ["SUMVIN_JWT"],
              "x-juno-orgid": os.environ["SUMVIN_ORG_ID"],
          },
          params={
              "source_amount": "100",
              "from_asset": "USD",
              "to_asset": "SEI",
              "chain_id": 1329,
              "country_code": "US",
          },
      )
      quotes = res.json()["quotes"]
      ```
    </CodeGroup>

    **Response:** `200 OK`

    ```json theme={null}
    {
      "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`).

    <Note>
      `chain_id` always describes the crypto leg. Discover the rampable `(symbol, chain_id)` pairs in [Supported values](/products/ramps/supported-values#crypto--rampable-today) — `SEI` on Sei (`1329`) is the first launch chain; `ETH`, `USDC`, and `EURC` on Base (`8453`) are also live today.
    </Note>
  </Step>

  <Step title="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`](/api-reference/ramp/open-a-ramp-widget-session) — Create a ramp session.

    <CodeGroup>
      ```bash curl theme={null}
      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"
        }'
      ```

      ```typescript TypeScript theme={null}
      const res = await fetch("https://api.sumvin.com/v0/ramp/sessions", {
        method: "POST",
        headers: {
          "x-juno-jwt": process.env.SUMVIN_JWT!,
          "x-juno-orgid": process.env.SUMVIN_ORG_ID!,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          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",
        }),
      });
      const { session } = await res.json();
      ```

      ```python Python theme={null}
      import httpx
      import os

      res = httpx.post(
          "https://api.sumvin.com/v0/ramp/sessions",
          headers={
              "x-juno-jwt": os.environ["SUMVIN_JWT"],
              "x-juno-orgid": os.environ["SUMVIN_ORG_ID"],
          },
          json={
              "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",
          },
      )
      session = res.json()["session"]
      ```
    </CodeGroup>

    **Response:** `201 Created`

    ```json theme={null}
    {
      "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" }
      }
    }
    ```

    <Warning>
      `403 Forbidden` on this call means the user has not completed KYC. Check `GET /v0/kyc/status` and route the user through [KYC](/guides/kyc) before retrying.
    </Warning>
  </Step>

  <Step title="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.

    ```typescript theme={null}
    // 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.
  </Step>

  <Step title="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 `pending` → `processing` → `completed`. `meld_status` carries the provider-side state in parallel — useful for debugging a stuck transaction.

    [`GET /v0/ramp/transactions`](/api-reference/ramp/list-ramp-transactions) — List ramp transactions.

    <CodeGroup>
      ```bash curl theme={null}
      curl "https://api.sumvin.com/v0/ramp/transactions" \
        -H "x-juno-jwt: <your-jwt-token>" \
        -H "x-juno-orgid: <your-org-id>"
      ```

      ```typescript TypeScript theme={null}
      const res = await fetch("https://api.sumvin.com/v0/ramp/transactions", {
        headers: {
          "x-juno-jwt": process.env.SUMVIN_JWT!,
          "x-juno-orgid": process.env.SUMVIN_ORG_ID!,
        },
      });
      const { transactions } = await res.json();
      ```

      ```python Python theme={null}
      import httpx
      import os

      res = httpx.get(
          "https://api.sumvin.com/v0/ramp/transactions",
          headers={
              "x-juno-jwt": os.environ["SUMVIN_JWT"],
              "x-juno-orgid": os.environ["SUMVIN_ORG_ID"],
          },
      )
      transactions = res.json()["transactions"]
      ```
    </CodeGroup>

    **Response:** `200 OK`

    ```json theme={null}
    {
      "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" }
      }
    }
    ```

    <Note>
      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.
    </Note>

    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.
  </Step>

  <Step title="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`](/api-reference/wallet-assets/list-wallet-assets) — List wallet assets.

    <Check>
      The fiat purchase has settled on chain. The user holds the destination asset in their Sumvin wallet.
    </Check>
  </Step>
</Steps>

## 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 `status` | Maps from `meld_status`                                                          |
| ----------------- | -------------------------------------------------------------------------------- |
| `pending`         | `PENDING_CREATED`, `PENDING`                                                     |
| `processing`      | `PROCESSING`, `SETTLING`, `ONRAMP_SETTLED`, `TWO_FA_REQUIRED`, `TWO_FA_PROVIDED` |
| `completed`       | `SETTLED`, `COMPLETED`                                                           |
| `failed`          | `FAILED`, `DECLINED`, `ERROR`, `CANCELLED`, `VOIDED`                             |
| `cancelled`       | `REFUNDED`                                                                       |

## Common failure modes

| Symptom                                                                                                                        | Cause                                                                                                                     | What to do                                                                                                                          |
| ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Quotes list is empty                                                                                                           | No 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 Forbidden`                                                                               | The user has not completed KYC.                                                                                           | Check `GET /v0/kyc/status` and route the user through [KYC](/guides/kyc).                                                           |
| `POST /v0/ramp/sessions` returns `400 Bad Request` with `RAMP_INVALID_PAIR`, `RAMP_UNKNOWN_ASSET`, or `RAMP_UNSUPPORTED_ASSET` | The `(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](/products/ramps/supported-values#crypto--rampable-today) and retry with a rampable pair. |
| `POST /v0/ramp/sessions` returns `502 Bad Gateway` with `RAMP_PROVIDER_ERROR`                                                  | Meld 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 minutes                                                                                    | The 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 appeared                                                                           | Chain indexer is still catching up.                                                                                       | Wait 30–60 seconds and re-read `GET /v0/wallets/{wallet_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 [Off-ramp](/products/ramps/off-ramp) for the settlement model.

## What's next

* [Ramps & banking](/products/ramps/overview) — how ramp composes with KYC passthrough and bank linking.
* [Ramp sessions](/concepts/ramp-sessions) — conceptual model behind sessions, scopes, and settlement.
* [Off-ramp](/products/ramps/off-ramp) — the crypto-to-fiat direction.
