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

# Add and Withdraw Funds

The ramp clients build a headless fiat on-ramp and off-ramp around a Swig
wallet. Every ramp client call runs on your server. Your application decides
how to present authorized quote, launch URL, and session data to a user.

Ramp is split by direction. There is no generic ramp client:

* `swig.ramp.onramp` — fiat in, crypto to the Swig
* `swig.ramp.offramp` — crypto out of the Swig, fiat to the user

## Required configuration

Every ramp call requires `environment`. Options, quotes, and session creation
also require the organization's MELD configuration id:

| Field                                                                    | Value                                              |
| :----------------------------------------------------------------------- | :------------------------------------------------- |
| `environment`                                                            | `sandbox` or `production`                          |
| `organizationMeldConfigurationId` / `organization_meld_configuration_id` | required for options, quotes, and session creation |

The SDK encodes `environment` as the MELD enum on the wire, so pass the plain
string.

Quote calls additionally require:

| Field                                                                          | Value                                                      |
| :----------------------------------------------------------------------------- | :--------------------------------------------------------- |
| `externalCustomerId` / `external_customer_id`                                  | your identifier for the end customer                       |
| `swigConfigAddress` / `swig_config_address`                                    | the Swig receiving or sending funds                        |
| `network`                                                                      | `devnet` or `mainnet`, from the call or the client default |
| `sourceAmount`, `sourceCurrencyCode`, `destinationCurrencyCode`, `countryCode` | the quote request itself                                   |

`subdivision` and `paymentMethodType` / `payment_method_type` are optional.

<Warning>
  A `launchUrl` / `launch_url` is a user-specific session URL. Hand it to the
  customer who owns the session and keep it out of logs and analytics.
</Warning>

## On-ramp

Read the available options first, so currency and payment-method codes come
from the API rather than from a hardcoded list.

<CodeGroup dropdown>
  ```typescript TypeScript theme={null}
  const environment = 'sandbox';

  const options = await swig.ramp.onramp.getOptions({
    organizationMeldConfigurationId,
    environment,
    countryCode: 'US',
  });

  const { quotes } = await swig.ramp.onramp.quote({
    organizationMeldConfigurationId,
    environment,
    externalCustomerId,
    swigConfigAddress,
    network: 'devnet',
    sourceAmount: '100.00',
    sourceCurrencyCode: options.fiatCurrencyCodes[0]!,
    destinationCurrencyCode: options.cryptoCurrencyCodes[0]!,
    countryCode: 'US',
    paymentMethodType: options.paymentMethodTypes[0],
  });

  const session = await swig.ramp.onramp.createSession({
    organizationMeldConfigurationId,
    environment,
    quoteId: quotes[0]!.quoteId,
  });

  // Send session.launchUrl to the customer.
  const state = await swig.ramp.onramp.getSession({
    sessionId: session.sessionId,
    environment,
  });
  ```

  ```python Python theme={null}
  from swig_developer_sdk import QuoteRampArgs

  environment = "sandbox"

  options = await swig.ramp.onramp.get_options(
      organization_meld_configuration_id=configuration_id,
      environment=environment,
      country_code="US",
  )

  result = await swig.ramp.onramp.quote(
      QuoteRampArgs(
          organization_meld_configuration_id=configuration_id,
          environment=environment,
          external_customer_id=external_customer_id,
          swig_config_address=swig_config_address,
          network="devnet",
          source_amount="100.00",
          source_currency_code=options.fiat_currency_codes[0],
          destination_currency_code=options.crypto_currency_codes[0],
          country_code="US",
          payment_method_type=options.payment_method_types[0],
      )
  )

  session = await swig.ramp.onramp.create_session(
      organization_meld_configuration_id=configuration_id,
      quote_id=result.quotes[0].quote_id,
      environment=environment,
  )

  # Send session.launch_url to the customer.
  state = await swig.ramp.onramp.get_session(
      session_id=session.session_id,
      environment=environment,
  )
  ```
</CodeGroup>

Each quote carries `quoteId`, `serviceProvider`, `paymentMethodType`,
`sourceAmount`, `sourceCurrencyCode`, `destinationAmount`,
`destinationCurrencyCode`, `exchangeRate`, and `totalFee` (snake\_case in
Python).

On-ramp session status is one of:

```text theme={null}
unspecified  created  pending  settling  settled
failed  declined  cancelled  refunded
```

## Off-ramp

Off-ramp adds an on-chain step. The customer's wallet must authorize the
transfer to the provider before the session can settle, so the flow is:
quote → session → prepare authorization → application-owned signer → submit
authorization. It settles on mainnet even when `environment` is `sandbox`, so
use `mainnet` for the quote network.

