# AI Integration Assistant

{% hint style="info" %}
**Need help? Ask our AI assistant about endpoints, authentication, webhooks, or troubleshooting.**

<h2 align="center"><a href="https://chatgpt.com/g/g-67ef959ca3e88191a03120f448ebdb56-swapped-com-integration-api-documentation">Open Integration Assistant →</a></h2>
{% endhint %}


# On-ramp Integration

Swapped.com Onramp is an embeddable widget that lets your users buy cryptocurrency directly within your application. Support for 40+ payment methods across 150+ countries.

#### Why Swapped

* **Competitive fees** - Among the lowest rates in the market
* **Global coverage** - 150+ countries, 40+ local payment methods
* **24/7 human support** - Real support agents, no bots

<figure><img src="https://2102146608-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDf1VBRUItvdLkWUnkNIb%2Fuploads%2FPQibrvMkvSegnXyLKBWW%2FSwapped%20Widget.gif?alt=media&amp;token=30696059-bf50-46ba-afa3-6c8eb7ff5eed" alt=""><figcaption></figcaption></figure>

### User Flow

1. Select cryptocurrency, fiat currency, and amount
2. Choose payment method
3. Authenticate via one-time password (OTP)
4. Enter destination wallet address
5. Complete payment
6. Receive crypto

### Merchant Dashboard

