Skip to main content
The React Native SDK exposes 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 using your client API key. You do not call Noah’s servers directly from the app.
For dashboard setup, signing keys, and supported CAIP-2 networks, see Noah integration overview. For HTTP shapes and webhooks, see the Noah workflow guides and Noah Business API / EMM documentation.

Prerequisites

Architecture

LayerRole
Your appCalls portal.ramps.noah.*
React Native SDKThe Noah module at portal.ramps.noah issues authenticated HTTP requests through portal.api to the Portal API
Portal APIPOST/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 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 on React Native). Validate HTTPS and the hostname against the checkout domains Noah documents for your environment (extend the example allowlist accordingly).
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
public async initiateKyc(data: NoahInitiateKycRequest): Promise<NoahInitiateKycResponse>
ParameterTypeRequiredDescription
data.returnUrlstringYesHTTPS URL where Noah returns the user after onboarding.
data.fiatOptions{ fiatCurrencyCode: string }[]NoFiat currencies to present in onboarding.
data.customerType'Individual' | 'Business'NoOnboarding flow variant.
data.metadataRecord<string, unknown>NoOpaque metadata forwarded per API rules.
data.formRecord<string, unknown>NoOptional prefill payload for hosted forms.
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.
ReturnsNoahInitiateKycResponse: { data: { hostedUrl: string } }.
This call only starts onboarding; KYC outcome and status changes arrive asynchronously via Noah Customer webhooks. See Noah webhooks.
See also: Noah KYC guide, Noah hosted flows.

initiatePayin

Creates a fiat-to-stablecoin payin and returns bank instructions and a payinId. Use a supported CAIP-2 network and the user’s wallet address as destinationAddress.
const { data } = await portal.ramps.noah.initiatePayin({
  fiatCurrency: 'USD',
  cryptoCurrency: 'USDC_TEST',
  network: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
  destinationAddress: 'SoLAddr1111111111111111111111111111111111111',
})

console.log(data.payinId, data.bankDetails)
Signature
public async initiatePayin(data: NoahInitiatePayinRequest): Promise<NoahInitiatePayinResponse>
ParameterTypeRequiredDescription
data.fiatCurrencystringYesFiat currency code (for example USD).
data.cryptoCurrencystringYesNoah crypto asset code (for example stablecoin test symbols in sandbox).
data.networkstringYesCAIP-2 chain identifier.
data.destinationAddressstringYesAddress that receives crypto after settlement.
data.businessFeesBusinessFeesInputNoCustom business fee overrides keyed by channel or rule identifier.
ReturnsNoahInitiatePayinResponse: { data: { payinId: string; cryptoCurrency: string; fee: NoahFeeDetails; bankDetails: BankDetails } }.
Payin lifecycle updates are asynchronous; track them with Noah FiatDeposit and Transaction webhooks, not by polling this SDK response. See Noah webhooks.
See also: Payins, FiatDeposit webhooks.

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.
await portal.ramps.noah.simulatePayin({
  paymentMethodId: 'pm-1',
  fiatAmount: '10',
  fiatCurrency: 'USD',
})
Signature
public async simulatePayin(data: NoahSimulatePayinRequest): Promise<NoahSimulatePayinResponse>
ParameterTypeRequiredDescription
data.paymentMethodIdstringYesPayment method identifier from Noah.
data.fiatAmountstringYesFiat amount as a string (decimal).
data.fiatCurrencystringYesFiat currency code.
ReturnsNoahSimulatePayinResponse: { data: { fiatDepositId: string; reference?: string } }.

getPayoutCountries

Lists countries available for fiat payouts.
const { data } = await portal.ramps.noah.getPayoutCountries()
console.log(data.countries)
Signature
public async getPayoutCountries(): Promise<NoahGetPayoutCountriesResponse>
ReturnsNoahGetPayoutCountriesResponse: { data: { countries: Record<string, string[]> } }.

getPayoutChannels

Returns payout rails for a given crypto asset. country and fiatCurrency narrow results but are optional; only cryptoCurrency is required. Optional fiatAmount can refine channel availability.
const { data } = await portal.ramps.noah.getPayoutChannels({
  cryptoCurrency: 'USDC_TEST',
  country: 'US',
  fiatCurrency: 'USD',
  fiatAmount: '10',
  pageSize: 10,
  pageToken: 'NEXT_PAGE_TOKEN',
})
Signature
public async getPayoutChannels(data: NoahGetPayoutChannelsRequest): Promise<NoahGetPayoutChannelsResponse>
ParameterTypeRequiredDescription
data.cryptoCurrencystringYesCrypto asset code for the payout leg.
data.countrystringNoISO country code (for example US).
data.fiatCurrencystringNoFiat currency for the payout.
data.fiatAmountstringNoOptional amount string used for filtering or quotes.
data.paymentMethodIdstringNoFilter to channels compatible with a saved payment method.
data.pageSizenumberNoMaximum number of payout channels to return.
data.pageTokenstringNoPagination token returned from a previous response.
ReturnsNoahGetPayoutChannelsResponse: { data: { items: Channel[]; pageToken?: string } }. See also: Payouts.

