# Search Payout Channels

The ways the bank ramp can pay out a cryptocurrency as fiat to a country and currency: fees, limits, processing time, the details the beneficiary needs and the user's saved accounts.

## Overview

A channel is a country, a fiat currency and a payment method type (for example `BankSepa`), with its own fees, limits and form. Search right before showing channels to the user: The bank ramp changes channel ids and limits, so don't store them.

- `cryptoCurrency` must be offered for payout by your tenant in that environment ([Currencies & Networks](https://docs.aureahub.com/docs/bank-currencies.md)): otherwise `400` `NOAH_PAIR_UNAVAILABLE`, naming what it offers. In the sandbox an asset code such as `EURC` is read as `EURC_TEST`.
- Send `fiatAmount` to get each channel's `totalFee` for that amount.
- Send `paymentMethodId`, from [Saved Beneficiaries](https://docs.aureahub.com/docs/payout-beneficiaries.md), and each channel's form asks only for what the bank ramp doesn't have yet. The search is a `POST` for this reason: the id contains the account number, and a URL is written to server logs.
- Channels come one page at a time: send `nextPageToken` back as `pageToken` until it is `null`. Unknown body fields are ignored.
- **Aurea does not pay out to cards.** A channel the bank ramp offers whose payment method is a card is left out of `channels`, and `cardChannelsHidden` counts how many — so a short list is never a mystery.
- **Payouts must be switched on** for your tenant in that environment ([Tenant Settings](https://docs.aureahub.com/docs/bank-settings.md)): otherwise `403` `NOAH_FUNCTION_OFF`. A tenant that does not use the bank ramp, or a token without a tenant, gets `403`.
- The user needs a bank ramp profile in that environment ([Onboarding Session](https://docs.aureahub.com/docs/payin-session.md)): otherwise `404` with `details.code` `NOAH_CUSTOMER_NOT_FOUND`. KYC approval is not needed to read; the bank ramp's own refusals pass through with their status and `details`, for example `403` `NOAH_FORBIDDEN` with `denyReasons`. **A user who has not started their onboarding is a different case**: Aurea lets the read through and the bank ramp answers `404`, which arrives as `404` `NOAH_RESOURCE_NOT_FOUND`. The reason is worth knowing — **The bank ramp does not create the customer when the session is created, but when the user actually begins the hosted flow**, so until then the bank ramp has nobody by that id (measured against the bank ramp's sandbox on 21 September 2026: [Sync KYC Status](https://docs.aureahub.com/docs/payin-sync-status.md) answers `synced: false` and says the customer is not in the bank ramp yet). These reads become useful once the user has started onboarding.
- `isTestnet: true` reads the bank ramp's sandbox with the user's sandbox profile; `false` or omitted reads production. Nothing is stored and nothing moves.

## Endpoint

### `POST /v1/ramp/bank/payout/channels/search`

Authentication: bearer token required.

Returns one page of the channels a payout of cryptoCurrency can go through, for the user's bank ramp customer.

**Request body**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `cryptoCurrency` | string | yes | The currency the user pays out, e.g. EURC_TEST |
| `country` | string | no | ISO 3166-1 alpha-2 country of the beneficiary, e.g. DE |
| `fiatCurrency` | string | no | ISO 4217 currency the beneficiary receives, e.g. EUR |
| `fiatAmount` | string | no | Decimal text, e.g. 100.50; with it each channel has a totalFee |
| `paymentMethodId` | string | no | A saved payment method (1 to 150 characters): forms then ask only for what the bank ramp doesn't have |
| `pageSize` | integer | no | 1 to 100; the bank ramp's default is 20 |
| `pageToken` | string | no | nextPageToken of the previous page |
| `isTestnet` | boolean | no | `true` for the bank ramp's sandbox; `false` or omitted for production |

**Responses**

`200` OK

```json
{
  "environment": "sandbox",
  "cryptoCurrency": "EURC_TEST",
  "channels": [
    {
      "channelId": "ebb9736b-08b3-599d-886b-10ee8aea82b5",
      "country": "DE",
      "fiatCurrency": "EUR",
      "paymentMethodCategory": "Bank",
      "paymentMethodType": "BankSepa",
      "rate": "0.98",
      "fee": { "fixed": "0.5", "percentage": "0.25", "fiatCurrency": "EUR" },
      "totalFee": "0.75",
      "limits": { "min": "1", "max": "10000" },
      "cryptoLimits": { "min": "1.53", "max": "10230" },
      "processingSeconds": 86400,
      "processingTier": null,
      "issuer": null,
      "formSchema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "object",
        "properties": {
          "BankDetails": {
            "type": "object",
            "title": "Bank Details",
            "properties": {
              "AccountNumber": { "type": "string", "title": "IBAN", "minLength": 22, "maxLength": 22 }
            },
            "required": ["AccountNumber"]
          }
        },
        "required": ["BankDetails"]
      },
      "formContentHash": "3f2a9c",
      "savedPaymentMethods": []
    }
  ],
  "nextPageToken": null
}
```

`400` Currency not offered

```json
{
  "statusCode": 400,
  "error": "BadRequestError",
  "message": "USDT_TEST payouts are not available with the bank ramp in sandbox. Available: EURC_TEST, PYUSD_TEST, USDC_TEST, USDG_TEST.",
  "details": {
    "code": "NOAH_PAIR_UNAVAILABLE",
    "environment": "sandbox",
    "cryptoCurrency": "USDT_TEST",
    "available": [{ "cryptoCurrency": "EURC_TEST" }, { "cryptoCurrency": "PYUSD_TEST" }, { "cryptoCurrency": "USDC_TEST" }, { "cryptoCurrency": "USDG_TEST" }]
  }
}
```

## Channels

- `rate` is fiat per unit of the cryptocurrency, without fees: it is not a quote. `fee.percentage` is a percent value (`"0.25"` is 0.25%); `fee` is `null` when the bank ramp sends none.
- `limits` are in `fiatCurrency`; `cryptoLimits` are the same limits in the cryptocurrency, fees included, or `null`. `max` is `null` when the bank ramp sets no maximum. Every amount is exact decimal text.
- `formSchema` is the JSON Schema of the beneficiary details the channel needs, as the bank ramp sent it (render it with a JSON Schema form library); `null` when nothing is needed. [Channel Form](https://docs.aureahub.com/docs/payout-channel-form.md) returns the same schema for one channel.
- `savedPaymentMethods` are the user's recent payment methods on this channel, in the shape described in [Saved Beneficiaries](https://docs.aureahub.com/docs/payout-beneficiaries.md).
- **Card channels are not listed**: The bank ramp pays a card only through its own hosted page. A channel the bank ramp sends without an id, type, country, currency, rate, minimum or processing time is left out too.

## Implementation

```javascript
async function searchChannels(token, { country, fiatCurrency, fiatAmount }) {
  const channels = [];
  let pageToken;
  do {
    const res = await fetch('https://api.aureahub.com/v1/ramp/bank/payout/channels/search', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
      body: JSON.stringify({ cryptoCurrency: 'EURC_TEST', country, fiatCurrency, fiatAmount, pageToken, isTestnet: true })
    });
    const page = await res.json();
    if (!res.ok) throw new Error(page.message);
    channels.push(...page.channels);
    pageToken = page.nextPageToken ?? undefined;
  } while (pageToken);
  // Offer only the channels whose fiat limits hold the amount
  return channels.filter((c) => Number(fiatAmount) >= Number(c.limits.min)
    && (c.limits.max === null || Number(fiatAmount) <= Number(c.limits.max)));
}
```

---

Web version: https://docs.aureahub.com/#payout-channels
