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.
The Web SDK exposes Noah virtual accounts and global payouts through portal.ramps.noah. Each method sends a message to the embedded Portal iframe, which calls Portal’s Noah integration on the Client API using your client credentials. You do not call Noah’s servers directly from the browser.
Prerequisites
Architecture
| Layer | Role |
|---|
| Your app | Calls portal.ramps.noah.* |
| Portal Web SDK | postMessage bridge to the Portal iframe (do not call Mpc directly) |
| Portal iframe | Forwards to POST/GET …/api/v3/clients/me/integrations/noah/... with the Portal session |
| Noah (via Portal) | Hosted KYC, banking rails, settlement |
Prefer portal.ramps.noah over lower-level APIs. The SDK types for requests and responses live in @portal-hq/web (see the Web 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, iframe timeouts, or API error payloads surfaced by the SDK—handle them with try/catch like other async Portal calls.
initiateKyc
Starts hosted Noah onboarding. Open data.hostedUrl in a new browser context (for example window.open with noopener,noreferrer). Validate HTTPS and the hostname against the checkout domains Noah documents for your environment (extend the example allowlist accordingly).
import Portal from '@portal-hq/web';
const portal = new Portal({
rpcConfig: { 'eip155:1': 'https://...' },
apiKey: 'YOUR_API_KEY',
});
portal.onReady(async () => {
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');
}
window.open(url.toString(), '_blank', 'noopener,noreferrer');
});
Signature
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. |
Returns — NoahInitiateKycResponse: { 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>
| 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: Record<string, unknown> } }.
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>
| 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: Record<string, unknown> } (shape depends on environment and product).
getPayoutCountries
Lists countries available for fiat payouts.
const { data } = await portal.ramps.noah.getPayoutCountries();
console.log(data.countries);
Signature
public async getPayoutCountries(): Promise<NoahGetPayoutCountriesResponse>
Returns — NoahGetPayoutCountriesResponse: { data: { countries: unknown } } (format is provider-specific).
getPayoutChannels
Returns payout rails for a country and currency pair. Optional fiatAmount can refine channel availability.
const { data } = await portal.ramps.noah.getPayoutChannels({
country: 'US',
cryptoCurrency: 'USDC_TEST',
fiatCurrency: 'USD',
fiatAmount: '10',
});
Signature
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: unknown } (array or object, depending on Noah).
See also: Payouts.
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>
| Parameter | Type | Required | Description |
|---|
channelId | string | Yes | Channel identifier from getPayoutChannels. |
Returns — NoahGetPayoutChannelFormResponse: { data: unknown }.
getPayoutQuote
Requests fees and crypto amount estimates for a payout. Include form when the channel requires recipient data.
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
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 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 = crypto.randomUUID();
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>
| 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: unknown } }.
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();
console.log(data.paymentMethods, data.pageToken);
Signature
public async getPaymentMethods(): Promise<NoahGetPaymentMethodsResponse>
Returns — NoahGetPaymentMethodsResponse: { data: { paymentMethods: unknown; pageToken?: unknown } }.
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.