Manage your integration at [dashboard.swapped.com](https://dashboard.swapped.com):

* View volume and transaction statistics
* Monitor orders
* Configure integration parameters


# iFrame Initialization

#### Required Parameters

* <mark style="color:$danger;">**`apiKey`**</mark>: Your publishable API key for customer and transaction assignment (also known as the public key).
* <mark style="color:$danger;">**`signature`**</mark>: Your HMAC-SHA256 signature of the full query string, base64-encoded. The signature must be the final parameter in the query string. See Server-Side URL Signature for implementation details.
* <mark style="color:$danger;">**`currencyCode`**</mark>: The cryptocurrency code for purchase (e.g., `BTC`, `ETH`, `BCH`). [See the documentation for all options](https://docs.swapped.com/swapped-ramp/readme/supported-cryptocurrencies). When multiple wallet addresses are provided, this serves as the default cryptocurrency.
* <mark style="color:$danger;">**`walletAddress`**</mark>: The destination wallet address for the purchased cryptocurrency.
  * Single address: <mark style="color:$danger;">`walletAddress=`</mark><mark style="color:$primary;">`ltc1q2k0xaafhgt3s8qw03wmajjmlc8gcepdy0un0ah`</mark>
  * Multiple currencies: To accept multiple cryptocurrencies, use the format `SYMBOL:address` with comma separation, e.g. <mark style="color:$danger;">`walletAddress=`</mark><mark style="color:$primary;">`BTC:yourBitcoinAddress,LTC:yourLitecoinAddress,DOGE:yourDogecoinAddress`</mark>

#### Optional Parameters

* <mark style="color:$danger;">**`method`**</mark>: Specifies a payment method on load. Value is the `payment_group` mentioned [here](https://docs.swapped.com/swapped-ramp/endpoints/onramp-endpoints/get-payment-methods) (e.g., <mark style="color:$danger;">`method=`</mark><mark style="color:$primary;">`creditcard`</mark>).
* <mark style="color:$danger;">**`baseCurrencyCode`**</mark>: The fiat currency code for transactions (e.g., `USD`, `EUR`, `GBP`). [Supported currencies](https://docs.swapped.com/swapped-ramp/readme/supported-fiat-currencies).
* <mark style="color:$danger;">**`lockBaseCurrency`**</mark>: `True|False` Locks currency selection to the specified `baseCurrencyCode`. Prevents users from selecting other currencies and removes payment methods that don't support the specified currency.
* <mark style="color:$danger;">**`baseCurrencyAmount`**</mark>: The fiat amount to spend. Maximum 2 decimal places and cannot be zero. Requires `baseCurrencyCode` to be set.
* <mark style="color:$danger;">**`quoteCurrencyAmount`**</mark>: The cryptocurrency amount to purchase. Maximum 6 decimal places with a minimum equivalent of 7 EUR or 8 USD.
* <mark style="color:$danger;">**`email`**</mark>: Pre-fills the customer's email address on the login page.
* <mark style="color:$danger;">**`externalCustomerId`**</mark>: Your unique identifier for the customer.
* <mark style="color:$danger;">**`redirectUrl`**</mark>: URL for redirection after purchase completion. Must be URL-encoded.
  * Without variables: \ <mark style="color:$danger;">`redirectUrl=`</mark>`https%3A%2F%2Fwebhook.site%2FSwapped`
  * With dynamic variables: <mark style="color:$danger;">`redirectUrl=`</mark>`https%3A%2F%2Fwebhook.site%2FSwapped%3ForderId%3D%7BorderId%7D%26orderStatus%3D%7BorderStatus%7D`
* <mark style="color:$danger;">**`responseUrl`**</mark>: Webhook URL for order notifications. Must be URL-encoded.
  * Additionally, you can define a global callback URL via the [Swapped.com dashboard](https://dashboard.swapped.com/developers)
* <mark style="color:$danger;">**`customerKYC`**</mark>: The customer's Know Your Customer (KYC) verification level:
  * `0`: No KYC completed
  * `1`: Proof of ID + Liveness Check&#x20;
  * `2`: Proof of ID + Liveness Check + Proof of Address&#x20;
* <mark style="color:$danger;">**`destinationTag`**</mark>: Adds a numeric destination tag or text memo for recipient identification or transaction context.
* <mark style="color:$danger;">**`minAmount`**</mark>: Minimum order amount in EUR. Cannot be lower than 7 EUR.
* <mark style="color:$danger;">**`lockAmount`**</mark>: `True|False` Locks the fiat and crypto amount fields, preventing user modification.
* <mark style="color:$danger;">**`baseCountry`**</mark>: ISO country code for the user's location. Determines available payment methods.
* <mark style="color:$danger;">**`markup`**</mark>: Order markup percentage, between 0 and 5. The value is the percent applied to the order (e.g. `?markup=0.05` applies a 0.05% markup, `?markup=2.5` applies 2.5%).
* <mark style="color:$danger;">**`submerchant`**</mark>: Submerchant identifier for multi-tenant setups

#### Server-Side URL Signature

Generate a signature to prevent URL tampering. The signature is created using the query string (including the `?`) and your secret key.

```javascript
// Import the crypto module.
import crypto from 'crypto';

// Define the public API key.
const publicKey = 'your_public_key';

// Define the secret API key.
const secretKey = 'your_secret_key';

// Define the currency code.
const currencyCode = 'currency_code';

// Define the wallet address.
const walletAddress = 'your_wallet_address';

// Build URL with query parameters.
const originalUrl = `https://widget.swapped.com?apiKey=${publicKey}&currencyCode=${currencyCode}&walletAddress=${walletAddress}`;

// Create a SHA-256 HMAC signature from the URL's search string, then encode in Base64.
const signature = crypto.createHmac('sha256', secretKey).update(new URL(originalUrl).search).digest('base64');

// Append the URL-encoded signature to the original URL.
const urlWithSignature = `${originalUrl}&signature=${encodeURIComponent(signature)}`;

// Output the final URL with the signature appended.
console.log(urlWithSignature);
```

```php
<?php

// Define the public API key.
$publicKey = 'your_public_key';

// Define the secret API key.
$secretKey = 'your_secret_key';

// Define the currency code.
$currencyCode = 'currency_code';

// Define the wallet address.
$walletAddress = 'your_wallet_address';

// Build URL with query parameters.
$originalUrl = "https://widget.swapped.com?apiKey={$publicKey}&currencyCode={$currencyCode}&walletAddress={$walletAddress}";

// Parse the URL into its components.
$parsedUrl = parse_url($originalUrl);

// Create a SHA-256 HMAC signature from the query string, then encode in Base64.
$signature = base64_encode(hash_hmac('sha256', '?'.$parsedUrl['query'], $secretKey, true));

// Append the URL-encoded signature to the URL.
$urlWithSignature = "{$originalUrl}&signature=" . urlencode($signature);

// Output the final URL with the signature appended.
echo $urlWithSignature;

```

#### Example iFrame URL <a href="#example-iframe-url" id="example-iframe-url"></a>

Note: this is a test key, your key **will** be different.

<https://widget.swapped.com/?apiKey=pk_live_3e4c36240c0f46880e543b04e721dbee&walletaddress=ltc1q2k0xaafhgt3s8qw03wmajjmlc8gcepdy0un0ah&signature=okYOG6%2FzzQBmkEchBU4XUTYrMWGAPROVC46skuf2hl8%3D>

#### Example iFrame <a href="#example-iframe" id="example-iframe"></a>

The iFrame has been optimized for height: 482px; width: 400px;.

{% code overflow="wrap" %}

```html
<iframe allow="accelerometer; autoplay; camera; encrypted-media; gyroscope; payment; clipboard-read; clipboard-write"
  src="https://widget.swapped.com/?apiKey={your-api-key}&currencyCode=BTC&walletAddress={your-wallet-address}&signature={your_signature}" title="Buy crypto with Swapped" style="height:
  482px; width: 400px; border-radius: 28px; margin: auto;"></iframe>
```

{% endcode %}


# Order Notifications

To receive order notifications. Configure a callback URL either per-order through <mark style="color:$danger;">**`responseUrl`**</mark>  or at the merchant level via the [Swapped Dashboard](https://dashboard.swapped.com/developers).

### Callback URL Priority

1. <mark style="color:$danger;">**`responseUrl`**</mark> in the iframe URL (if provided)
2. Merchant-level webhook in Dashboard (if configured)
3. No callback (if neither is set)

> **Important:** The callback destination is locked at order creation and cannot be changed afterwards.

{% hint style="warning" %}
Callbacks may be resent due to network errors. \
\ <mark style="color:$danger;">**Always verify an order hasn't already been credited before processing.**</mark> \
\
[See Order Notification Retry Policy for retry behavior.](/misc/order-notification-retry-policy)
{% endhint %}

### Verifying Signatures

Validate callbacks using the <mark style="color:$danger;">**`signature`**</mark> header. Compute an HMAC-SHA256 using your secret key and the raw request body, then compare.

**Example with NodeJS:**

{% code overflow="wrap" %}

```javascript
import crypto from 'crypto';

const secretKey = 'sk_test_key'; // Replace with your secret key
const requestBody = '{ "order_id": "9fcc45a5-4def-4953-9bd8-9ff75d9aaa9c"}'

const signature =
  crypto
    .createHmac('sha256', secretKey)
    .update(requestBody)
    .digest('base64'); 
```

{% endcode %}

Both <mark style="color:$danger;">**`order_broadcasted`**</mark> and <mark style="color:$danger;">**`order_cancelled`**</mark> are final states. An order cannot transition from completed to cancelled.

### Callback Payloads

#### `payment_pending`

Order created, awaiting customer payment.

```json
{
  "order_id": "9af6cd02-174f-438f-a362-fc6545ad125b",
  "external_transaction_id": null,
  "external_customer_id": null,
  "order_status": "payment_pending",
  "order_crypto": "LTC",
  "order_type": "buy",
  "order_crypto_amount": "0.070175135286017",
  "order_crypto_address": "ltc1q2k0xaafhgt3s8qw03wmajjmlc8gcepdy0un0ah",
  "order_crypto_tag": null,
  "order_amount_usd": 8.18,
  "order_amount_usd_plus_fees": 8.9,
  "order_amount_eur": 7.01,
  "order_amount_eur_plus_fees": 7.62,
  "network": "litecoin"
}
```

#### `order_completed`

Payment successful, crypto purchase processed.

```json
{
  "order_id": "9fcc45a5-4def-4953-9bd8-9ff75d9aaa9c",
  "order_crypto_amount": 0.070175135286017,
  "order_crypto": "LTC",
  "order_status": "order_completed",
  "order_crypto_address": "ltc1qlec2yfpkdvn4lr0vpf27qggrxtu34zeu5l6g2u",
  "external_customer_id": "1234567",
  "order_amount_usd": "25",
  "order_amount_usd_plus_fees": "25.5",
  "order_amount_eur": "21",
  "order_crypto_tag": 12345,
  "order_amount_eur_plus_fees": "22.5",
  "network": "litecoin"
}
```

#### `order_broadcasted`

Transaction broadcast to blockchain.

```json
{
  "order_id": "9fcc45a5-4def-4953-9bd8-9ff75d9aaa9c",
  "order_crypto_amount": 0.070309096973144,
  "order_crypto": "LTC",
  "order_status": "order_broadcasted",
  "transaction_id": "ea458dda0ff8583199bdd4d9b9a69a2813694764a633fd40b27de22a868cebec",
  "order_crypto_address": "ltc1qlec2yfpkdvn4lr0vpf27qggrxtu34zeu5l6g2u",
  "external_customer_id": "1234567",
  "order_amount_usd": "25",
  "order_amount_usd_plus_fees": "25.5",
  "order_amount_eur": "21",
  "order_crypto_tag": 12345,
  "order_amount_eur_plus_fees": "22.5",
  "network": "litecoin"
}
```

#### `order_cancelled`

Order cancelled (payment failure, user cancellation, etc.).

```json
{
  "order_id": "9ab49879-92f0-44fc-992e-460285c879e8",
  "order_status": "order_cancelled",
  "order_type": "buy",
  "order_crypto": "LTC",
  "external_transaction_id": null,
  "external_customer_id": null
}
```

### Response Fields

| Field                                                                | Description                                           |
| -------------------------------------------------------------------- | ----------------------------------------------------- |
| <mark style="color:$danger;">**`order_id`**</mark>                   | Swapped order ID                                      |
| <mark style="color:$danger;">**`order_status`**</mark>               | Current order state                                   |
| <mark style="color:$danger;">**`order_crypto`**</mark>               | Cryptocurrency code                                   |
| <mark style="color:$danger;">**`order_crypto_amount`**</mark>        | Crypto amount received                                |
| <mark style="color:$danger;">**`order_crypto_address`**</mark>       | Destination wallet address                            |
| <mark style="color:$danger;">**`order_crypto_tag`**</mark>           | Destination tag/memo (XRP, TON, etc.)                 |
| <mark style="color:$danger;">**`network`**</mark>                    | Blockchain network used                               |
| <mark style="color:$danger;">**`order_amount_usd`**</mark>           | Crypto value in USD (mid-market rate, excludes fees)  |
| <mark style="color:$danger;">**`order_amount_usd_plus_fees`**</mark> | USD amount including platform fee                     |
| <mark style="color:$danger;">**`order_amount_eur`**</mark>           | Crypto value in EUR                                   |
| <mark style="color:$danger;">**`order_amount_eur_plus_fees`**</mark> | EUR amount including platform fee                     |
| <mark style="color:$danger;">**`transaction_id`**</mark>             | Blockchain transaction hash (broadcasted orders only) |
| <mark style="color:$danger;">**`external_customer_id`**</mark>       | Your customer ID (if provided in URL)                 |


# Test Card

<mark style="color:red;">**Note: The test debit card number will not work in the live environment. For more info, please see**</mark> [Sandbox Environment](/swapped-ramp/readme/sandbox-environment)

**It's currently only possible to make test orders with Visa/MasterCard as the payment method and ETH or BTC as the cryptocurrencies.**

### Debit Card:

Card number:

```plaintext
4929 4205 7359 5709
```

Expiration date:

```plaintext
10/31
```

CVC/CVV:

```plaintext
123
```


# Sandbox Environment

### Accessing the Sandbox

Swapped.com's sandbox environment can be accessed via [**https://sandbox.swapped.com**](https://sandbox.swapped.com).&#x20;

Swapped.com's sandbox environment allows merchants to test their integration before going live. This ensures that all functionality is working as expected without real funds being charged.&#x20;

**The sandbox environment only offers BTC & ETH testnet cryptocurrencies, and supports only Visa/MasterCard** [**test card**](/swapped-ramp/readme/test-card) **payments. As a result of this, only those currencies and methods can be selected. Payments are limited to a 15 euro maximum.**

### Generating a Sandbox iFrame

To generate a sandbox iframe, follow these steps:

1. Use the following keys:

   ```
   Public Key: pk_sandbox_rT9bW3sN6mJ8F5hP2cRqLvZ7SaD4XoY9
   Private Key: sk_sandbox_gV4eT2aK5bP6C7nR3fWmQxY8FdZ9HhE2
   ```
2. Follow the instructions on the [**iframe-initialization**](/swapped-ramp/readme/iframe-initialization) page to generate an iframe URL and signature.

### Setting Up Testnet Wallets

To test cryptocurrency transactions, ensure you are using the correct testnet wallets:

* **Bitcoin Testnet**: Follow the guide [here ](https://support.bitpay.com/hc/en-us/articles/360015463612-How-to-Create-a-Testnet-Wallet)to enable Bitcoin testnet via Bitpay.
* **Sepolia Ethereum**: Follow the guide [here ](https://support.metamask.io/configure/networks/how-to-view-testnets-in-metamask/)to enable Sepolia ETH via MetaMask.


# Onramp Aggregator Partners

Aggregator integrations bypass the widget's index and confirmation pages. The user flow depends on which parameters you include.

### Flow Types

#### Onramp Flow (Direct to Summary)

When all required parameters are provided, users skip directly to the summary screen.

* <mark style="color:$danger;">**`currencyCode`**</mark>
* <mark style="color:$danger;">**`baseCurrencyCode`**</mark>
* <mark style="color:$danger;">**`baseCurrencyAmount`**</mark>
* <mark style="color:$danger;">**`method`**</mark>

#### Optional Parameters

* <mark style="color:$danger;">**`walletAddress`**</mark> : Skips wallet entry screen
* <mark style="color:$danger;">**`destinationTag`**</mark> : Skips tag entry screen
* <mark style="color:$danger;">**`submerchant`**</mark>: Sub merchant identifier for multi-tenant setups

### Examples

**Direct to summary (all parameters):**

{% code overflow="wrap" %}

```
?apiKey=pk_live_xxx&currencyCode=BTC&walletAddress=yourBtcAddress&baseCurrencyCode=USD&baseCurrencyAmount=100&method=creditcard
```

{% endcode %}

**Manual wallet entry (no address):**

{% code overflow="wrap" %}

```
?apiKey=pk_live_xxx&currencyCode=BTC&baseCurrencyCode=USD&baseCurrencyAmount=100&method=creditcard
```

{% endcode %}

**XRP with manual tag entry:**

{% code overflow="wrap" %}

```
?apiKey=pk_live_xxx&currencyCode=XRP&walletAddress=yourXrpAddress&baseCurrencyCode=USD&
```

{% endcode %}


# Supported Cryptocurrencies

The **Code** column should be used for <mark style="color:$danger;">**`currencyCode`**</mark> parameter.

| Code              | Name               | Network             |
| ----------------- | ------------------ | ------------------- |
| `ADA`             | Cardano            | Cardano             |
| `APE_ETHEREUM`    | Apecoin            | Ethereum            |
| `ARB`             | Arbitrum           | Arbitrum            |
| `ATOM_COSMOS`     | Cosmos             | Cosmos              |
| `AVAX_AVALANCHE`  | Avalanche          | Avalanche           |
| `BCH`             | Bitcoin Cash       | Bitcoin Cash        |
| `BNB`             | Binance Coin       | Binance Smart Chain |
| `BTC`             | Bitcoin            | Bitcoin             |
| `CRO`             | Cronos             | Ethereum            |
| `DAI_BSC`         | DAI                | Binance Smart Chain |
| `DAI_ETHEREUM`    | DAI                | Ethereum            |
| `DOGE`            | Dogecoin           | Dogecoin            |
| `EURC`            | EURC               | Ethereum            |
| `ETH`             | Ethereum           | Ethereum            |
| `ETH_BASE`        | Ethereum           | Base                |
| `ETH_BSC`         | Ethereum           | Binance Smart Chain |
| `HYPE`            | Hyperliquid        | Hyperliquid         |
| `LINK_BSC`        | Chainlink          | Binance Smart Chain |
| `LINK_ETHEREUM`   | Chainlink          | Ethereum            |
| `LTC`             | Litecoin           | Litecoin            |
| `MON`             | Monad              | Monad Mainnet       |
| `OP`              | Optimism           | Optimism            |
| `OSMO`            | Osmosis            | Osmosis             |
| `PAXG`            | Paxos Gold         | Ethereum            |
| `POLYGON`         | Polygon            | Polygon             |
| `SAND_ETHEREUM`   | Sandbox            | Ethereum            |
| `SHIB`            | Shiba Inu          | Ethereum            |
| `SHIB_BSC`        | Shiba Inu          | Binance Smart Chain |
| `SOL`             | Solana             | Solana              |
| `TON`             | Toncoin            | TON                 |
| `TRUMP`           | Trump Coin         | Solana              |
| `TRX`             | Tron               | Tron                |
| `TWT`             | Trust Wallet Token | BSC                 |
| `UNI_BSC`         | Uniswap            | Binance Smart Chain |
| `UNI_ETHEREUM`    | Uniswap            | Ethereum            |
| `USDC_ARBITRUM`   | USDC               | Arbitrum            |
| `USDC_POLYGON`    | USDC               | Polygon             |
| `USDC_AVALANCHE`  | USDC               | Avalanche           |
| `USDC_BASE`       | USDC               | Base                |
| `USDC_BSC`        | USDC               | Binance Smart Chain |
| `USDC_ETHEREUM`   | USDC               | Ethereum            |
| `USDC_HYPERCORE`  | USDC               | Hypercore           |
| `USDC_MONAD`      | USDC               | Monad Mainnet       |
| `USDC_NOBLE`      | USDC               | Noble               |
| `USDCE_WORLDCOIN` | USDCe              | Worldchain          |
| `USDCE_POLYGON`   | USDCe              | Polygon             |
| `USDC_SOLANA`     | USDC               | Solana              |
| `USDC_HYPE`       | USDC               | Hyperliquid         |
| `USDH_HYPE`       | USDH               | Hyperliquid         |
| `USDG_ROBINHOOD`  | USDG               | Robinhood           |
| `USDT_BSC`        | USDT               | Binance Smart Chain |
| `USDT_ETHEREUM`   | Tether             | Ethereum            |
| `USDT_POLYGON`    | Tether             | Polygon             |
| `USDT_AVALANCHE`  | Tether             | Avalanche           |
| `USDT_SOLANA`     | Tether             | Solana              |
| `USDT_TON`        | Tether             | TON                 |
| `USDT_TRON`       | Tether             | TRC-20 TRON         |
| `XAUT`            | Tether Gold        | Ethereum            |
| `XRP`             | XRP                | Ripple              |

Note: Due to regulatory reasons, users from Texas won't be able to use stablecoins.


# Supported Fiat Currencies

| Currency |     |     |     |     |
| -------- | --- | --- | --- | --- |
| EUR      | USD | PLN | SEK | SGD |
| GBP      | RON | ZAR | HUF | BRL |
| MXN      | IDR | JPY | AUD | HKD |
| NZD      | THB | CZK | TRY | DKK |
| CHF      | CAD | INR | BGN | ILS |
| NOK      | PHP | MYR | VND | KRW |
| COP      | PEN | CLP | ZMW |     |


# Off-ramp Integration

#### How does the Swapped.com off-ramp work?

Swapped.com provides a seamless crypto-to-fiat off-ramp via an embeddable iFrame.

To sell crypto, users must complete the following:

1. Select the cryptocurrency to sell, the fiat currency to receive, and the amount.
2. Choose a payout method.
3. Log in using a one-time password (OTP).
4. Complete KYC (if not already done).
5. Enter payout account details.
6. Send crypto to the provided wallet address.
7. The transaction undergoes a fraud check.
8. Swapped.com sends the fiat to the user.


# iFrame initialization

## Required Parameters

* <mark style="color:red;">`apiKey`</mark>: Your publishable API key, also known as the public key.
* <mark style="color:red;">`signature`</mark>: Your HMAC-SHA256 signature of the full query string, base64-encoded.

## Optional Parameters

* <mark style="color:red;">`email`</mark>: Pre-fills the customer's email address on the login page.
* <mark style="color:red;">`customerKYC`</mark>: The level of Know Your Customer (KYC) verification.
  * 0 = the customer has not completed KYC.&#x20;
  * 1 = the customer has completed Proof of ID + Liveness Check.&#x20;
  * 2 = the customer has completed Proof of ID + Liveness Check + Proof of Address.
* <mark style="color:red;">`externalCustomerId`</mark>: Your unique identifier for the customer.
* <mark style="color:red;">`baseCountry`</mark>: User's ISO country code. Used to determine available payout methods. See [supported countries](/swapped-ramp/endpoints/misc.-endpoints/get-supported) for the full list.
* <mark style="color:red;">`method`</mark>: The method the user will receive their payout in. (e.g. bank transfer, Skrill) A full list of supported methods can be found [here](/swapped-ramp/off-ramp-integration/supported-payout-methods).&#x20;
* <mark style="color:red;">`minAmount`</mark>: Sets the minimum order amount in EUR. This cannot be lower than 7 EUR.
* <mark style="color:red;">`userSendsFunds=false`</mark>: This parameter enables merchants to send crypto on behalf of their users. Must be set to false, will default to True.
* <mark style="color:red;">`fiatCurrencyCode`</mark>: Fiat payout currency (e.g. EUR, USD). Required for <mark style="color:red;">`userSendsFunds=false`</mark> flow.&#x20;
* <mark style="color:red;">`cryptoCurrencyCode`</mark>: The crypto the user is selling (e.g. BTC, ETH). Required for <mark style="color:red;">`userSendsFunds=false`</mark> flow.&#x20;
* <mark style="color:red;">`cryptoCurrencyAmount`</mark> : Locks the cryptocurrency amount to be sent. Required for <mark style="color:red;">`userSendsFunds=false`</mark> flow.
* <mark style="color:red;">`fiatCurrencyAmount`</mark>: Locks the fiat amount the user will receive. Required for <mark style="color:red;">`userSendsFunds=false`</mark> flow.
* <mark style="color:red;">`submerchant`</mark>: Submerchant identifier for multi-tenant setups

**Note:** Only one of the following must be passed. If <mark style="color:red;">`cryptoCurrencyAmount`</mark> and <mark style="color:red;">`fiatCurrencyAmount`</mark> both are passed, <mark style="color:red;">`cryptoCurrencyAmount`</mark> will take precedence.&#x20;

***

### Example with PHP

{% code overflow="wrap" %}

```php
<?php

// Define the public API key.
$publicKey = 'your_public_key';

// Define the secret API key.
$secretKey = 'your_secret_key';

// Define the currency code.
$currencyCode = 'currency_code';

// Build URL with query parameters.
$originalUrl = "https://widget.swapped.com/sell?apiKey={$publicKey}&currencyCode={$currencyCode}";

// Parse the URL into its components.
$parsedUrl = parse_url($originalUrl);

// Create a SHA-256 HMAC signature from the query string, then encode in Base64.
$signature = base64_encode(hash_hmac('sha256', '?'.$parsedUrl['query'], $secretKey, true));

// Append the URL-encoded signature to the URL.
$urlWithSignature = "{$originalUrl}&signature=" . urlencode($signature);

// Output the final URL with the signature appended.
echo $urlWithSignature;
```

{% endcode %}

### Example with NodeJS

{% code overflow="wrap" %}

```js
// Import the crypto module.
import crypto from 'crypto';

// Define the public API key.
const publicKey = 'your_public_key';

// Define the secret API key.
const secretKey = 'your_secret_key';

// Define the currency code.
const currencyCode = 'currency_code';

// Build URL with query parameters.
const originalUrl = `https://widget.swapped.com/sell?apiKey=${publicKey}&currencyCode=${currencyCode}`;

// Create a SHA-256 HMAC signature from the URL's search string, then encode in Base64.
const signature = crypto.createHmac('sha256', secretKey).update(new URL(originalUrl).search).digest('base64');

// Append the URL-encoded signature to the original URL.
const urlWithSignature = `${originalUrl}&signature=${encodeURIComponent(signature)}`;

// Output the final URL with the signature appended.
console.log(urlWithSignature);
```

{% endcode %}

***

### iFrame Embed Example

{% code overflow="wrap" %}

```html
<iframe allow="accelerometer; autoplay; camera; encrypted-media; gyroscope; payment; clipboard-read; clipboard-write" src="https://widget.swapped.com/sell?apiKey={pk_live_key}&currencyCode=btc&signature=lorem" title="Buy crypto with Swapped" style="height: 585px; width: 445px; border-radius: 
0.75rem; margin: auto;"></iframe>

```

{% endcode %}

***

### Order Status Flow&#x20;

`payment_pending → order_processing → payout_pending → order_completed`\
                                  `↘ order_cancelled`

**Status Definitions:**&#x20;

<mark style="color:blue;">`payment_pending`</mark>: Awaiting the user’s crypto deposit.

<mark style="color:blue;">`order_processing`</mark>: Crypto detected, awaiting blockchain confirmation.

<mark style="color:blue;">`payout_pending`</mark>: Crypto has been confirmed on the blockchain, and the payout to the user is pending.

<mark style="color:blue;">`order_completed`</mark>: Crypto received and fiat sent to the user.

<mark style="color:blue;">`order_cancelled`</mark>: Order cancelled (may include a refund if crypto was sent).

### Iframe Order Data Event

The order data will be posted from the iframe when the user presses continue from the payout summary.

If you'd like to allow your frontend access to the order data, you can check for order data events like so:

```javascript
window.addEventListener('message', function (event) {
  // Verify origin
  if (event.origin !== 'https://widget.swapped.com') return

  const { type, data } = event.data
  if (type === 'SWAPPED_ORDER_DATA') {
    console.log('New order data:', data)
    // Optional: Update your UI
  }
})
```

All messages are wrapped like this:

```javascript
{
  type: 'SWAPPED_ORDER_DATA',
  data: {
    crypto: "BTC",
    network: "mainnet",
    amount: "0.001",
    address: "0x...",
    order_id: "ord_123456",
    timestamp: 1643723400000
  }
}
```

#### Data:

```typescript
interface OrderPostMessageData {
    crypto: string       // e.g., "BTC", "ETH", "USDC"
    network: string      // e.g., "mainnet"
    amount: string       // Amount in crypto
    address: string      // Wallet address (may be blank)
    order_id: string     // Unique order ID
    timestamp: number    // Unix timestamp of event
}
```

## Sending payments on behalf of users

This flow enables merchants to initiate and send crypto on behalf of their users, streamlining the off-ramp experience.

#### Flow:

1. The user enters payout details in the Swapped widget.
2. The user sees an order summary showing the expected fiat amount.
3. The user confirms, creating the order.
4. Swapped sends a callback to the merchant with order details.
5. The merchant sends the specified crypto amount to Swapped.
6. Swapped waits for the required blockchain confirmations (varies by crypto and network, see [here](/swapped-ramp/off-ramp-integration/cryptocurrencies-and-confirmations) for the full list).
7. Once confirmed, Swapped sends the fiat to the user.
8. The widget displays a final confirmation based on the actual crypto received.


# Order Notifications

To receive order notifications, you can either provide a <mark style="color:red;">`responseUrl`</mark> per order or define a merchant-level webhook on the “Developers” page within the [**Swapped.com Dashboard**](https://dashboard.swapped.com/developers). You will receive the notification via the provided URL. In the header of the HTTP request, there’s a signature to validate that the data comes from Swapped.com.

The callback destination is locked at order creation and cannot be changed.

### Callback Config Priority

The system follows a clear priority structure for determining where to send callbacks.

* If a responseURL is provided in the iframe initialization URL, this will be used as a priority.
* If a responseURL is not provided, but a callback URL is configured via the [Swapped.com dashboard](https://dashboard.swapped.com/developers), this will be used.
* If neither responseURL nor callback URL is set, callbacks will be disabled for this order.

This configuration is locked in when the order is created and cannot be changed, even if you later update your merchant-level webhook settings.

### Best Practices

Order notifications can be resent to account for network errors. As such, <mark style="color:red;">you</mark> <mark style="color:red;"></mark><mark style="color:red;">**must**</mark> <mark style="color:red;"></mark><mark style="color:red;">validate that a transaction has not been credited</mark> before crediting it.

For more information on notification resending, see the [Order Notification Retry Policy](https://docs.swapped.com/#order-notification-retry-policy).

### Callback examples:

#### Payment Pending:

The transaction was created, but the payment is still incomplete.

```json
{
  "order_id": "16a285c1-b04e-4b9f-b35d-a68fc292229e",
  "external_transaction_id": null,
  "external_customer_id": null,
  "order_status": "payment_pending",
  "order_crypto": "LTC",
  "order_type": "sell",
  "order_crypto_amount": "1.1880399307349",
  "order_crypto_address": "ltc1qgydf26ffh3zen6k75ye568rpqmes7fx4daqvrg",
  "order_crypto_tag": null,
  "order_amount_usd": 109.38,
  "order_amount_usd_plus_fees": 116.01,
  "order_amount_eur": 94.29,
  "order_amount_eur_plus_fees": 100,
  "network": "litecoin"
}
```

#### Payout pending:

Indicates that the cryptocurrency transaction has been confirmed on the chain and the payout to the user is pending.

```json
{
  "order_id": "81f2fcff-a81c-4e5a-8377-14bbe23fb1ef",
  "external_transaction_id": null,
  "external_customer_id": null,
  "order_status": "payout_pending",
  "order_crypto": "SOL",
  "order_type": "sell",
  "order_crypto_amount": 0.060096622,
  "order_crypto_address": "7frXvz2EutQmsmX6mgFMTE9MPuLsSPT2mgEro2EzPoNz",
  "order_crypto_tag": null,
  "order_amount_usd": 10.21,
  "order_amount_usd_plus_fees": 10.45,
  "order_amount_eur": 8.8,
  "order_amount_eur_plus_fees": 9.01,
  "network": "solana",
  "transaction_id": "C2237DF9D3268F715A80E48BF20D860C495B9726F28097A9AA18399F49BB7342"
}
```

#### Order Completed:

Indicates that the order has been processed, and the sale of cryptocurrency was successful.

```json
{
  "order_id": "81f2fcff-a81c-4e5a-8377-14bbe23fb1ef",
  "external_transaction_id": null,
  "external_customer_id": null,
  "order_status": "order_completed",
  "order_crypto": "SOL",
  "order_type": "sell",
  "order_crypto_amount": "0.060096622",
  "order_crypto_address": "7frXvz2EutQmsmX6mgFMTE9MPuLsSPT2mgEro2EzPoNz",
  "order_crypto_tag": null,
  "order_amount_usd": 10.21,
  "order_amount_usd_plus_fees": 10.45,
  "order_amount_eur": 8.8,
  "order_amount_eur_plus_fees": 9.01,
  "network": "solana",
  "transaction_id": "C2237DF9D3268F715A80E48BF20D860C495B9726F28097A9AA18399F49BB7342"
}
```

#### Order Cancelled:

Indicates that the order is cancelled for any reason, such as payment failure or user cancellation.

```json
{
  "order_id": "16a285c1-b04e-4b9f-b35d-a68fc292229e",
  "external_transaction_id": null,
  "external_customer_id": null,
  "order_status": "order_cancelled",
  "order_crypto": "LTC",
  "order_type": "sell"
}
```

### Response Definition:

* <mark style="color:red;">`order_id`</mark>: The order ID on Swapped.com.
* <mark style="color:red;">`order_crypto_amount`</mark>: The exact cryptocurrency amount you will receive.
* <mark style="color:red;">`order_crypto`</mark>: The cryptocurrency you receive.
* <mark style="color:red;">`order_status`</mark>: The current status of the order.
* <mark style="color:red;">`order_crypto_address`</mark>: The cryptocurrency address where you receive the cryptocurrency.
* <mark style="color:red;">`external_customer_id`</mark>: Your customer's ID (If provided in the URL).
* <mark style="color:red;">`order_amount_usd`</mark>: The <mark style="color:orange;">`order_crypto_amount`</mark> converted to USD (Mid-market rates without spread). This does not include the platform fee.
* <mark style="color:red;">`order_crypto_tag`</mark>: The destination tag/memo of the order (often used with e.g. XRP or TON)
* <mark style="color:red;">`order_amount_usd_plus_fees`</mark>: The <mark style="color:red;">`order_amount_usd`</mark> plus the platform fee.
* <mark style="color:red;">`network`</mark>: The network used to send transactions.
* <mark style="color:red;">`order_type`</mark>: Indicator if the order is a buy or sell order.
* <mark style="color:red;">`transaction_id`</mark>: The crypto transaction hash.

### Order State Flows

An order can follow one of two possible state flows:

Flow 1: This is applied when an order gets completed successfully and the user receives crypto:

<mark style="color:red;">`payment_pending`</mark> →<mark style="color:red;">`order_processing`</mark>→<mark style="color:red;">`payout_pending`</mark>→ <mark style="color:red;">`order_completed`</mark>

Flow 2: This occurs when an order gets cancelled for any reason, and the user does not receive crypto:

<mark style="color:red;">`payment_pending`</mark> → <mark style="color:red;">`order_cancelled`</mark>

Both <mark style="color:red;">`order_completed`</mark> and <mark style="color:red;">`order_cancelled`</mark> are final states that correspond to a finalized swapped.com order ID. This means that an order will **never** go from a <mark style="color:red;">completed</mark> to a <mark style="color:red;">cancelled</mark> state.

### The signature:

Compute an HMAC with a SHA-256 hash function. Use your secret API key as the key and use the request body as the message. Compare this to the signature sent in the request header.

#### Example with NodeJS:

```javascript
import crypto from 'crypto';

const secretKey = 'sk_test_key'; // Replace with your secret key
const requestBody = '{ "order_id": "9fcc45a5-4def-4953-9bd8-9ff75d9aaa9c"}'

const signature =
  crypto
    .createHmac('sha256', secretKey)
    .update(requestBody)
    .digest('base64'); 
```


# Sandbox Environment

### Accessing the Sandbox

Swapped.com's sandbox environment can be accessed via <https://sandbox.swapped.com/sell>.&#x20;

Swapped.com's sandbox environment allows merchants to test their integration before going live. This ensures that all functionality is working as expected without real funds being charged. **The sandbox environment operates exclusively with BTC & ETH testnet cryptocurrencies.**

### Generating a Sandbox iFrame

To generate a sandbox iframe, follow these steps:

1. Use the following keys:

   ```
   Public Key: pk_sandbox_rT9bW3sN6mJ8F5hP2cRqLvZ7SaD4XoY9
   Private Key: sk_sandbox_gV4eT2aK5bP6C7nR3fWmQxY8FdZ9HhE2
   ```
2. Follow the instructions on the [**iframe-initialization**](/swapped-ramp/off-ramp-integration/iframe-initialization) page to generate an iframe URL and signature.


# Cryptocurrencies and Confirmations

| Code              | Name               | Confirmations |
| ----------------- | ------------------ | ------------- |
| `ADA`             | Cardano            | 15            |
| `APE`             | Apecoin            | 12            |
| `ARB`             | Arbitrum           | 12            |
| `ATOM`            | Cosmos             | 1             |
| `AVAX`            | Avalanche          | 1             |
| `BCH`             | Bitcoin Cash       | 1             |
| `BNB`             | BNB                | 12            |
| `BTC`             | Bitcoin            | 1             |
| `DAI_ETHEREUM`    | DAI                | 12            |
| `DOGE`            | Dogecoin           | 20            |
| `ETH`             | Ethereum           | 12            |
| `HYPE`            | Hyperliquid        | 12            |
| `LINK_ETHEREUM`   | Chainlink          | 12            |
| `LTC`             | Litecoin           | 6             |
| `OP`              | Optimism           | 12            |
| `OSMO`            | Osmosis            | 1             |
| `PAXG`            | Pax Gold           | 12            |
| `POLYGON`         | Polygon            | 80            |
| `SAND`            | Sandbox            | 12            |
| `SHIB`            | Shiba Inu          | 12            |
| `SOL`             | Solana             | 1             |
| `TON`             | Toncoin            | 1             |
| `TRX`             | Tron               | 12            |
| `TWT`             | Trust Wallet Token | 12            |
| `UNI`             | Uniswap            | 12            |
| `USDC_ARBITRUM`   | USDC               | 12            |
| `USDC_AVAX`       | USDC               | 1             |
| `USDC_BASE`       | USDC               | 12            |
| `USDC_ETHEREUM`   | USDC               | 12            |
| `USDC_NOBLE`      | USDC               | 12            |
| `USDC_POLYGON`    | USDC               | 12            |
| `USDC_SOLANA`     | USDC               | 1             |
| `USDCE_POLYGON`   | USDCe              | 8             |
| `USDCE_WORLDCOIN` | USDCe              | 12            |
| `USDT_AVAX`       | Tether             | 1             |
| `USDT_BSC`        | USDT               | 12            |
| `USDT_ETHEREUM`   | Tether             | 12            |
| `USDT_POLYGON`    | Tether             | 12            |
| `USDT_SOLANA`     | Tether             | 1             |
| `USDT_TON`        | Tether             | 1             |
| `USDT_TRON`       | Tether             | 12            |
| `XAUT`            | Tether Gold        | 12            |
| `XRP`             | XRP                | 1             |


# Supported Payout Methods

Supported payout methods and corresponding fiat currencies

Globally available:

* `bank-transfer` (EUR, DKK, GBP)
* `skrill` (EUR, DKK, GBP)

Available in Brazil:

* `pix` (BRL)

Available in Canada:

* `interac-extra` (CAD)&#x20;


# Endpoints

{% content-ref url="/pages/XMbG7ZRxM9LFVO7Zj8co" %}
[Onramp Endpoints](/swapped-ramp/endpoints/onramp-endpoints)
{% endcontent-ref %}

{% content-ref url="/pages/uCDpj7lbtcxn4WdVIG6Z" %}
[Offramp Endpoints](/swapped-ramp/endpoints/offramp-endpoints)
{% endcontent-ref %}

{% content-ref url="/pages/F2tbSufzf05MizW2bR9Q" %}
[Misc. Endpoints](/swapped-ramp/endpoints/misc.-endpoints)
{% endcontent-ref %}


# Onramp Endpoints

## Current supported endpoints:

{% content-ref url="/pages/LgxKmh54nmiVcwAYjOWX" %}
[Get Current Price](/swapped-ramp/endpoints/onramp-endpoints/get-current-price)
{% endcontent-ref %}

{% content-ref url="/pages/CXNbtEkutTgoKlom84Uz" %}
[Get Payment Methods](/swapped-ramp/endpoints/onramp-endpoints/get-payment-methods)
{% endcontent-ref %}


# Get Current Price

This endpoint breaks down cryptocurrency purchase pricing, including fees, markups, and conversions, so that you can display accurate costs to your users before order creation.

**All pricing information can be retrieved with a POST request.**

URL: <https://widget.swapped.com/api/v1/merchant/pricing>

#### Request Data:

```json
{
    "api_key": "",
    "payment_method": "creditcard",
    "fiat_currency": "USD",
    "fiat_amount": 500,
    "crypto_currency": "ETH",
    "crypto_amount": 1,
    "region": "BE"
}
```

**Note:** The <mark style="color:red;">`crypto_amount`</mark> and <mark style="color:red;">`fiat_amount`</mark> fields are optional. If only one is provided, the other is calculated based on the current exchange rate.

**Note:** <mark style="color:red;">`payment_method`</mark> value must be a valid [payment group](https://widget.swapped.com/api/v1/merchant/get_payment_methods), and <mark style="color:red;">`region`</mark> is required, or the request will fail.

#### Markup Parameter

Optionally, the <mark style="color:red;">`markup`</mark> parameter can be used to apply a different markup on a per-request basis without modifying your merchant default.

#### Request Data with Markup:

```json
{
    "api_key": "",
    "payment_method": "creditcard",
    "fiat_currency": "USD",
    "fiat_amount": 500,
    "crypto_currency": "ETH",
    "crypto_amount": 1,
    "markup": 3,
    "region": "BE"
}
```

### Request Definition:

* `api_key`: The merchant's public key. Identifies the requesting merchant.
* `payment_method`: Payment method to use (e.g., `creditcard`).
  * &#x20;[Get valid methods via the payment methods endpoint.](/swapped-ramp/endpoints/onramp-endpoints/get-payment-methods)
* `fiat_currency`: The fiat currency you want to query. For the full list of supported currencies, see [here](/swapped-ramp/readme/supported-fiat-currencies).
* `fiat_amount`: The fiat amount you want to convert.
* `crypto_currency`: The cryptocurrency you want to convert to. For the full list of supported currencies, see [here](/swapped-ramp/readme/supported-cryptocurrencies).
* `crypto_amount`: The cryptocurrency amount you want to convert to.
* `region`: The 2-letter ISO-3166 code of the country the method is available in.
* `markup`: An additional fee applied to the cryptocurrency purchase price. Value must be between 0 and 5.

## Response data:

```json
{
    "success": true,
    "data": {
        "crypto_amount": 0.12284,
        "crypto_currency": "ETH",
        "crypto_unit_price": 4070.34,
        "network_fee": 0.2,
        "network_fee_local": 0.24,
        "fiat_amount_incl_fees": 440.85,
        "fiat_amount_excl_fees": 424.61,
        "fiat_amount_incl_fees_local": 519.12,
        "fiat_amount_excl_fees_local": 500,
        "fiat_currency": "USD",
        "markup_fiat_value": 20,
        "processing_fee": 19.11,
        "payment_method": "creditcard-extra",
        "payment_group": "creditcard"
    }
}
```

### Response Definition:

* `crypto_amount`: Amount of crypto the user will receive (e.g., 0.14137 ETH).
* `crypto_currency`: The crypto token used (e.g., "ETH").
* `crypto_unit_price`: Price per 1 unit of crypto in the given fiat (e.g., 3536.82 EUR per ETH).
* `network_fee`: Network fee in EUR.
* `network_fee_local`: Provides the network fee amount converted to the user's local fiat currency.
* `fiat_amount_incl_fees`: Fiat value the user is paying, including fees, in EUR.
* `fiat_amount_excl_fees`: Fiat value the user is paying, excluding fees, in EUR.
* `fiat_amount_incl_fees_local`: Total fiat paid, including fees, in user’s fiat currency (e.g., USD).
* `fiat_amount_excl_fees_local`: Total fiat paid, excluding fees, in user’s fiat currency (e.g., USD).
* `fiat_currency`: The local fiat currency (e.g., "USD").
* `markup_fiat_value`: Additional markup displayed in fiat.
* `processing_fee`: Total processing fee in local fiat (e.g., 19.21 EUR).
* `payment_method`: The payment method used for the order.
* `payment_group`: The payment group the method belongs to.

{% hint style="danger" %}
All <kbd><mark style="color:red;">/merchant/<mark style="color:red;"></kbd> endpoints are subject to a global rate limit of **100 requests per second**. Exceeding this limit may result in throttling.
{% endhint %}


# Get Payment Methods

**All payment methods & their supported countries can be retrieved with a GET request.** \
URL: <https://widget.swapped.com/api/v1/merchant/get_payment_methods>\
\
The public key can be appended to filter down the endpoint to only display your available methods. \
\
<https://widget.swapped.com/api/v1/merchant/get_payment_methods?apiKey=YOUR_API_KEY>

{% hint style="warning" %}
The value to use with the [method parameter](https://docs.swapped.com/swapped-ramp/readme/iframe-initialization#optional-parameters) is **payment\_group.**&#x20;
{% endhint %}

Response:

```json
{
  "id": 101,
  "name": "Card",
  "fee": 1.75,
  "slug": "creditcard-extra",
  "default": true,
  "currency": [
    "DKK",
    "GBP",
    "CHF",
    "JPY",
    "BRL",
    "IDR",
    "BGN",
    "VND"
  ],
  "base_fee": {
    "base_fee": 0.35
  },
  "disabled": false,
  "min_fee": 0,
  "min_amount": 7,
  "max_amount": 100000,
  "payment_group": "creditcard",
  "img_url": "https://widget.swapped.com/images/payment/creditcard.svg",
  "img_url_light": "https://widget.swapped.com/images/payment/creditcardlight.svg"
}
```

{% hint style="warning" %}
**Please note: The 'creditcard' payment method includes both credit and debit card transactions.**&#x20;
{% endhint %}

### Response Definition:

* `id`: The payment method ID.
* `name`: The name of the payment method.
* `fee`: The fee percentage as an integer.
* `slug`: The internal name for the payment method.
* `currency`: The currencies the payment method supports.
* `base_fee`: The base fee in EUR for the payment method.&#x20;
* `disabled`: Whether the method is disabled or not.
* `min_fee`: The minimum fee for the payment method in EUR.
* `min_amount`: The minimum amount in EUR that this payment supports.
* `max_amount`: The maximum amount in EUR that this payment supports.
* `payment_group`: The group a payment method belongs to.
* `img_url`: The standard image URL for the payment method logo.
* `img_url_light`: The light theme (dark background) variant image URL for the payment method logo.

The total fee for a method is a combination of `base_fee` + `fee`. i.e. 1.75% of the order total + 0.35 EUR.

If you wish to use this endpoint for testing ingress of payment methods you can include <mark style="color:red;">`include_mock_methods=true`</mark> in your GET request. It appends a fake method to every available country.\
**Please note this parameter is only available in sandbox.**&#x20;

{% hint style="danger" %}
All <kbd><mark style="color:red;">/merchant/<mark style="color:red;"></kbd> endpoints are subject to a global rate limit of **100 requests per second**. Exceeding this limit may result in throttling.
{% endhint %}


# Offramp Endpoints

{% content-ref url="/pages/M99mGhtgMqbL452CNBXv" %}
[Get Payout Methods](/swapped-ramp/endpoints/offramp-endpoints/get-payout-methods)
{% endcontent-ref %}

{% content-ref url="/pages/7xSvq8vcy8H25md9lfMr" %}
[Get Current Price](/swapped-ramp/endpoints/offramp-endpoints/get-current-price)
{% endcontent-ref %}


# Get Payout Methods

**All payment methods & their supported countries can be retrieved with a GET request.** \
URL: [https://widget.swapped.com/api/v1/merchant/sell/get\_payout\_methods](https://widget.swapped.com/api/v1/merchant/sell/get_payout_methods?api_key=YOUR_API_KEY)

\
The public key can be appended to filter down the endpoint to only display your available methods. \
\
<https://widget.swapped.com/api/v1/merchant/sell/get_payout_methods?api_key=YOUR_API_KEY>

### Response Structure:

No parameters in URL:

{% code overflow="wrap" %}

```json
{
  "success": true,
  "data": {
    "BR": [
      {
        "id": 13,
        "name": "PIX",
        "fee": 2,
        "slug": "pix",
        "default": true,
        "currency": ["BRL"],
        "base_fee": {
          "base_fee": 0.1
        },
        "disabled": false,
        "min_amount": 7,
        "max_amount": 2400,
        "img_url": "https://widget.swapped.com/assets/payment/pix.svg",
        "img_url_light": "https://widget.swapped.com/assets/payment/pixlight.svg"
      }
    ]
  }
}
```

{% endcode %}

When country slug (in this example DK) is used: <https://widget.swapped.com/api/v1/merchant/sell/get_payout_methods?slug=DK>

```json
{
    "success": true,
    "data": [
      {
        "id": 1,
        "name": "Bank",
        "fee": 0.5,
        "slug": "bank-transfer",
        "default": true,
        "currency": ["EUR", "DKK", "GBP"],
        "base_fee": {
          "EUR": 0,
          "DKK": 0,
          "GBP": 0.4
        },
        "disabled": false,
        "min_amount": 7,
        "max_amount": 1000000,
        "img_url": "https://widget.swapped.com/assets/payment/bank-transfer.svg",
        "img_url_light": "https://widget.swapped.com/assets/payment/bank-transferlight.svg"
      }
    ]
  }
```

Data Fields Returned:

<mark style="color:red;">`name`</mark>: Name of the payment method.

<mark style="color:red;">`fee`</mark>: Processing fee in percentage.

<mark style="color:red;">`slug`</mark>: Identifier for the payment method.

<mark style="color:red;">`default`</mark>: Whether this is the default method for the country.&#x20;

<mark style="color:red;">`currency`</mark>: An array of supported fiat currencies.&#x20;

<mark style="color:red;">`base_fee`</mark>: Fixed fee amounts per currency.&#x20;

<mark style="color:red;">`disabled`</mark>: Whether the method is disabled or not.&#x20;

<mark style="color:red;">`min_amount`</mark>: The minimum amount in EUR that this method supports.&#x20;

<mark style="color:red;">`max_amount`</mark>: The maximum amount in EUR that this method supports.&#x20;

<mark style="color:red;">`img_url`</mark>: The standard image URL for the payment method logo.&#x20;

<mark style="color:red;">`img_url_light`</mark>: The light theme (dark background) variant image URL for the payment method logo.

{% hint style="danger" %}
All <kbd><mark style="color:red;">/merchant/<mark style="color:red;"></kbd> endpoints are subject to a global rate limit of **100 requests per second**. Exceeding this limit may result in throttling.
{% endhint %}


# Get Current Price

[POST /api/v1/merchant/sell/pricing](https://widget.swapped.com/api/v1/merchant/sell/pricing)

Returns a fiat quote based on the selected payout method and crypto.

### Request Data:

```json
{
    "payout_method": "skrill",
    "crypto_currency": "ETH",
    "fiat_amount": 500,
    "fiat_currency": "EUR",
    "api_key": ""
  }
```

### Request Definition:

* `payout_method`: Payment method slug (e.g., `skrill`, `bank-transfer`). For the full list of supported methods, see [here](/swapped-ramp/off-ramp-integration/supported-payout-methods).
* `crypto_currency`: Cryptocurrency code (e.g., `BTC`, `ETH`). For the full list of supported currencies, see [here](/swapped-ramp/off-ramp-integration/cryptocurrencies-and-confirmations).
* `fiat_amount`: Fiat amount being sold.
* `fiat_currency`: Fiat currency being sold.

**Optional:**

* `api_key`: The merchant's public key. Identifies the requesting merchant.

### Response Data:

{% code fullWidth="false" %}

```php
{
    "success": true,
    "data": {
        "crypto_amount": 0.16901475,
        "crypto_currency": "ETH",
        "crypto_unit_price": 3069.17,
        "network_fee": 0,
        "fiat_amount_incl_fees": 500,
        "fiat_amount_excl_fees": 481.9,
        "fiat_amount_incl_fees_local": 500,
        "fiat_amount_excl_fees_local": 481.9,
        "fiat_currency": "EUR",
        "markup_fiat_value": 0,
        "processing_fee": 18.1
    }
}
```

{% endcode %}

### Response Definition:

* `crypto_amount`: Amount of crypto the user receives.
* `crypto_currency`: The crypto being sold (e.g., "ETH").
* `crypto_unit_price`: Price of 1 crypto unit in `fiat_currency` (EUR).
* `network_fee`: Blockchain fee in crypto (0 if not applied).
* `fiat_amount_incl_fees`: Total fiat incl. fees (EUR).
* `fiat_amount_excl_fees`: Fiat amount before fees (EUR).
* `fiat_amount_incl_fees_local`: Same as above, in local fiat (EUR here).
* `fiat_amount_excl_fees_local`: Same as above, excl. fees, in local fiat (EUR here).
* `fiat_currency`: User’s fiat currency (also the base currency here).
* `markup_fiat_value`: Merchant-added markup in fiat.
  * **Merchants can add a markup via** <mark style="color:blue;">`dashboard.swapped.com > Settings > Affiliate Fee`</mark>.
  * Only the **workspace owner** can configure this.
* `processing_fee`: Processing fee in fiat (EUR).

{% hint style="danger" %}
All <kbd><mark style="color:red;">/merchant/<mark style="color:red;"></kbd> endpoints are subject to a global rate limit of **100 requests per second**. Exceeding this limit may result in throttling.
{% endhint %}


# Misc. Endpoints

[Need help with your integration? Click here to chat with our custom GPT for instant answers.](https://chatgpt.com/g/g-67ef959ca3e88191a03120f448ebdb56-swapped-com-integration-api-documentation)

{% content-ref url="/pages/vRhxvORk0n2yqJYCPsqt" %}
[Get Minimum Amount](/swapped-ramp/endpoints/misc.-endpoints/get-minimum-amount)
{% endcontent-ref %}

{% content-ref url="/pages/YbmtLlXLwAmmloH2IiFC" %}
[Get supported](/swapped-ramp/endpoints/misc.-endpoints/get-supported)
{% endcontent-ref %}

{% content-ref url="/pages/JRNxTstDa0pHzaeZisKu" %}
[Get Payment Status](/swapped-ramp/endpoints/misc.-endpoints/get-payment-status)
{% endcontent-ref %}

{% content-ref url="/pages/iDSkFylI1HqOBVY3nFeK" %}
[Get Transactions](/swapped-ramp/endpoints/misc.-endpoints/get-transactions)
{% endcontent-ref %}


# Get Minimum Amount

All minimum accepted amounts for each fiat currency can be retrieved with a GET request. Please note these values are cached for 10 minutes.

URL: <https://widget.swapped.com/api/v1/merchant/get_min_amount>

Response example:

```json
{
  "success": true,
  "data": {
    "EUR": 7,
    "GBP": 6,
    "BRL": 43,
    "RON": 35,
    "NOK": 83,
    "MYR": 34
  }
}
```

{% hint style="danger" %}
All <kbd><mark style="color:red;">/merchant/<mark style="color:red;"></kbd> endpoints are subject to a global rate limit of **100 requests per second**. Exceeding this limit may result in throttling.
{% endhint %}


# Get supported

The endpoint returns all standardised codes (ISOs) for supported FIAT currencies, cryptocurrencies, and countries.

**Endpoint:**\
[`GET /api/v1/merchant/get_supported`](http://widget.swapped.com/api/v1/merchant/get_supported)

Respons&#x65;**:**

```json
{
    "success": true,
    "data": {
        "supported_fiats": [
            {
                "iso": "BRL",
                "name": "Brazilian Real"
                "exchange_rate": "6.364674"
            }
        ],v
        "supported_cryptos": [
            {
                "id": 35,
                "name": "USDC (POL)",
                "iso": "USDC",
                "type": "token",
                "network": "polygon",
                "network_fee": "0",
                "tags": [
                    "USDC_POLYGON"
                ]
            }
        ],
        "supported_countries": [
            {
                "iso": "US",
                "name": "United States",
                "currency": "USD"
            }
        ]
    }
}
```

### Response Definition:

* `supported_fiats` : Supported FIAT currencies.
  * `iso`Standardised short codes for the FIAT currency.
  * `name` : Name of the currency
  * `exchange_rate`: field shows the currency's value relative to EUR
* `supported_cryptos` : Supported cryptocurrencies
  * `id` : The ID of the cryptocurrency&#x20;
  * `name` : Name of the crypto
  * `iso`: The standardised short code for the crypto
  * `type`: Whether if it's a token or a coin &#x20;
  * `network`: The network the crypto belongs to.
  * `network_fee` : The network fee in EUR.
  * `tags`: The value(s) merchants can use as currency when initialising an iframe.
* `supported_countries` : The supported countries.
  * `iso`The standardised short codes for the countries.
  * `name` : Name of the country
  * `currency`: Default currency for that country.

{% hint style="danger" %}
All <kbd><mark style="color:red;">/merchant/<mark style="color:red;"></kbd> endpoints are subject to a global rate limit of **100 requests per second**. Exceeding this limit may result in throttling.
{% endhint %}


# Get Payment Status

The get\_status endpoint returns the last attempted IPN/callback webhook, regardless of whether it succeeded. It requires that an IPN attempt has been made.

**A POST request has to be made to call for this information.**

URL: <https://widget.swapped.com/api/v1/merchant/get_status>

Request Data:

```json
{
  "order_id": "swapped_order_id",
  "api_key": "your_public_key"
}
```

Response:

{% code overflow="wrap" %}

```json
{
  "success": true,
  "data": {
    "order_id": "swapped_order_id",
    "external_transaction_id": "",
    "external_customer_id": "123456",
    "order_status": "order_broadcasted",
    "order_type": "buy",
    "order_crypto": "LTC",
    "order_crypto_amount": "0.086584360432545",
    "order_crypto_address": "ltc1q2k0xaafhgt3s8qw03wmajjmlc8gcepdy0un0ah",
    "order_crypto_tag": null,
    "order_amount_usd": 9.32,
    "order_amount_usd_plus_fees": 10.02,
    "order_amount_eur": 8.99,
    "order_amount_eur_plus_fees": 9.67,
    "network": "litecoin",
    "transaction_id": "3885ab47b19f0b1b49b722f7de0e2d81e1b0916a21a4718541e876762aaea93f",
    "markup_fiat_value": 0,
    "processing_fee": 2.5
  }
}

```

{% endcode %}

### Response Definition:

* `order_id`: The order ID on Swapped.com.
* `external_transaction_id`: <mark style="color:red;">**DEPRECATED**</mark>
* `external_customer_id`: Your user's ID (If provided in the URL).
* `order_status`: The current status of the order.
* `order_crypto`: The cryptocurrency that was purchased.
* `order_crypto_amount`: The amount of crypto sent.
* `order_crypto_address`: The crypto address the crypto was sent to.
* `order_amount_usd`: The total order amount without fees in USD.
* `order_amount_usd_plus_fees`: The total order amount including fees in USD.
* `order_amount_eur`: The total order amount without fees in EUR.
* `order_amount_eur_plus_fees`: The total order amount including fees in EUR.
* `network`: The network the crypto belongs to.
* `order_status`: The current status of the order.
* `transaction_id`: The transaction ID on the blockchain.
* `markup_fiat_value`: The markup (in fiat) added on top of the base price.
* `processing_fee`: The processing fee (in fiat) charged for the transaction.&#x20;

{% hint style="danger" %}
All <kbd><mark style="color:red;">/merchant/<mark style="color:red;"></kbd> endpoints are subject to a global rate limit of **100 requests per second**. Exceeding this limit may result in throttling.
{% endhint %}


# Get Transactions

This endpoint allows for mass querying of all transactions created by your users.

**Type: POST**

**URL**:  <https://widget.swapped.com/api/v1/merchant/get_transactions>

**Params**:&#x20;

* <mark style="color:red;">`apiKey`</mark>: Required, your public key.
* <mark style="color:red;">`timestamp`</mark>: Required, an ISO 8601 formatted UTC timestamp within 5 seconds of the request being received.
* <mark style="color:red;">`signature`</mark>: Required, SHA-256 hash of the body using your secret key. See below for more information on how to generate this.
* <mark style="color:red;">`page`</mark>: Optional, the page number you wish to access.
* <mark style="color:red;">`limit`</mark>: Optional, the number of results per page, max: 100.
* <mark style="color:red;">`start_date`</mark>: Optional, ISO 8601 formatted UTC timestamp.
* <mark style="color:red;">`end_date`</mark>: Optional, ISO 8601 formatted UTC timestamp.
* <mark style="color:red;">`order_id`</mark>: Optional, the Swapped.com order ID

Example Body:

{% code fullWidth="true" %}

```json
{
    "apiKey": "public_key",
    "timestamp": "2025-05-16T09:38:25.000Z",
    "signature": "RAsRZUtDHhyY/On0qWZcxVdQ0AAQE+yUWk1/sf/pnI0="
}
```

{% endcode %}

Example Response:

{% code fullWidth="true" %}

```json
{
    "success": true,
    "data": {
        "orders": [
            {
                "order_id": "61b1d8f0-ab0e-4e18-b541-c62489d3869c",
                "created_at": "2025-11-10 00:32:20.812857+00",
                "updated_at": "2025-11-10 00:32:20.967135",
                "user_id": "8e93ccf4-5b44-4ce0-82d4-e64e0399a653",
                "order_total": 1529.27,
                "order_crypto": "XRP",
                "order_currency": "DKK",
                "order_status": "payment_pending",
                "order_payment_method": "bank-transfer",
                "order_type": "buy",
                "order_crypto_amount": 96.881233778549,
                "processing_fee": 7.65,
                "network_fee": 0,
                "fiat_rate": "7.467126",
                "blockchain_address": "raV5bXp9hNe5G4YFxLDSGHExL3bVyYmwZ9",
                "order_crypto_price": 2.06379,
                "transaction_id": null,
                "order_total_eur": 204.80034755005,
                "external_transaction_id": null,
                "external_customer_id": null,
                "merchant": "Test",
                "handling_fee": 3.932167,
                "response_url": "https://webhook.site/Swapped",
                "merchant_poi": false,
                "merchant_poa": false,
                "merchant_vip": false,
                "destination_tag": null,
                "crypto_network": "xrp",
                "markup": "0",
                "markup_total_eur": "0",
                "payment_group": "bank-transfer",
                "user_country": "BE"
            }
        ],
        "total": 1,
        "page": 1,
        "limit": 1,
        "pages": 1
    }
}
```

{% endcode %}

{% hint style="warning" %}

The `get_transactions` endpoint only returns the following states:

* `order_completed`
* `order_cancelled`
* `payment_pending`

`order_broadcasted` is a **pseudo-state** used only for merchant callbacks.

To infer if an order has been broadcast to the blockchain (i.e. `order_broadcasted`):

* If `order.transaction_id` is **set** = it's been broadcast.
* If `order.transaction_id` is **null** = it's still pending broadcast.
  {% endhint %}

All values for the following keys will **always** be in EUR:

* `processing_fee`
* `network_fee`
* `order_crypto_price`
* `order_total_eur`
* `handling_fee`

`order_total` will **always** be in the currency denoted in `order_currency`&#x20;

#### Order JSON Structure

The JSON response detailed above provides comprehensive information about a user's order. Below is a breakdown of key fields present within each order object:

### Order Details

* **User Information:**
  * `user_id`: Unique identifier for a swapped.com user.
  * `user_country`: The user's country.
  * `merchant_vip`: Is the user a VIP with the merchant
  * `merchant_poa`: Has the user completed proof of address with the merchant.
  * `merchant_poi`: Has the user completed proof of identity with the merchant.
* **Cryptocurrency Details:**
  * `order_crypto`: Cryptocurrency type (e.g., BTC).
  * `order_crypto_amount`: Amount of cryptocurrency in the transaction. Note this is updated when crypto is sent out.
  * `order_crypto_price`: Price of the cryptocurrency at the time of the order. Note this is updated when crypto is sent out.
* **Order Information:**
  * `order_id`: Unique identifier for the order.
  * `order_type`: Type of the order ('buy' or 'sell').
  * `order_status`: Current status (e.g., payment\_pending).
  * `order_currency`: Fiat currency used (e.g., DKK).
  * `order_total`: Total order value in the fiat currency.
  * `order_total_eur`: Total order value in EUR.
  * `created_at`: Order creation timestamp.
  * `updated_at`: Timestamp of the last update.
  * `order_payment_method`: The payment method used.
  * `payment_group`: The payment group the method belongsto.
* **Financial Details:**
  * `network_fee`: Network fee in EUR.
  * `fiat_rate`: Exposes the exchange rate used when the order was created, showing how local currency was converted to EUR.
  * `processing_fee`: Processing fee cost for this method in EUR.
  * `handling_fee`: Swapped's spread (1.92%) + any static processing fees&#x20;
  * `markup`: The merchant’s markup fee, if set, is a percentage expressed as a whole number (e.g. 1 = 1%), configurable in the [Swapped dashboard](https://dashboard.swapped.com/).
* **Transaction Details:**
  * `external_customer_id`: External identifier for the customer.
  * `external_transaction_id`: External transaction identifier.
  * `transaction_id`: Unique blockchain transaction ID.
  * `blockchain_address`: Cryptocurrency blockchain address.
* **Additional Information:**
  * `network_destination_tag`: Destination tag/memo/tag provided for the `wallet_address`&#x20;
  * `response_url`: URL provided for the callback, if provided.

**Generating A Signature:**

To create a `signature`, hash the JSON body of the request using your secret key with the SHA-256 algorithm. Make sure the JSON body is in a consistent string format before hashing.

Below are examples of how a signature hash can be generated correctly.

{% code overflow="wrap" %}

```php
<?php

$data = [
    "apiKey" => "example_public_key",
    "timestamp" => "2025-05-16T09:38:25.000Z"
];

// Convert to JSON string
$json_data = json_encode($data);

echo "Data being signed: <br><pre>" . $json_data . PHP_EOL . "</pre><br>";

// Use the correct secret key, replace with your actual secret key
$secret_key = "example_secret_key";

// Generate signature
$signature = base64_encode(hash_hmac('sha256', $json_data, $secret_key, TRUE));

echo "<br>Generated signature: <br>" . PHP_EOL . $signature . PHP_EOL . "<br>";

// Add signature to the original data array (not the JSON string)
$data['signature'] = $signature;

echo "<br>Data with signature: <br><pre>" . PHP_EOL . json_encode($data) . "</pre>" . PHP_EOL;
```

{% endcode %}

Postman Pre-Request Script:

```javascript
const publicKey = "YOUR KEY HERE";
const secretKey = "YOUR SECRET HERE";

function getISOTimestamp() {
   const now = new Date();
   const pad = (n) => String(n).padStart(2, '0');
   return `${now.getUTCFullYear()}-${pad(now.getUTCMonth()+1)}-${pad(now.getUTCDate())}T${pad(now.getUTCHours())}:${pad(now.getUTCMinutes())}:${pad(now.getUTCSeconds())}+00:00`;
}

const timestamp = getISOTimestamp();

// Get the request body and parse it
const requestBody = JSON.parse(pm.request.body.raw);

// Add/update required fields
requestBody.apiKey = publicKey;
requestBody.timestamp = timestamp;

// Remove signature field if it exists (before signing)
delete requestBody.signature;

// Generate signature from the body
const jsonData = JSON.stringify(requestBody);
const signature = CryptoJS.enc.Base64.stringify(
   CryptoJS.HmacSHA256(jsonData, secretKey)
);

// Add signature back to the body
requestBody.signature = signature;

// Update the request body
pm.request.body.raw = JSON.stringify(requestBody);

// Set environment variables for reference
pm.environment.set("apiKey", publicKey);
pm.environment.set("timestamp", timestamp);
pm.environment.set("signature", signature);
```

Example postman body (used with the above):

```json
{
  "apiKey": "{{apiKey}}",
  "timestamp": "{{timestamp}}",
  "order_id": "your_order_id_here",
  "signature": "{{signature}}"
}
```

{% hint style="danger" %}
All <kbd><mark style="color:red;">/merchant/<mark style="color:red;"></kbd> endpoints are subject to a global rate limit of **100 requests per second**. Exceeding this limit may result in throttling.
{% endhint %}


# Misc.


# Supported Languages

* Arabic
* Bulgarian
* Czech
* Danish
* German
* Greek
* English
* Spanish
* Estonian
* Finnish
* French
* Hebrew
* Croatian
* Hungarian
* Indonesian
* Italian
* Japanese
* Korean
* Lithuanian
* Latvian
* Malay
* Dutch
* Norwegian
* Filipino
* Polish
* Portuguese
* Romanian
* Slovak
* Slovenian
* Albanian
* Swedish
* Thai
* Turkish
* Vietnamese


# Order Notification Retry Policy

If Swapped fails to send any of the notifications mentioned in [Order Notifications](/swapped-ramp/readme/order-notifications) to your server, we will retry sending the notification for up to 24 hours.&#x20;

We'll retry using the following schedule:

* Once per minute for the first 5 attempts
* Once every 10 minutes for the next 5 attempts
* Once every 20 minutes for the next 5 attempts
* Once every 30 minutes for the next 5 attempts
* Once every hour until 24 hours from order creation have passed.

A 200 response code from your server will stop retries, indicating success. To prevent retries, respond with a 409 status code.\
\
**In the event of a missed order notification, you can resend the most recent notification directly from the** [**Swapped.com Dashboard**](https://dashboard.swapped.com/) **transaction page. This functionality is available to users with the roles of User, Developer or Admin. Or you may request a manually resent callback via your shared support channel.**


# FAQ

Answers to frequently asked questions.

## What is the manual review process?

A small subset of orders require a manual review, triggered by Swapped.com's anti-fraud system. Review decisions are completed within 10 minutes; in times of extreme load, it can take up to 30 minutes.&#x20;

## How are chargebacks handled?

In case of payment chargebacks, Swapped.com manages the dispute process on the merchant's behalf. Upon receiving a chargeback notification, Swapped.com automatically restrict the user's access to future transactions and notifies the merchant for their records. Swapped.com's chargeback policy includes no merchant penalties or associated fees. However, KYC may be requested as part of Swapped.com's data-sharing agreement.

## How are refunds handled?

Refunds are issued when the merchant returns the cryptocurrency to Swapped.com. Upon request, the merchant will be provided with a crypto wallet & must send the crypto to Swapped.com's designated address. Once received, Swapped.com processes the refund back to the user's original payment method.&#x20;

## Refund processing

Refunds typically take 24 hours but may take up to 5 business days, depending on the payment method used.

## What is a payment group?

A payment group is an identifier for a group of payment methods. Instead of using specific method slugs like "`apple-pay-extra`", use the `payment_group` as your method parameter value.

**How to use it:**\
Pass the `payment_group` value as the `method` parameter when generating an iframe URL.

**Where to find it:**\
Each payment method returned from the [Get Payment Methods endpoint](https://docs.swapped.com/swapped-ramp/readme/endpoints/get-payment-methods) includes its `payment_group` value.

**Documentation:**

* [iFrame Initialization](https://docs.swapped.com/swapped-ramp/readme/iframe-initialization) - Using the method parameter
* [Get Payment Methods Endpoint](https://docs.swapped.com/swapped-ramp/readme/endpoints/get-payment-methods) - Finding payment\_group values


# Connect Integration

[Need help with your integration? Click here to chat with our custom GPT for instant answers.](https://chatgpt.com/g/g-67ef959ca3e88191a03120f448ebdb56-swapped-com-integration-api-documentation)

**Swapped Connect** makes crypto deposits and top-ups from exchanges and wallets more intuitive by removing the complexity of sending crypto. It allows users to deposit and top up on your platform/app with minimal effort, protecting them from mistakes and malicious actors.

Rather than requiring the user to visit your platform's deposit/top-up page, copy a wallet address, select a network, and create a transaction, **Connect handles all of this automatically**. The widget is pre-filled with all the necessary information. Users must only enter the amount they wish to send and approve the transaction.

<figure><img src="https://2102146608-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDf1VBRUItvdLkWUnkNIb%2Fuploads%2FMWuKvDJEM8Lj4bbOuxsI%2FWeb3%20Index%20Standard.png?alt=media&amp;token=0ebf4955-df66-4c58-b805-d2da8aab2655" alt=""><figcaption></figcaption></figure>

There are three types of connections available with Swapped Connect:

* **Direct connection to the wallet or exchange**
  * This is the most intuitive and stable option, but not all wallets and exchanges offer direct integration yet.
* **API key connection**
  * The customer creates an API key from their wallet or exchange, allowing Swapped to send funds on their behalf.
* **Proxy connection**
  * The customer logs into their wallet or exchange, and Swapped initiates a temporary connection to complete the transaction.


# iFrame Initialization

### Required Parameters

* <mark style="color:red;">`apiKey`</mark>: Your publishable API key for customer identification and session validation. Also known as the public key. Can be found in the "**Developers**" section of the [swapped.com dashboard](https://dashboard.swapped.com/connect/developers).
* <mark style="color:red;">`walletAddress`</mark>: The crypto wallet where the user's funds will be sent. You can include one or more wallet entries, separated by commas. **Format to follow:** <mark style="color:blue;">`CURRENCY:NETWORK:ADDRESS:AMOUNT`</mark>
  * **CURRENCY** – token symbol (e.g., <mark style="color:blue;">`BTC`</mark>, <mark style="color:blue;">`SOL`</mark>, <mark style="color:blue;">`ETH`</mark>, <mark style="color:blue;">`USDT`</mark>)
  * **NETWORK** – on‑chain network identifier (e.g., <mark style="color:blue;">`bitcoin`</mark>, <mark style="color:blue;">`ethereum`</mark>, <mark style="color:blue;">`solana`</mark>)
  * **ADDRESS** – the on‑chain address itself (e.g., <mark style="color:blue;">`ltc1q2k0xaafhgt3s8qw03wmajjmlc8gcepdy0un0ah`</mark>)
  * **(OPTIONAL): AMOUNT** – Your minimum deposit amount in the specified cryptocurrency. This is **not** a USD value. For example, use `0.1` for a minimum of 0.1 BTC when `CURRENCY` is `BTC`. Leave this value out if there is no minimum. It must be greater than 0. Decimals are supported.
* <mark style="color:red;">`signature`</mark>: A cryptographic signature to verify the authenticity of the request. See the [**Server-Side URL Signature**](#server-side-url-signature) section below for implementation details.

If using one address, it’ll look like this:\ <mark style="color:blue;">`walletAddress=LTC:litecoin:ltc1q2k0xaafhgt3s8qw03wmajjmlc8gcepdy0un0ah`</mark>

If you want to accept multiple currencies, for example, Bitcoin, Litecoin, and Ethereum, format the <mark style="color:red;">`walletAddress`</mark> parameter as follows:\ <mark style="color:blue;">`walletAddress=BTC:bitcoin:yourBitcoinAddress,LTC:litecoin:yourLitecoinAddress,ETH:ethereum:yourEthereumAddress`</mark>

To enforce a minimum transaction amount on a specific address, **add it as the final value**:\ <mark style="color:blue;">`walletAddress=LTC:litecoin:yourLitecoinAddress:5`</mark>

Examples:

* <mark style="color:blue;">`BTC:bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa:0.1`</mark> – Bitcoin address with a minimum of 0.1 BTC
* <mark style="color:blue;">`ETH:ethereum:0x742d35Cc6634C0532925a3b844Bc454e4438f44e:0.5`</mark> – Ethereum address with a minimum of 0.5 ETH
* <mark style="color:blue;">`ETH:ethereum:0x742d35Cc6634C0532925a3b844Bc454e4438f44e`</mark> – Ethereum address with no minimum amount

### Optional Parameters

* <mark style="color:red;">`baseCurrencyCode`</mark>: The FIAT currency code for transactions (e.g., USD, EUR, GBP). See [**Supported Fiat currencies**](https://docs.swapped.com/readme/iframe-initialization/supported-fiat-currencies) for more options.
* <mark style="color:red;">`connection`</mark>: The exchange platform or wallet to use (e.g., Binance, Coinbase, Kraken, Phantom, etc.). See [supported connections](/swapped-connect/connect-integration/supported-connections) for available platforms and wallets.
* <mark style="color:red;">`destinationTag`</mark>: Adds a numeric destination tag (XRP) or text memo (TON) to identify specific recipients or provide transaction context.
* <mark style="color:red;">`baseCountry`</mark>: (ISO) The country code for the user's location. If not provided, it will be detected automatically. See [supported countries](https://swapped.com/supported-countries) for more options.
* <mark style="color:red;">`webhookUrl`</mark>: To receive webhooks, you can specify a webhook URL through this parameter - it must be URLencoded (**e.g., https%3A%2F%2Fwww\.myurl.com**).
* <mark style="color:red;">`payWalletAddress`</mark>: The crypto wallet where the user's funds will be sent for Exchange Pay products. Structure is the same as for required <mark style="color:red;">`walletAddress`</mark> parameter <mark style="color:blue;">`CURRENCY:NETWORK:ADDRESS:AMOUNT`</mark>, **e.g. USDC:solana:yourSolanaAddress,LTC:litecoin:yourLitecoinAddress:5**
* <mark style="color:red;">`externalCustomerId`</mark>: Your unique identifier for the customer.
* <mark style="color:red;">`preferredCurrencyToReceive`</mark>: The preferred currency to receive from Exchange Pay products. The user may still choose a different currency, however, if available, it will be displayed as the default currency in the initial selection screen. Structure is as follows: <mark style="color:blue;">`CURRENCY:NETWORK`</mark> **e.g. USDC:solana**
* <mark style="color:red;">`name`</mark>: Overrides the displayed merchant name in the Connect interface with a custom value. Must be URL-encoded (e.g., `My%20Store`)
* <mark style="color:red;">`logo`</mark>: A URL pointing to the merchant's logo to be displayed in the Connect interface. Must be a publicly accessible HTTPS URL and URL-encoded (e.g., `https%3A%2F%2Fexample.com%2Flogo.png`). Recommended formats: PNG or SVG.

### Server-Side URL Signature

Generate a signature to prevent the URL from being modified. This is done using the query string, including '?' and the secret key shared with you.

#### Example with NodeJS

{% code overflow="wrap" fullWidth="false" %}

```javascript
// Import the crypto module.
import crypto from 'crypto';

// Define the public API key.
const apiKey = 'your-api-key-12345';

// Define the secret API key.
const secretKey = 'your_secret_key';

// Define the wallet address.
const walletAddress = 'BTC:bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa:10';

// Build URL with query parameters.
const originalUrl = `https://connect.swapped.com/?apiKey=${apiKey}&walletAddress=${walletAddress}`;

// Create a SHA-256 HMAC signature from the URL's search string, then encode in Base64.
const signature = crypto.createHmac('sha256', secretKey).update(new URL(originalUrl).search).digest('base64');

// Append the URL-encoded signature to the original URL.
const urlWithSignature = `${originalUrl}&signature=${encodeURIComponent(signature)}`;

// Output the final URL with the signature appended.
console.log(urlWithSignature);
```

{% endcode %}

## Example with PHP

{% code overflow="wrap" fullWidth="false" %}

```php
<?php

// Define the public API key.
$apiKey = 'your-api-key-12345';

// Define the secret API key.
$secretKey = 'your_secret_key';

// Define the wallet address.
$walletAddress = 'BTC:bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa:10';

// Build URL with query parameters.
$originalUrl = "https://connect.swapped.com/?apiKey={$apiKey}&walletAddress={$walletAddress}";

// Parse the URL into its components.
$parsedUrl = parse_url($originalUrl);

// Create a SHA-256 HMAC signature from the query string, then encode in Base64.
$signature = base64_encode(hash_hmac('sha256', '?'.$parsedUrl['query'], $secretKey, true));

// Append the URL-encoded signature to the URL.
$urlWithSignature = "{$originalUrl}&signature=" . urlencode($signature);

// Output the final URL with the signature appended.
echo $urlWithSignature;
```

{% endcode %}

### Example iFrame URL

**Note: This is a test key, so your key will be different.**

<mark style="color:blue;">`https://connect.swapped.com/?apiKey=your-api-key-12345&walletAddress=BTC:bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa:10&signature=RyvwgGPnBBfP2VwKz1beHveU4%2BTjPIwRYNj0s6hKNVU%3D`</mark>

### Example iFrame

The iFrame has been optimized for height: 585px; width: 445px.

{% code overflow="wrap" fullWidth="false" %}

```html
<iframe
  allow="accelerometer; autoplay; camera; encrypted-media; gyroscope; payment; clipboard-read; clipboard-write"
  src="https://connect.swapped.com/?apiKey={your-api-key}&walletAddress=BTC:bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa:10&signature={your_signature}"
  title="Deposit with Swapped Connect"
  style="height: 585px; width: 445px; border-radius: 0.75rem; margin: auto;">
</iframe>
```

{% endcode %}

### Supported Networks

Below is a list of supported network identifiers — the values you supply in the [**NETWORK** ](#required-parameters)segment of your [`walletAddress` ](#required-parameters)parameter:

* Bitcoin: <mark style="color:red;">`bitcoin`</mark>
* Litecoin: <mark style="color:red;">`litecoin`</mark>
* Ethereum: <mark style="color:red;">`ethereum`</mark>
* Solana: <mark style="color:red;">`solana`</mark>
* Polygon: <mark style="color:red;">`polygon`</mark>
* Binance Smart Chain: <mark style="color:red;">`bsc`</mark>
* Ripple: <mark style="color:red;">`ripple`</mark>
* Base: <mark style="color:red;">`base`</mark>
* Tron: <mark style="color:red;">`tron`</mark>
* Avalanche: <mark style="color:red;">`avalanche`</mark>
* Arbitrum: <mark style="color:red;">`arb`</mark>
* Cronos: <mark style="color:red;">`cronos`</mark>
* Fantom: <mark style="color:red;">`fantom`</mark>
* Optimism: <mark style="color:red;">`optimism`</mark>

### Error Handling

The system will return an appropriate error message if an invalid signature or API key is provided.

Common errors include:

* Unknown partner - The API key is not recognized
* Invalid signature - The signature does not match the expected value
* Partner '\[name]' is disabled - This account is currently disabled. Please have an admin or higher contact our support for more information

**Ensure all required parameters are included and the signature is generated correctly to avoid these errors.**


# Supported Connections

**Supported Centralised Exchanges list:**

| Name              | Connection |
| ----------------- | ---------- |
| Binance Exchange  | `binance`  |
| Bitfinex Exchange | `bitfinex` |
| BtcTurk Exchange  | `btcturk`  |
| Bybit Exchange    | `bybit`    |
| Coinbase Exchange | `coinbase` |
| Gate Exchange     | `gate`     |
| HTX Exchange      | `htx`      |
| Kraken Exchange   | `kraken`   |
| KuCoin Exchange   | `kucoin`   |

**Supported Web3 Wallets list:**

| Name              | Connection          |
| ----------------- | ------------------- |
| Binance Wallet    | `binance_wallet`    |
| Bitget Wallet     | `bitget_wallet`     |
| Bybit Wallet      | `bybit_wallet`      |
| Coin98 Wallet     | `coin98_wallet`     |
| Coinbase Wallet   | `coinbase_wallet`   |
| Crypto.com Wallet | `crypto.com_wallet` |
| Exodus Wallet     | `exodus_wallet`     |
| Keplr Wallet      | `keplr_wallet`      |
| Kraken Wallet     | `kraken_wallet`     |
| MetaMask Wallet   | `metamask_wallet`   |
| OKX Wallet        | `okx_wallet`        |
| Phantom Wallet    | `phantom_wallet`    |
| Rainbow Wallet    | `rainbow_wallet`    |
| Robinhood Wallet  | `robinhood_wallet`  |
| Ronin Wallet      | `ronin_wallet`      |
| Trust Wallet      | `trust_wallet`      |
| Uniswap Wallet    | `uniswap_wallet`    |


# Order Notifications

To receive order notifications, you can provide a <mark style="color:red;">`webhookUrl`</mark> per session as a query parameter. You will receive the notification via the provided URL. In the header of the HTTP request, there’s a signature to validate that the data comes from Swapped.com.

The callback destination is locked at order creation and cannot be changed.

### Callback Config Priority

The system follows a clear priority structure for determining where to send callbacks.

* If a webhookUrl is provided in the iframe initialization URL, this will be used as a priority.
* If a webhookUrl is not set in the iframe initialization, callbacks will be disabled for this order.

This configuration is locked in when the order is created and cannot be changed.

### Best Practices

Order notifications can be resent to account for network errors. As such, <mark style="color:red;">you</mark> <mark style="color:red;"></mark><mark style="color:red;">**must**</mark> <mark style="color:red;"></mark><mark style="color:red;">validate that a transaction has not been credited</mark> before crediting it.

For more information on notification resending, see the [Order Notification Retry Policy](https://docs.swapped.com/#order-notification-retry-policy).

### Callback examples:

#### Payment Pending:

Indicates that the transaction has been created, but the customer hasn't completed payment.

```json
{
  "order_id": "eaf0fcb1-7543-4cad-a712-92caeb25db63",
  "order_crypto_amount": "0.0001",
  "order_crypto": "BTC",
  "order_crypto_address": "2uA6F27wYY6iwtVESsYUhG4VUAxx7mFD4EwMbwxNFmSm",
  "order_status": "payment_pending",
  "order_amount_usd": "5.000252367857236",
  "network": "bitcoin",
  "order_crypto_tag": null,
  "transaction_id": null,
  "external_customer_id": "User-fe1b9",
  "connection": "coinbase_wallet"
}
```

#### Order Completed:

Indicates that the order has been processed, and the sale of cryptocurrency was successful.

```json
{
  "order_id": "eaf0fcb1-7543-4cad-a712-92caeb25db63",
  "order_crypto_amount": "0.0001",
  "order_crypto": "BTC",
  "order_crypto_address": "2uA6F27wYY6iwtVESsYUhG4VUAxx7mFD4EwMbwxNFmSm",
  "order_status": "order_completed",
  "order_amount_usd": "5.000252367857236",
  "network": "bitcoin",
  "order_crypto_tag": null,
  "transaction_id": "9f488e8af23e68d091d171627766dd7224f4f67f84ca2c924dfd11a4a73c3d8c",
  "external_customer_id": "User-fe1b9",
  "connection": "coinbase_wallet"
}
```

<mark style="color:red;">The callbacks below should not be used to credit users and should only be used for analytical purposes.</mark>

**Wallet Order Registered:**

Indicates that a wallet transaction has been created, but has not been confirmed yet .

```json
{
  "order_id": "eaf0fcb1-7543-4cad-a712-92caeb25db63",
  "order_crypto_amount": "0.0001",
  "order_crypto": "BTC",
  "order_crypto_address": "2uA6F27wYY6iwtVESsYUhG4VUAxx7mFD4EwMbwxNFmSm",
  "order_status": "wallet_order_registered",
  "order_amount_usd": "5.000252367857236",
  "network": "bitcoin",
  "order_crypto_tag": null,
  "transaction_id": null,
  "external_customer_id": "User-fe1b9",
  "connection": "coinbase_wallet"
}
```

**Wallet Order Confirmed:**

Indicates that a wallet transaction has been confirmed and the order has been completed.

```json
{
  "order_id": "eaf0fcb1-7543-4cad-a712-92caeb25db63",
  "order_crypto_amount": "0.0001",
  "order_crypto": "BTC",
  "order_crypto_address": "2uA6F27wYY6iwtVESsYUhG4VUAxx7mFD4EwMbwxNFmSm",
  "order_status": "wallet_order_confirmed",
  "order_amount_usd": "5.000252367857236",
  "network": "bitcoin",
  "order_crypto_tag": null,
  "transaction_id": null,
  "external_customer_id": "User-fe1b9",
  "connection": "coinbase_wallet"
}
```

### Response Definition:

* <mark style="color:red;">`order_id`</mark>: The order ID on Swapped.com.
* <mark style="color:red;">`order_crypto_amount`</mark>: The exact cryptocurrency amount you will receive.
* <mark style="color:red;">`order_crypto`</mark>: The cryptocurrency you receive.
* <mark style="color:red;">`order_status`</mark>: The current status of the order.
* <mark style="color:red;">`order_crypto_address`</mark>: The cryptocurrency address where you receive the cryptocurrency.
* <mark style="color:red;">`external_customer_id`</mark>: Your customer's ID (If provided in the URL).
* <mark style="color:red;">`order_amount_usd`</mark>: The <mark style="color:orange;">`order_crypto_amount`</mark> converted to USD.
* <mark style="color:red;">`order_crypto_tag`</mark>: The destination tag/memo of the order (used with XRP)
* <mark style="color:red;">`network`</mark>: The network used to send transactions.
* <mark style="color:red;">`transaction_id`</mark>: The crypto transaction hash.
* <mark style="color:red;">`connection`</mark>: The connection used for the transaction. Provided as <mark style="color:orange;">`provider`</mark> for exchanges and <mark style="color:orange;">`provider_wallet`</mark> for wallets (e.g. <mark style="color:orange;">`phantom_wallet`</mark> , <mark style="color:orange;">`binance`</mark> )

### Order State Flows

Currently, an order can follow only one flow that is applied when an order gets completed successfully and the user receives crypto:

<mark style="color:red;">`payment_pending`</mark> → <mark style="color:red;">`order_completed`</mark>

### The signature:

Compute an HMAC with a SHA-256 hash function. Use your secret API key as the key and use the request body as the message. Compare this to the signature sent in the <mark style="color:orange;">`x-signature`</mark> request header.

#### Example with NodeJS:

```javascript
import crypto from 'crypto';

const secretKey = 'sk_test_key'; // Replace with your secret key
const requestBody = `{"order_id":"eaf0fcb1-7543-4cad-a712-92caeb25db63","order_crypto_amount":"0.0001","order_crypto":"BTC","order_crypto_address":"2uA6F27wYY6iwtVESsYUhG4VUAxx7mFD4EwMbwxNFmSm","order_status":"completed","order_amount_usd":"5.000252367857236","network":"bitcoin","transaction_id":"9f488e8af23e68d091d171627766dd7224f4f67f84ca2c924dfd11a4a73c3d8c","external_customer_id":"User-fe1b9"}`;

const signature =
  crypto
    .createHmac('sha256', secretKey)
    .update(requestBody)
    .digest('base64'); 
```


# Misc


# Order Notification Retry Policy

If we are unable to send any of the notifications mentioned in [Order Notifications](/swapped-ramp/readme/order-notifications) to your server, we will retry sending the notification for up to 24 hours.&#x20;

We'll retry using the following schedule:

* Once per minute for the first 5 attempts
* Once every 10 minutes for the next 5 attempts
* Once every 20 minutes for the next 5 attempts
* Once every 30 minutes for the next 5 attempts
* Once every hour until 24 hours from order creation have passed.

A 200 response code from your server will stop retries, indicating success. To prevent retries, respond with a 409 status code.\
\
**In the event of a missed order notification, you may request a manually resent callback via your shared support channel.**


