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

<AgentInstructions>

## Submitting Feedback

If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback:

POST https://developers.fireblocks.com/feedback

```json
{
  "path": "/docs/on-ramp-off-ramp-and-bridgeswap-via-account-based-providers-cefi",
  "feedback": "Description of the issue"
}
```

Only submit feedback when you have something specific and actionable to report.

</AgentInstructions>

# On/Off-Ramp, and cross-chain Swap via CeFi

<Info>
  ### **Beta Feature**

  The Trading API is currently in beta and subject to change. For participation details, contact your Fireblocks Customer Success Manager or email [CSM@fireblocks.com](mailto:CSM@fireblocks.com).
</Info>

This guide provides step-by-step examples of how to execute various order operations using the Fireblocks Trading API via account-based providers. These require you to connect an account before trading. For instructions on how to connect accounts, see [Fireblocks Connected Accounts](https://support.fireblocks.io/hc/en-us/articles/360017435399-Fireblocks-connected-accounts). This guide covers multiple use cases including on-ramp (fiat to crypto), off-ramp (crypto to fiat), and bridging (crypto-to-crypto).

## Prerequisites

Before you begin, ensure you have completed the prerequisites outlined in the [Trading API Overview](/docs/trading-api-overview#/):

* ✅ Fireblocks API credentials configured
* ✅ Fireblocks TypeScript SDK installed (`@fireblocks/version 13.x or later`)
* ✅ Connected account(s) set up with your chosen provider(s) via the Fireblocks Console (see [Fireblocks Connected Accounts](https://support.fireblocks.io/hc/en-us/articles/360017435399-Fireblocks-connected-accounts) for setup instructions)

## SDK Setup

First, set up your Fireblocks SDK client:

<CodeGroup>
  ```bash bash theme={"system"}
  import { Fireblocks } from '@fireblocks/ts-sdk';
  import * as fs from 'fs';

  // Initialize the Fireblocks SDK
  const fireblocks = new Fireblocks({
    apiKey: 'your-api-key',
    secretKey: fs.readFileSync('/path/to/your/secret.key', 'utf8'),
    basePath: 'https://api.fireblocks.io',
  });
  ```
</CodeGroup>

## Provider and account discovery

Before trading with account-based providers, find out which providers are available and which accounts you have connected. If you haven't connected any accounts yet, see [Fireblocks Connected Accounts](https://support.fireblocks.io/hc/en-us/articles/360017435399-Fireblocks-connected-accounts) for setup instructions.

### Step 1: Get Providers and Connected Accounts

Retrieve all trading providers. For account-based providers, the response includes provider information and connected accounts, allowing you to extract both `providerId` and `accountId` in a single call.

<CodeGroup>
  ```bash bash theme={"system"}
  // Get all trading providers
  const response = await fireblocks.trading.getTradingProviders({ pageSize: 20 });

  // Filter for account-based providers
  const accountBasedProviders = response.data.data.filter(p => p.accountBased);

  // Access provider and account information
  for (const provider of accountBasedProviders) {
    console.log(`Provider: ${provider.id} (${provider.name})`);
    provider.accounts?.forEach(account => {
      console.log(`  Account: ${account.id} (${account.name})`);
    });
  }
  ```
</CodeGroup>

### Response Example

<CodeGroup>
  ```bash bash theme={"system"}
  {
    "data": [
      {
        "id": "ALFREDPAY",
        "name": "Alfred Pay",
        "accountBased": true,
        "connected": true,
        "accounts": [
          {
            "id": "acc_5e9a2d1c4b7f3e8a",
            "name": "My Alfred Pay Account"
          }
        ],
        "manifest": {
          "assetTypes": ["FIAT", "DIGITAL"],
          "capabilities": ["TRADING"]
        }
      },
      {
        "id": "YELLOWCARD",
        "name": "Yellow Card",
        "accountBased": true,
        "connected": true,
        "accounts": [
          {
            "id": "acc_9f4e2d8b1c6a5e73",
            "name": "Yellow Card Main Account"
          }
        ],
        "manifest": {
          "assetTypes": ["FIAT", "DIGITAL"],
          "capabilities": ["TRADING"]
        }
      }
    ],
    "total": 2,
    "next": null
  }
  ```
</CodeGroup>

### Key Fields Explained

| Field          | Description                                                                                                                     |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `id`           | Unique identifier for the provider (use as `providerId` in subsequent API calls)                                                |
| `name`         | Display name of the provider                                                                                                    |
| `accountBased` | `true` for account-based providers, `false` for direct access providers                                                         |
| `connected`    | Whether you have at least one connected account with this provider                                                              |
| `accounts`     | Array of connected accounts for this provider. Each account has an `id` (use as `accountId` in subsequent API calls) and `name` |

<Info>
  ### For more details about this endpoint, see the [Get Providers API Reference](/reference/gettradingproviders).
</Info>

### Step 2: Get Supported Trading Pairs

For each connected account, discover which trading pairs are supported:

<CodeGroup>
  ```bash bash theme={"system"}
  // Get supported trading pairs for a specific connected account
  const response = await fireblocks.trading.getTradingPairs({
    accountId: 'acc_9f4e2d8b1c6a5e73',
  });

  // Response data
  const tradingPairs = response.data;
  // tradingPairs = [
  //   {
  //     "id": "7c9e8f2a-4b5d-4e1c-9a3b-6f8d2e5c7a1b",
  //     "toAsset": "USDC",
  //     "fromAsset": "USD",
  //     "prefunded": false,
  //     "fromAssetRail": "ACH"
  //   }
  // ]
  ```
</CodeGroup>

### Step 3: Get Indicative Rates

Get indicative rates for price preview (these are not executable quotes):

<CodeGroup>
  ```bash bash theme={"system"}
  // Get indicative rates
  const response = await fireblocks.trading.getRates({
    accountId: 'acc_9f4e2d8b1c6a5e73',
    baseAssetId: 'USD',
    quoteAssetId: 'BTC',
  });
  const rates = response.data;
  ```
</CodeGroup>

<Info>
  ### **Note:** Rates provide indicative prices for preview, while quotes return committed rates that can be executed until expiration.
</Info>

## Clarification on how to translating user intent into baseAssetId, quoteAssetId, side, and baseAmount

When creating a **Quote** or an **Order**, you express the trade using:

* `baseAssetId`: the asset you **receive** on **BUY** / **give** on **SELL**
* `quoteAssetId`: the counter asset used to **pay**/**receive**
* `side`:
  * `BUY`: receive base / pay quote
  * `SELL`: give base / receive quote
* `baseAmount`: amount in `baseAssetId`
  * `BUY`: base amount to receive
  * `SELL`: base amount to sell

### Examples

| Intent                  | baseAssetId | quoteAssetId | side | baseAmount |
| ----------------------- | ----------- | ------------ | ---- | ---------- |
| Buying 100 BTC with USD | BTC         | USD          | BUY  | 100        |
| Buying 100 USD with BTC | USD         | BTC          | BUY  | 100        |
| Selling 100 BTC for USD | BTC         | USD          | SELL | 100        |
| Selling 100 USD for BTC | USD         | BTC          | SELL | 100        |

## Participants & compliance

Participant details vary by provider and rail. The `participantsIdentification` object defines the originator and beneficiary involved in an order.

### Example structure

```json theme={"system"}
{
  "participantsIdentification": {
    "originator": {
      "externalReferenceId": "user_123",
      "participantRelationshipType": "FirstParty",
      "entityType": "INDIVIDUAL"
    },
    "beneficiary": {
      "participantRelationshipType": "ThirdParty",
      "fullName": {
        "firstName": "Alice",
        "lastName": "Lee"
      }
    }
  }
}
```

### Key concepts

* **First-party**: Acting for self — provider already holds KYC; minimal data required.
* **Third-party**: Acting for another — provider may require full PII.

The level of PII data required depends on the provider and the relationship type (first-party vs. third-party).

## Use Case Examples

The following sections demonstrate different trading use cases with account-based providers:

## Use Case 1: On-Ramp - DVP Settlement with Market Execution

**Use Case:** Convert fiat to crypto at the market rate. The user creates the order, receives payment instructions from the provider, deposits the funds, and once payment is confirmed, the provider executes and settles the crypto, ensuring delivery versus payment (DVP).

**Settlement Type:** DVP (Delivery vs Payment)\
**Execution Type:** Market

<Callout icon="📖" theme="default">
  ### **Note:** The `baseAssetId`, `baseAssetRail`, `quoteAssetId`, and `quoteAssetRail` values used in the order must match a supported trading pair returned from the `getTradingPairs` endpoint (see Step 2 in Getting Started). This ensures the provider supports the specific asset and rail combination you're requesting.
</Callout>

### Step 1: Create the Order

```typescript theme={"system"}
// Create on-ramp order with DVP settlement and market execution
const response = await fireblocks.trading.createOrder({
  createOrderRequest: {
    via: {
      type: 'PROVIDER_ACCOUNT',
      providerId: 'bridge-provider-001',
      accountId: 'acc_9f4e2d8b1c6a5e73',
    },
    executionRequestDetails: {
      type: 'MARKET',
      side: 'BUY',
      baseAmount: '1000',
      baseAssetId: 'USD',
      baseAssetRail: 'ACH',
      quoteAssetId: 'USDC',
      quoteAssetRail: 'BLOCKCHAIN',
    },
    settlement: {
      type: 'DVP',
      sourceAccount: {
        type: 'EXTERNAL',
      },
      destinationAccount: {
        type: 'ONE_TIME_ADDRESS',
        address: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
      },
    },
    participantsIdentification: {
      originator: {
        entityType: 'BUSINESS',
        participantRelationshipType: 'FirstParty',
      },
      beneficiary: {
        entityType: 'INDIVIDUAL',
        participantRelationshipType: 'ThirdParty',
        fullName: {
          lastName: 'Johnson',
          firstName: 'Alexander',
        },
        postalAddress: {
          streetName: 'Fifth Avenue',
          buildingNumber: '350',
          postalCode: '10118',
          city: 'New York',
          subdivision: 'NY',
          district: 'Manhattan',
          country: 'US',
        },
        externalReferenceId: 'person_ref_7f3e2d1c4b8a5e9f',
        dateOfBirth: '1985-03-15',
      },
    },
    customerInternalReferenceId: '32e423',
  },
  idempotencyKey: `order-${Date.now()}`,
});

const order = response.data;
```

### Step 2: Handle Payment Instructions

Since the settlement type is DVP and the source type is EXTERNAL, the funds will move from outside Fireblocks. The order creation response will include payment instructions for the rail which you select (e.g., ACH, SEPA, Wire):

```json theme={"system"}
{
  "paymentInstructions": {
    "referenceId": "REF-ACH-001",
    "type": "ACH",
    "address": {
      "accountHolder": {
        "name": "Bridge Provider Ltd.",
        "address": "123 Main Street",
        "city": "New York",
        "country": "US",
        "subdivision": "NY",
        "postalCode": "10001"
      },
      "bankName": "JPMorgan Chase Bank N.A.",
      "bankAccountNumber": "9876543210",
      "routingNumber": "021000021",
      "accountType": "CHECKING"
    }
  }
}
```

### Considerations

* For third-party payouts, like the one in the example, the provider must receive the beneficiary details (PII as required by the provider). In this case, you are the originator — acting as a first party, already KYC'd with the provider. Therefore, the only data needed is to set the `beneficiary.participantRelationshipType = "FirstParty"`.
* Since the settlement type is DVP and the source type is EXTERNAL, the funds will move from outside Fireblocks. As a result, the order creation response will include payment instructions for the rail which you select (e.g., ACH, SEPA, Wire).

## Use Case 2: On-Ramp - Prefunded settlement with quote execution

**Use Case:** Convert fiat to crypto at a locked rate from a committed quote. Funds are already held in the account; no payment instructions are returned in the response, and the provider will execute and settle the request immediately.

**Settlement Type:** Prefunded\
**Execution Type:** Quote

### Step 1: Create a Quote

```typescript theme={"system"}
// Create a quote for on-ramp
const quoteResponse = await fireblocks.trading.createQuote({
  createQuote: {
    scope: [
      {
        providerId: 'SCRYPT',
        accountId: 'scrypt_acc_5e9a2d1c4b7f3e8a',
      },
    ],
    side: 'BUY',
    baseAssetId: 'USDT_ERC20',
    quoteAssetId: 'TRX_USDT_S2UZ',
    baseAmount: '15000',
  },
  idempotencyKey: `quote-${Date.now()}`,
});

const quote = quoteResponse.data.quotes[0];
```

In the quote response, you will receive all related metadata, including the quote ID (`id`) and expiration time (`expiresAt`). The quote ID is then used in the next step to create an order and execute the trade.

### Step 2: Execute order with quote

```typescript theme={"system"}
// Execute order using the quote from Step 1
const response = await fireblocks.trading.createOrder({
  createOrderRequest: {
    via: {
      type: 'PROVIDER_ACCOUNT',
      accountId: 'acc_5e9a2d1c4b7f3e8a',
      providerId: 'ALFREDPAY',
    },
    executionRequestDetails: {
      type: 'QUOTE',
      reQuote: {
        type: 'MARKET',
      },
      quoteId: 'quote_8f2e4d1a9c5b7e3f',
    },
    settlement: {
      type: 'PREFUNDED',
      destinationAccount: {
        type: 'VAULT_ACCOUNT',
        accountId: 'vault_acc_9f3e2d1c4b8a7e5f',
      },
    },
    participantsIdentification: {
      originator: {
        entityType: 'INDIVIDUAL',
        participantRelationshipType: 'FirstParty',
      },
      beneficiary: {
        entityType: 'INDIVIDUAL',
        participantRelationshipType: 'FirstParty',
      },
    },
  },
  idempotencyKey: `order-${Date.now()}`,
});

const order = response.data;
```

### Considerations

* In this example, you perform an on-ramp for yourself, not for a third-party recipient. Therefore, both the originator and beneficiary use `"participantRelationshipType": "FirstParty"`, and no additional PII data is required.
* The `quoteId` used in the order request is the same ID returned in the response from the `POST /trading/quotes` call.

## Use Case 3: Off-Ramp - DVP settlement with market execution

**Use Case:** Convert crypto to fiat at the market rate. The provider waits for confirmation of the crypto deposits before finalizing the settlement, ensuring delivery versus payment (DVP).

**Settlement Type:** DVP\
**Execution Type:** Market

<Callout icon="📖" theme="default">
  ### **Note:** The `baseAssetId`, `baseAssetRail`, `quoteAssetId`, and `quoteAssetRail` values used in the order must match a supported trading pair returned from the `getTradingPairs` endpoint (see Step 2 in Getting Started). This ensures the provider supports the specific asset and rail combination you're requesting.
</Callout>

### Step 1: Create the Order

```typescript theme={"system"}
// Create off-ramp order with DVP settlement and market execution
const response = await fireblocks.trading.createOrder({
  createOrderRequest: {
    via: {
      type: 'PROVIDER_ACCOUNT',
      providerId: 'YELLOWCARD',
      accountId: 'acc_9f4e2d8b1c6a5e73',
    },
    executionRequestDetails: {
      type: 'MARKET',
      side: 'BUY',
      baseAmount: '250',
      baseAssetId: 'XOF',
      baseAssetRail: 'LOCAL_BANK_TRANSFER_AFRICA',
      quoteAssetId: 'USDT_ERC20',
      quoteAssetRail: 'BLOCKCHAIN',
    },
    settlement: {
      type: 'DVP',
      sourceAccount: {
        type: 'VAULT_ACCOUNT',
        accountId: 'vault_acc_5e9a2d1c4b7f3e8a',
      },
      destinationAccount: {
        type: 'EXTERNAL_WALLET',
        accountId: 'fiat_whitelisted_acc_9f3e2d1c4b8a7e5f',
      },
    },
    participantsIdentification: {
      originator: {
        entityType: 'INDIVIDUAL',
        participantRelationshipType: 'FirstParty',
      },
      beneficiary: {
        entityType: 'INDIVIDUAL',
        participantRelationshipType: 'FirstParty',
      },
    },
  },
  idempotencyKey: `order-${Date.now()}`,
});

const order = response.data;
```

### Considerations

* In this example, you perform an off-ramp for yourself, not for a third-party recipient. Therefore, both the originator and beneficiary use `"participantRelationshipType": "FirstParty"`, and no additional PII data is required.
* In this example, you chose to use a whitelisted account as the destination fiat account type. This allows you to register and manage external bank accounts (and also crypto addresses) directly within Fireblocks, ensuring secure, verified destinations that can be safely reused for future orders and transactions.
* Since the source of this order is a Vault Account, once the provider receives the order request, a transfer request will be automatically created from your vault to the provider. You will then need to approve and sign this transfer in accordance with the workspace's policy rules before the order can be executed.

## Use Case 4: Bridging (Crypto-to-Crypto) - DVP settlement with quote execution

**Use Case:** Execute a cross-chain bridging operation through the provider's connected accounts. In this flow, the user swaps USDT on Ethereum for USDT on Tron using their Scrypt provider account.

**Settlement Type:** DVP\
**Execution Type:** Quote

### Step 1: Create a Quote

```typescript theme={"system"}
// Create a quote for crypto-to-crypto bridging
const quoteResponse = await fireblocks.trading.createQuote({
  createQuote: {
    scope: [
      {
        providerId: 'SCRYPT',
        accountId: 'scrypt_acc_5e9a2d1c4b7f3e8a',
      },
    ],
    side: 'BUY',
    baseAssetId: 'USDT_ERC20',
    quoteAssetId: 'TRX_USDT_S2UZ',
    baseAmount: '15000',
  },
  idempotencyKey: `quote-${Date.now()}`,
});

const quote = quoteResponse.data.quotes[0];
```

In the quote response, you will receive all related metadata, including the quote ID (`id`) and expiration time (`expiresAt`). The quote ID is then used in the next step to create an order and execute the trade.

### Step 2: Execute Order with Quote

```typescript theme={"system"}
// Execute bridging order using the quote from Step 1
const response = await fireblocks.trading.createOrder({
  createOrderRequest: {
    via: {
      type: 'PROVIDER_ACCOUNT',
      providerId: 'SCRYPT',
      accountId: 'scrypt_acc_5e9a2d1c4b7f3e8a',
    },
    executionRequestDetails: {
      type: 'QUOTE',
      reQuote: {
        type: 'MARKET',
      },
      quoteId: 'quote_khge4d1a9c5bmvby',
    },
    settlement: {
      type: 'DVP',
      sourceAccount: {
        type: 'VAULT_ACCOUNT',
        accountId: 'vault_acc_5e9a2d1c4b7f3e8a',
      },
      destinationAccount: {
        type: 'VAULT_ACCOUNT',
        accountId: 'vault_acc_5e9a2d1c4b7f3e8a',
      },
    },
    participantsIdentification: {
      originator: {
        entityType: 'INDIVIDUAL',
        participantRelationshipType: 'FirstParty',
      },
      beneficiary: {
        entityType: 'INDIVIDUAL',
        participantRelationshipType: 'FirstParty',
      },
    },
  },
  idempotencyKey: `order-${Date.now()}`,
});

const order = response.data;
```

### Considerations

* In this example, you perform bridging via a connected account for yourself, not for a third-party recipient. Therefore, both the originator and beneficiary use `"participantRelationshipType": "FirstParty"`, and no additional PII data is required.
* The `quoteId` used in the order request is the same ID returned in the response from the `POST /trading/quotes`call.
* Since the source of this order is a Vault Account, once the provider receives the order request, a transfer will automatically be initiated from your Vault Account to the provider's connected account on Scrypt. This transfer is governed by the workspace's Transfer Policy, just like any other transfer in Fireblocks.
* **ReQuote Option:** Instead of `"type": "MARKET"`, you can use `"type": "RETRY"` with `count` (1-10 retry attempts) and optional `slippageBps` (slippage tolerance in basis points) to automatically retry quote generation if the original quote expires, giving you more control over price execution.

## Order Tracking & Monitoring

After creating an order, monitor its execution status to track completion.

### Polling for order status

```typescript theme={"system"}
// Get order status and details
const response = await fireblocks.trading.getOrder({
  orderId: 'order_id_here',
});

const order = response.data;
// Check: order.status, order.executionSteps, order.createdAt, etc.
```

### Order Status Values

| Status                | Description                                      |
| --------------------- | ------------------------------------------------ |
| `CREATED`             | Order has been created and is being processed    |
| `AWAITING_PAYMENT`    | Waiting for payment to be received               |
| `PENDING_USER_ACTION` | Requires user action (e.g., approval in console) |
| `PROCESSING`          | Order is being executed                          |
| `COMPLETED`           | Order has been successfully completed            |
| `FAILED`              | Order execution failed                           |
| `CANCELED`            | Order was canceled                               |

<Callout icon="📖" theme="default">
  ### **Note:** FAILED, COMPLETED and CANCELED are terminal states.
</Callout>

### Webhooks

Subscribe to order-update events through the Fireblocks Webhooks API. See the [Fireblocks Webhooks API documentation](/) for more details.

## Additional Resources

* [Trading API Overview](/docs/trading-api-overview)
* [Bridging via Direct Access Providers (DeFi)](/docs/swap-via-direct-access-providers-defi) - For crypto-to-crypto bridging using direct access providers like Uniswap
* Fireblocks SDKs: [Python](https://pypi.org/project/fireblocks/) | [TypeScript](https://www.npmjs.com/package/@fireblocks/ts-sdk) | [Java](https://central.sonatype.com/artifact/com.fireblocks.sdk/fireblocks-sdk/overview)
* [Fireblocks Developer Portal](/)

## Support

For questions or issues with the Trading API:

* Contact your Fireblocks [Customer Success Manager](https://support.fireblocks.io/hc/en-us/requests/new?ticket_form_id=6947882197532)
* Email: [CSM@fireblocks.com](mailto:CSM@fireblocks.com)
* Check the [Fireblocks Developer Portal](/) for updates
