# Channels

> A channel is a payment route with its own currencies, limits and form data. Channel IDs must be read at runtime, never hardcoded.

## Overview

Channels represent a payment route with specific characteristics for processing transactions.

A Channel can be seen as a type of contract where the details are fixed, including fees and transaction limits.

Each Channel is defined by:

- Country
- Fiat Currency
- Payment Method Type

**Important note:** the `Country` code `XX` is used for Channels with multiple compatible countries, these Channels are available internationally.

## Using Channels

### Get Available Countries

To retrieve the list of supported countries and their available fiat currencies, use the [`GET /channels/sell/countries`](../../api-reference/countries) endpoint in the Business API.

```typescript
curl -L 'https://api.sandbox.noah.com/v1/channels/sell/countries' \
-H 'Accept: application/json' \
-H 'X-Api-Key: <X-Api-Key>'
```

### Get Available Channels

Query available channels for a specific country or currency:

To retrieve the list of available channels for a specific country or currency, use the [`GET /channels/sell`](../../api-reference/channels) endpoint in the Business API.

```typescript
curl -L 'https://api.sandbox.noah.com/v1/channels/sell
        ?Country=GB // Provide country (optional if currency is specified)
        &CryptoCurrency=USDC_TEST
        &FiatCurrency=EUR // Provide currency (optional if country is specified)
        &FiatAmount=1000' // Optional - includes price calculation \
-H 'Accept: application/json' \
-H 'X-Api-Key: <X-Api-Key>'
```

:::tip

For details on the USDC_TEST token, used above, see [Sandbox Testnet Currencies](../api-concepts/testnet-currencies.md).

:::

For each channel returned by the call above, the response body is as follows.

```typescript
{
  "Calculated": {
    "TotalFee": "2"
  },
  "Country": "DE",
  "FiatCurrency": "EUR",
  "FormSchema": {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
      "BankDetails": {
        "properties": {
          "AccountType": {
            "enum": [
              "Checking",
              "Savings"
            ],
            "title": "Account Type",
            "type": "string"
          },
          "AccountNumber": {
            "maxLength": 22,
            "minLength": 22,
            "pattern": "^DE[0-9]{2}[A-Z0-9]{18}$",
            "title": "IBAN",
            "type": "string"
          }
        },
        "required": [
          "AccountType",
          "AccountNumber"
        ],
        "title": "Bank Details",
        "type": "object"
      }
    },
    "required": [
      "BankDetails"
    ]
  },
  "ID": "ebb9736b-08b3-599d-886b-10ee8aea82b5",
  "Limits": {
    "MinLimit": "1"
  },
  "PaymentMethodCategory": "Bank",
  "PaymentMethodType": "BankSepa",
  "ProcessingSeconds": 60,
  "Rate": "0.86"
}
```

:::tip

Looking at the above payload, consider the following when you select a channel.

- Transaction limits (`Limits` object).
- Processing time (`ProcessingSeconds`).
- Payment method requirements, some channels may require a Dynamic Form to submit a transaction.

:::

### Get Dynamic Forms

You can retrieve the required form fields for a given channel through two means:

1. **Directly from the Supported Channels Endpoint**. When you query available channels using the [`GET /channels/sell`](../../api-reference/channels) endpoint, the response includes the form schema needed for the selected payment method, as shown above. This method simplifies the process by reducing the number of API calls.

2. **Using the Dynamic Form Endpoint**. After selecting a channel, you can retrieve the required form fields by calling the [`GET /channels/:ChannelID/form`](../../api-reference/dynamic-form) endpoint. This endpoint provides a JSON Form schema specifying the required fields for the selected payment method.

## Code Example

Basic channel retrieval and selection:

```typescript
// 1. Get available countries
const countries = await api.get('/v1/channels/sell/countries');

// 2. Get channels for selected country
const channels = await api.get('/v1/channels/sell', {
  params: {
    Country: 'GB',
    CryptoCurrency: 'BTC',
    FiatCurrency: 'GBP',
    FiatAmount: '1000',
    PageSize: 20,
  },
});

// 3. Get form schema for selected channel
const formSchema = await api.get(`/channels/${channelId}/form`);
```

:::tip

**Best Practice 1: Regular Updates**

- Query the available payment channels immediately before displaying them to end users.
- Avoid relying on stale or cached data for prolonged periods — channels and their limits (e.g., max/min transaction amounts) can change frequently.
- Always obtain channel IDs from the Channels API at runtime — they are not suitable for caching or hardcoding.

**Best Practice 2: Error Handling**

- Handle channel disablement gracefully, by attempting to retrieve an equivalent channel.
- Validate transaction amounts against channel limits, before allowing a customer to select a channel.
- Verify all required form fields are available, before allowing a customer to select a channel.

**Best Practice 3: Performance**