getPayoutChannelForm

Loads the dynamic form schema for a channel so you can collect recipient fields before requesting a quote.
const { data } = await portal.ramps.noah.getPayoutChannelForm('ch-1')
// Render form fields from `data` per Noah’s schema
Signature
public async getPayoutChannelForm(channelId: string): Promise<NoahGetPayoutChannelFormResponse>
ParameterTypeRequiredDescription
channelIdstringYesChannel identifier from getPayoutChannels.
ReturnsNoahGetPayoutChannelFormResponse: { 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. Pass either fiatAmount or cryptoAmount — they are mutually exclusive.
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.cryptoAuthorizedAmount, data.totalFee)
Signature
public async getPayoutQuote(data: NoahGetPayoutQuoteRequest): Promise<NoahGetPayoutQuoteResponse>
ParameterTypeRequiredDescription
data.channelIdstringYesPayout channel id.
data.cryptoCurrencystringYesCrypto asset for the quote.
data.fiatAmountstringOne of fiatAmount or cryptoAmountFiat amount as a string. Mutually exclusive with cryptoAmount.
data.cryptoAmountstringOne of fiatAmount or cryptoAmountCrypto amount as a string. Mutually exclusive with fiatAmount.
data.formRecord<string, unknown>NoRecipient fields from the channel form.
data.fiatCurrencystringNoFiat currency override when needed.
data.paymentMethodIdstringNoPayment method hint when applicable.
data.quotedbooleanNoRequest a signed quote for locked-rate payouts. When true, the response includes a quote with a signedQuote and expiry.
data.businessFeeNoahBusinessFeeNoCustom business fee override for this quote.
ReturnsNoahGetPayoutQuoteResponse: includes payoutId, formSessionId, cryptoAmountEstimate, cryptoAuthorizedAmount, totalFee, and optional rate, breakdown, quote ({ signedQuote, expiry }), and 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 and Noah’s on-chain deposit triggers.
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
public async initiatePayout(data: NoahInitiatePayoutRequest): Promise<NoahInitiatePayoutResponse>
ParameterTypeRequiredDescription
data.payoutIdstringYesIdentifier from getPayoutQuote.
data.sourceAddressstringYesAddress funding the crypto leg when applicable.
data.expirystringYesISO-8601 expiry for the deposit authorization.
data.noncestringYesStable nonce for this payout attempt; reuse on retry so repeated calls stay idempotent. Must be ≤ 36 characters per Noah API constraints.
data.networkstringYesCAIP-2 network for the deposit leg.
data.fiatAmountstringNoFiat amount for the payout. Only valid when trigger.Type is 'SingleOnchainDepositSourceTriggerInput'.
data.businessFeeNoahBusinessFeeNoCustom business fee override for this payout.
data.triggerNoahOnchainDepositSourceTriggerInputNoOn-chain deposit trigger. Use NoahSingleOnchainDepositSourceTriggerInput, NoahPermanentOnchainDepositSourceTriggerInput, or NoahQuotedOnchainDepositSourceTriggerInput depending on the payout flow.
ReturnsNoahInitiatePayoutResponse: { data: { destinationAddress: string \| null; conditions: DepositSourceTriggerCondition[]; ruleId?: string } }.
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 (portal.sendAsset(...)) on the same Portal instance, which builds, signs, and broadcasts in one call.
This call initiates the payout flow; completion and failures are reported asynchronously via Noah Transaction webhooks. See Noah webhooks.
See also: Transaction events, automated payout recipes.

getPaymentMethods

Returns payment methods available to the customer (for example cards or bank rails), including pagination tokens when present.
const { data } = await portal.ramps.noah.getPaymentMethods({
  pageSize: 10,
  pageToken: 'NEXT_PAGE_TOKEN',
  capability: 'PayoutTo'
})
console.log(data.paymentMethods, data.pageToken)
Signature
public async getPaymentMethods(data?: NoahGetPaymentMethodsRequest): Promise<NoahGetPaymentMethodsResponse>
ParameterTypeRequiredDescription
data.pageSizenumberNoMaximum number of payment methods to return.
data.pageTokenstringNoPagination token returned from a previous response.
data.capability'PayoutFrom' | 'PayinTo' | 'PayoutTo'NoFilters payment methods by supported Noah capability.
ReturnsNoahGetPaymentMethodsResponse: { 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.