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

# Noah virtual accounts and payouts

> Use portal.ramps.noah in the React Native SDK for Noah KYC, payins, payouts, and quotes through the Portal Client API.

The React Native SDK exposes [Noah](/integrations/On-Off-Ramp/noah) virtual accounts and global payouts through `portal.ramps.noah`. Each method issues HTTP requests through `portal.api` to Portal’s Noah integration on the [Client API](/apis/quickstart) using your client API key. You do not call Noah’s servers directly from the app.

<Note>
  For dashboard setup, signing keys, and supported CAIP-2 networks, see [Noah integration overview](/integrations/On-Off-Ramp/noah). For HTTP shapes and webhooks, see the [Noah workflow guides](/integrations/On-Off-Ramp/noah#workflow-guides) and [Noah Business API / EMM documentation](https://docs.noah.com/).
</Note>

## Prerequisites

* An [initialized `Portal` client](./getting-started) with a wallet and API access.
* Noah enabled for your Portal environment and [configured in the dashboard](/integrations/On-Off-Ramp/noah).
* For payins and payouts, the end user must complete [Noah KYC](/integrations/On-Off-Ramp/noah-kyc) with approved status before those flows succeed.

## Architecture

| Layer             | Role                                                                                                             |
| ----------------- | ---------------------------------------------------------------------------------------------------------------- |
| Your app          | Calls `portal.ramps.noah.*`                                                                                      |
| React Native SDK  | The Noah module at `portal.ramps.noah` issues authenticated HTTP requests through `portal.api` to the Portal API |
| Portal API        | `POST/GET …/api/v3/clients/me/integrations/noah/...` with the Portal client API key                              |
| Noah (via Portal) | Hosted KYC, banking rails, settlement                                                                            |

Prefer `portal.ramps.noah` over lower-level APIs. The SDK types for requests and responses are exported from `@portal-hq/core` (see the [React Native SDK reference](/sdks/react-native/reference/core) section **portal.ramps.noah (Noah)**).

## Types and responses

Successful Client API responses use an envelope `{ data: T, metadata?: Record<string, unknown> }`. Methods on `portal.ramps.noah` return `Promise` of that envelope (for example `NoahInitiateKycResponse` is `{ data: { hostedUrl: string } }`).

Throwing or rejected promises usually indicate network errors, TLS issues, or API error payloads returned by the SDK—handle them with `try/catch` like other async Portal calls.

## initiateKyc

Starts hosted Noah onboarding. Open `data.hostedUrl` in the system browser (for example [`Linking.openURL`](https://reactnative.dev/docs/linking#openurl) on React Native). Validate **HTTPS** and the **hostname** against the checkout domains Noah documents for your environment (extend the example allowlist accordingly).

```typescript theme={null}
import { Linking } from 'react-native'
import { Portal } from '@portal-hq/core'
// …`backup`, `gatewayConfig`, and other constructor options as in [Getting started](./getting-started)

const portal = new Portal({
  apiKey: 'YOUR_API_KEY',
  backup: { /* … */ },
  gatewayConfig: { 'eip155:1': 'https://...' },
})

const { data } = await portal.ramps.noah.initiateKyc({
  returnUrl: 'https://yourapp.example/noah/return',
  fiatOptions: [{ fiatCurrencyCode: 'USD' }],
  customerType: 'Individual',
})

const url = new URL(data.hostedUrl)
const allowedHosts = new Set([
  'checkout.noah.com',
  'checkout.sandbox.noah.com',
  'staging-checkout.noah.com',
])
if (url.protocol !== 'https:' || !allowedHosts.has(url.hostname)) {
  throw new Error('Invalid KYC URL host or scheme')
}
await Linking.openURL(url.toString())
```

**Signature**

```typescript theme={null}
public async initiateKyc(data: NoahInitiateKycRequest): Promise<NoahInitiateKycResponse>
```

| Parameter           | Type                             | Required | Description                                             |
| ------------------- | -------------------------------- | -------- | ------------------------------------------------------- |
| `data.returnUrl`    | `string`                         | Yes      | HTTPS URL where Noah returns the user after onboarding. |
| `data.fiatOptions`  | `{ fiatCurrencyCode: string }[]` | No       | Fiat currencies to present in onboarding.               |
| `data.customerType` | `'Individual' \| 'Business'`     | No       | Onboarding flow variant.                                |
| `data.metadata`     | `Record<string, unknown>`        | No       | Opaque metadata forwarded per API rules.                |
| `data.form`         | `Record<string, unknown>`        | No       | Optional prefill payload for hosted forms.              |

<Note>
  The `returnUrl` must be an HTTPS URL. Custom app schemes (e.g. `myapp://callback`) are not supported. For mobile applications, the recommended pattern is to use an HTTPS bridge page that redirects to a deep link after KYC completion.
</Note>

**Returns** — `NoahInitiateKycResponse`: `{ data: { hostedUrl: string } }`.

<Note>
  This call only starts onboarding; KYC outcome and status changes arrive asynchronously via Noah **`Customer`** webhooks. See [Noah webhooks](/integrations/On-Off-Ramp/noah-webhooks).
</Note>

See also: [Noah KYC guide](/integrations/On-Off-Ramp/noah-kyc), [Noah hosted flows](https://docs.noah.com/).

## initiatePayin

Creates a fiat-to-stablecoin payin and returns bank instructions and a `payinId`. Use a [supported CAIP-2 network](/integrations/On-Off-Ramp/noah#supported-networks) and the user’s wallet address as `destinationAddress`.

```typescript theme={null}
const { data } = await portal.ramps.noah.initiatePayin({
  fiatCurrency: 'USD',
  cryptoCurrency: 'USDC_TEST',
  network: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
  destinationAddress: 'SoLAddr1111111111111111111111111111111111111',
})

console.log(data.payinId, data.bankDetails)
```

**Signature**

```typescript theme={null}
public async initiatePayin(data: NoahInitiatePayinRequest): Promise<NoahInitiatePayinResponse>
```

| Parameter                 | Type     | Required | Description                                                              |
| ------------------------- | -------- | -------- | ------------------------------------------------------------------------ |
| `data.fiatCurrency`       | `string` | Yes      | Fiat currency code (for example `USD`).                                  |
| `data.cryptoCurrency`     | `string` | Yes      | Noah crypto asset code (for example stablecoin test symbols in sandbox). |
| `data.network`            | `string` | Yes      | CAIP-2 chain identifier.                                                 |
| `data.destinationAddress` | `string` | Yes      | Address that receives crypto after settlement.                           |

**Returns** — `NoahInitiatePayinResponse`: `{ data: { payinId: string; bankDetails: BankDetails } }`.

<Note>
  Payin lifecycle updates are asynchronous; track them with Noah **`FiatDeposit`** and **`Transaction`** webhooks, not by polling this SDK response. See [Noah webhooks](/integrations/On-Off-Ramp/noah-webhooks).
</Note>

See also: [Payins](/integrations/On-Off-Ramp/noah-payins), [FiatDeposit webhooks](https://docs.noah.com/api-concepts/webhooks/fiat-deposits/).

## simulatePayin

Sandbox-oriented call to estimate fees or eligibility for a payin without creating a live payin. Typical body includes a Noah `paymentMethodId` and fiat amount.

```typescript theme={null}
await portal.ramps.noah.simulatePayin({
  paymentMethodId: 'pm-1',
  fiatAmount: '10',
  fiatCurrency: 'USD',
})
```

**Signature**

```typescript theme={null}
public async simulatePayin(data: NoahSimulatePayinRequest): Promise<NoahSimulatePayinResponse>
```

| Parameter              | Type     | Required | Description                          |
| ---------------------- | -------- | -------- | ------------------------------------ |
| `data.paymentMethodId` | `string` | Yes      | Payment method identifier from Noah. |
| `data.fiatAmount`      | `string` | Yes      | Fiat amount as a string (decimal).   |
| `data.fiatCurrency`    | `string` | Yes      | Fiat currency code.                  |

**Returns** — `NoahSimulatePayinResponse`: `{ data: { fiatDepositId: string } }`.

## getPayoutCountries

Lists countries available for fiat payouts.

```typescript theme={null}
const { data } = await portal.ramps.noah.getPayoutCountries()
console.log(data.countries)
```

**Signature**

```typescript theme={null}
public async getPayoutCountries(): Promise<NoahGetPayoutCountriesResponse>
```

**Returns** — `NoahGetPayoutCountriesResponse`: `{ data: { countries: Record<string, string[]> } }`.

## getPayoutChannels

Returns payout rails for a country and currency pair. Optional `fiatAmount` can refine channel availability.

```typescript theme={null}
const { data } = await portal.ramps.noah.getPayoutChannels({
  country: 'US',
  cryptoCurrency: 'USDC_TEST',
  fiatCurrency: 'USD',
  fiatAmount: '10',
})
```

**Signature**

```typescript theme={null}
public async getPayoutChannels(data: NoahGetPayoutChannelsRequest): Promise<NoahGetPayoutChannelsResponse>
```

| Parameter             | Type     | Required | Description                                          |
| --------------------- | -------- | -------- | ---------------------------------------------------- |
| `data.country`        | `string` | Yes      | ISO country code (for example `US`).                 |
| `data.cryptoCurrency` | `string` | Yes      | Crypto asset code for the payout leg.                |
| `data.fiatCurrency`   | `string` | Yes      | Fiat currency for the payout.                        |
| `data.fiatAmount`     | `string` | No       | Optional amount string used for filtering or quotes. |

**Returns** — `NoahGetPayoutChannelsResponse`: `{ data: { items: Channel[]; pageToken?: string } }`.

See also: [Payouts](/integrations/On-Off-Ramp/noah-payouts).

## getPayoutChannelForm

Loads the dynamic form schema for a channel so you can collect recipient fields before requesting a quote.

```typescript theme={null}
const { data } = await portal.ramps.noah.getPayoutChannelForm('ch-1')
// Render form fields from `data` per Noah’s schema
```

**Signature**

```typescript theme={null}
public async getPayoutChannelForm(channelId: string): Promise<NoahGetPayoutChannelFormResponse>
```

| Parameter   | Type     | Required | Description                                  |
| ----------- | -------- | -------- | -------------------------------------------- |
| `channelId` | `string` | Yes      | Channel identifier from `getPayoutChannels`. |

**Returns** — `NoahGetPayoutChannelFormResponse`: `{ data: { formSchema?: Record<string, unknown>; formMetadata?: { contentHash: string } } }`.

## getPayoutQuote

Requests fees and crypto amount estimates for a payout. Include `form` when the channel requires recipient data.

```typescript theme={null}
const { data } = await portal.ramps.noah.getPayoutQuote({
  channelId: 'ch-1',
  cryptoCurrency: 'USDC_TEST',
  fiatAmount: '10',
  form: { /* channel-specific fields */ },
})

console.log(data.payoutId, data.formSessionId, data.cryptoAmountEstimate, data.totalFee)
```

**Signature**

```typescript theme={null}
public async getPayoutQuote(data: NoahGetPayoutQuoteRequest): Promise<NoahGetPayoutQuoteResponse>
```

| Parameter              | Type                      | Required | Description                             |
| ---------------------- | ------------------------- | -------- | --------------------------------------- |
| `data.channelId`       | `string`                  | Yes      | Payout channel id.                      |
| `data.cryptoCurrency`  | `string`                  | Yes      | Crypto asset for the quote.             |
| `data.fiatAmount`      | `string`                  | Yes      | Fiat amount as a string.                |
| `data.form`            | `Record<string, unknown>` | No       | Recipient fields from the channel form. |
| `data.fiatCurrency`    | `string`                  | No       | Fiat currency override when needed.     |
| `data.paymentMethodId` | `string`                  | No       | Payment method hint when applicable.    |

**Returns** — `NoahGetPayoutQuoteResponse`: includes `payoutId`, `formSessionId`, `cryptoAmountEstimate`, `totalFee`, and optional `nextStep`.

## initiatePayout

Executes a payout after quoting. For crypto-sourced payouts you may need to pass deposit `conditions` from the quote response via a `trigger` payload; align with [Payouts](/integrations/On-Off-Ramp/noah-payouts) and Noah’s on-chain deposit triggers.

```typescript theme={null}
const payoutId = 'p1'
const expiry = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString().replace(/\.\d{3}Z$/, 'Z')
// Use a stable nonce per payout attempt (max 36 chars; reuse on retries)
const nonce =
  globalThis.crypto?.randomUUID != null
    ? globalThis.crypto.randomUUID()
    : `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`.slice(0, 36)

const { data } = await portal.ramps.noah.initiatePayout({
  payoutId,
  sourceAddress: 'SoLAddr1111111111111111111111111111111111111',
  expiry,
  nonce,
  network: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
})

console.log(data.destinationAddress, data.conditions)
```

**Signature**

```typescript theme={null}
public async initiatePayout(data: NoahInitiatePayoutRequest): Promise<NoahInitiatePayoutResponse>
```

| Parameter            | Type                                         | Required | Description                                                                                                                                   |
| -------------------- | -------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `data.payoutId`      | `string`                                     | Yes      | Identifier from `getPayoutQuote`.                                                                                                             |
| `data.sourceAddress` | `string`                                     | Yes      | Address funding the crypto leg when applicable.                                                                                               |
| `data.expiry`        | `string`                                     | Yes      | ISO-8601 expiry for the deposit authorization.                                                                                                |
| `data.nonce`         | `string`                                     | Yes      | Stable nonce for this payout attempt; **reuse on retry** so repeated calls stay idempotent. Must be ≤ 36 characters per Noah API constraints. |
| `data.network`       | `string`                                     | Yes      | CAIP-2 network for the deposit leg.                                                                                                           |
| `data.trigger`       | `NoahSingleOnchainDepositSourceTriggerInput` | No       | Structured trigger when Noah requires explicit on-chain deposit conditions.                                                                   |

**Returns** — `NoahInitiatePayoutResponse`: `{ data: { destinationAddress: string \| null; conditions: DepositSourceTriggerCondition[] } }`.

<Note>
  After this call returns `destinationAddress` and `conditions`, submit the onchain transfer to satisfy them. You can do this with any wallet — including Portal's own [send method](/sdks/web/guide/send-tokens) (`portal.sendAsset(...)`) on the same `Portal` instance, which builds, signs, and broadcasts in one call.
</Note>

<Note>
  This call initiates the payout flow; completion and failures are reported asynchronously via Noah **`Transaction`** webhooks. See [Noah webhooks](/integrations/On-Off-Ramp/noah-webhooks).
</Note>

See also: [Transaction events](https://docs.noah.com/api-concepts/webhooks/transactions/), [automated payout recipes](https://docs.noah.com/recipes/payout/automated-payouts).

## getPaymentMethods

Returns payment methods available to the customer (for example cards or bank rails), including pagination tokens when present.

```typescript theme={null}
const { data } = await portal.ramps.noah.getPaymentMethods()
console.log(data.paymentMethods, data.pageToken)
```

**Signature**

```typescript theme={null}
public async getPaymentMethods(): Promise<NoahGetPaymentMethodsResponse>
```

**Returns** — `NoahGetPaymentMethodsResponse`: `{ data: { paymentMethods: PaymentMethod[]; pageToken?: string } }`.

## Error handling

Wrap calls in `try/catch`. Log or surface errors without printing full API responses in production if they might contain sensitive identifiers. Retry only for idempotent reads unless your product team confirms otherwise.

## Related documentation

* [React Native SDK reference — `@portal-hq/core`](/sdks/react-native/reference/core) (section **portal.ramps.noah (Noah)**)
* [Noah integration overview](/integrations/On-Off-Ramp/noah)
* [KYC](/integrations/On-Off-Ramp/noah-kyc), [Payins](/integrations/On-Off-Ramp/noah-payins), [Payouts](/integrations/On-Off-Ramp/noah-payouts), [Webhooks](/integrations/On-Off-Ramp/noah-webhooks)
* [Noah docs — API concepts](https://docs.noah.com/api-concepts/transactions/)
* [Noah docs — authentication & signing](https://docs.noah.com/api-concepts/authentication/signing/)