- Implement pagination or filtering when listing multiple channels to reduce payload size and improve response times.
- If pricing calculations are required, pass any needed parameters (like `FiatAmount`) in the API request.

:::

## Payin Channels

For payins (fiat → crypto), the channel is determined implicitly by the currency you specify when calling the [POST `workflows/bank-deposit-to-onchain-address`](../../api-reference/convert-fiat-to-crypto) endpoint. Unlike payouts where you query and select from available channels, payins use an orchestrated workflow where Noah assigns the appropriate Virtual Account and payment method based on the customer's eligibility and the requested currency.

| Fiat Currency | Virtual Account Type | Payment Method Type | How It Works                                                                                                                                                          |
| ------------- | -------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **EUR**       | IBAN                 | `BankSepa`          | Customer receives a dedicated IBAN for SEPA deposits                                                                                                                  |
| **USD**       | ACH Routing Number   | `BankAch`           | Customer receives a dedicated ACH routing/account number. Wire transfers (`BankFedwire`) and international wires (`BankSwift`) are also accepted to the same account. |

To set up a payin channel, call the workflow endpoint with the desired `FiatCurrency`, `CryptoCurrency`, `Network`, and `DestinationAddress`. Noah returns the assigned Virtual Account details (account number, bank code, payment method ID) which you display to your customer.

For step-by-step integration guides, see:

- [Bank Onramp via EUR Virtual Account](../recipes/payin/bank-onramp-eu.md)
- [Bank Onramp via USD Virtual Account](../recipes/payin/bank-onramp-us.md)

### Payin vs. Payout Channel Selection

| Aspect                | Payin                                                                                          | Payout                                                                                                                        |
| --------------------- | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| **Channel selection** | Implicit - determined by currency and customer eligibility                                     | Explicit - query available channels and select one                                                                            |
| **API pattern**       | Single call to workflow endpoint                                                               | Query channels → select → get form → prepare → execute                                                                        |
| **Payment method**    | Assigned by Noah (Virtual Account)                                                             | Customer supplies details via Dynamic Form                                                                                    |
| **Endpoint**          | [POST `workflows/bank-deposit-to-onchain-address`](../../api-reference/convert-fiat-to-crypto) | [GET `channels/sell`](../../api-reference/channels) + [POST `transactions/sell`](../../api-reference/create-sell-transaction) |

## Payment Method Types

The API uses `PaymentMethodType` values to identify specific payment rails. These appear in channel responses, webhook payloads, and payment method objects throughout the API.

| PaymentMethodType | Description                | Currencies | Typical Settlement |
| ----------------- | -------------------------- | ---------- | ------------------ |
| `BankSepa`        | SEPA Credit Transfer       | EUR        | 1-3 business days  |
| `BankAch`         | ACH transfer (US)          | USD        | 1-3 business days  |
| `BankFedwire`     | Fedwire (US domestic wire) | USD        | Same day           |
| `BankSwift`       | SWIFT / International Wire | USD, EUR   | 1-5 business days  |

Additional payment method types are available across regions, including local bank transfers, mobile money, digital wallets, and card-based methods. The set of available methods is large and changes as new rails are added. Always query the Channels API for the current list.

:::tip
The Channels API is the authoritative source for available payment methods. The table above covers the core banking rails for Virtual Account flows. For the full set of payout methods available in any given country, query the [`GET /channels/sell`](../../api-reference/channels) endpoint at runtime.
:::

Each payment method type belongs to a `PaymentMethodCategory`:

| Category       | Description                                                              | Form Data                                                   |
| -------------- | ------------------------------------------------------------------------ | ----------------------------------------------------------- |
| **Bank**       | Bank transfer methods (SEPA, ACH, Fedwire, SWIFT, and local equivalents) | Bank account details (IBAN, routing number, account number) |
| **Card**       | Card-based payment methods                                               | Card details (via hosted interface)                         |
| **Identifier** | Identifier-based methods (e.g. tax ID, phone number, email)              | Local identifier as required by the payment rail            |

The `FormSchema` returned by a channel tells you exactly which fields to collect for that specific payment method and provider. See [Form Schemas](./form-schemas.md) for details on rendering and submitting form data.

For virtual bank account eligibility by country and rail — covering payin and VA-backed payouts on
SEPA, ACH, Fedwire, FedNow, and SWIFT (generated from channel policy) — see
[Virtual account countries by rail](./supported-fiat-countries.md).

## Related Developer Journeys

- [Form Schemas](./form-schemas.md) — Understanding and using form schemas for automation
- [Dynamic User Interface](./dynamic-ui.md) — Building UIs with dynamic forms
- [Global Payout Journey](../recipes/payout/global-payouts-business.md)
- [Automated Payout](../recipes/payout/automated-payouts.md)