<CodeGroup dropdown>
  ```typescript TypeScript theme={null}
  const options = await swig.ramp.offramp.getOptions({
    organizationMeldConfigurationId,
    environment,
    countryCode: 'US',
  });

  const { quotes } = await swig.ramp.offramp.quote({
    organizationMeldConfigurationId,
    environment,
    externalCustomerId,
    swigConfigAddress,
    network: 'mainnet',
    sourceAmount: '25.00',
    sourceCurrencyCode: options.cryptoCurrencies[0]!.currencyCode,
    destinationCurrencyCode: options.fiatCurrencyCodes[0]!,
    countryCode: 'US',
    paymentMethodType: options.paymentMethodTypes[0],
  });

  const session = await swig.ramp.offramp.createSession({
    organizationMeldConfigurationId,
    environment,
    quoteId: quotes[0]!.quoteId,
  });

  const authorization = await swig.ramp.offramp.prepareAuthorization({
    sessionId: session.sessionId,
    environment,
    feePayer,
    requesterAuthority: { secp256r1: { publicKey: passkeyPublicKey } },
  });

  // After authorized confirmation, coordinate signing in application-owned code.
  const signedBase64Transaction = await applicationSigner(
    authorization.preparedTransaction,
  );

  const { solanaSignature } = await swig.ramp.offramp.submitAuthorization({
    sessionId: session.sessionId,
    environment,
    authorizationId: authorization.authorizationId,
    signedTransaction: signedBase64Transaction,
  });
  ```

  ```python Python theme={null}
  from swig_developer_sdk import QuoteRampArgs

  options = await swig.ramp.offramp.get_options(
      organization_meld_configuration_id=configuration_id,
      environment=environment,
      country_code="US",
  )

  result = await swig.ramp.offramp.quote(
      QuoteRampArgs(
          organization_meld_configuration_id=configuration_id,
          environment=environment,
          external_customer_id=external_customer_id,
          swig_config_address=swig_config_address,
          network="mainnet",
          source_amount="25.00",
          source_currency_code=options.crypto_currencies[0].currency_code,
          destination_currency_code=options.fiat_currency_codes[0],
          country_code="US",
          payment_method_type=options.payment_method_types[0],
      )
  )

  session = await swig.ramp.offramp.create_session(
      organization_meld_configuration_id=configuration_id,
      quote_id=result.quotes[0].quote_id,
      environment=environment,
  )

  authorization = await swig.ramp.offramp.prepare_authorization(
      session_id=session.session_id,
      environment=environment,
      fee_payer=fee_payer,
      requester_authority={"secp256r1": {"publicKey": passkey_public_key}},
  )

  # After authorized confirmation, coordinate signing in application-owned code.
  signed_base64_transaction = await application_signer(
      authorization.prepared_transaction
  )

  submitted = await swig.ramp.offramp.submit_authorization(
      session_id=session.session_id,
      environment=environment,
      authorization_id=authorization.authorization_id,
      signed_transaction=signed_base64_transaction,
  )
  ```
</CodeGroup>

`authorization.display` is the human-readable transfer summary to show before
signing: `sourceWalletAddress`, `destinationWalletAddress`, `sourceAmount`,
`sourceCurrencyCode`, `destinationAmount`, `destinationCurrencyCode`,
`serviceProvider`, and optional `paymentMethodType` and
`providerDestinationAmount`.

The prepared authorization follows the same boundary as every other prepared
transaction. Inspect its signature metadata, obtain the required signature
from application-owned signing code, and return only the signed serialized
transaction to the server. The optional
[browser signing helpers](/developer-sdk/browser-signing) can assemble that
result. See [Server Runtime](/developer-sdk/server-runtime) for the trust
boundary.

Off-ramp session status adds three states to the on-ramp set:

```text theme={null}
provider-session-created  transfer-required  transfer-submitted
```

A settled off-ramp session also exposes `solanaSignature` /
`solana_signature` for the on-chain transfer.

## Routes behind the clients

| Client method                  | Route                                                        |
| :----------------------------- | :----------------------------------------------------------- |
| `onramp.getOptions`            | `GET /wallet/api/ramp/onramp/options`                        |
| `onramp.quote`                 | `POST /wallet/api/ramp/onramp/quote`                         |
| `onramp.createSession`         | `POST /wallet/api/ramp/onramp/session`                       |
| `onramp.getSession`            | `GET /wallet/api/ramp/onramp/session/{session_id}`           |
| `offramp.getOptions`           | `GET /wallet/api/ramp/offramp/options`                       |
| `offramp.quote`                | `POST /wallet/api/ramp/offramp/quote`                        |
| `offramp.createSession`        | `POST /wallet/api/ramp/offramp/session`                      |
| `offramp.prepareAuthorization` | `POST /wallet/api/ramp/offramp/session/{session_id}/prepare` |
| `offramp.submitAuthorization`  | `POST /wallet/api/ramp/offramp/session/{session_id}/submit`  |
| `offramp.getSession`           | `GET /wallet/api/ramp/offramp/session/{session_id}`          |

## Application delivery

Treat `launchUrl` / `launch_url`, quotes, and session state as user-scoped
data. If another application runtime needs them, return only the authorized
fields through your own server API. Do not import the Developer SDK's API
client or expose the Swig API key outside the server. The optional `/browser`
signing helpers remain limited to local transaction assembly.
