1. Documentation
Vortex
  • Documentation
    • Overview
    • Quick Start With The SDK
    • Authentication And API Keys
    • Ramp Lifecycle
    • Ephemeral Key Custody
    • Quotes And Pricing
    • Webhooks
    • Widget Integration
    • Fiat Corridors
    • Sandbox
    • Production Checklist
    • KYB Deep Link
    • Managed Profiles
    • Custom UI Integration
    • AI Agent Integration
  • API Endpoints
    • Vortex Widget
      • Create widget session
    • Quotes
      • Create a new quote
      • Get existing quote
      • Create a quote for the best network
    • Ramp
      • Get ramp status
      • Get ramp error logs
      • Get ramp history for wallet address
      • Register new ramp process
      • Start ramp process
      • Get authenticated user ramp history
      • Update ramp process
    • Reference Data
      • Supported Countries
      • Supported Cryptocurrencies
      • Supported Fiat Currencies
      • Supported Payment Methods
    • Public Key
      • Public Key
    • Webhooks
      • Register Webhook
      • Delete Webhook
    • Account Management
      • Create user or retry KYC
      • Get user's KYC status
      • Get selfie liveness URL
      • Get KYC document upload URLs
      • Get KYC document upload URLs
      • Get user information
      • Get user's remaining transaction limits
      • Submit KYC level 1 data
      • Validate Pix key
      • Create user or retry KYC
      • Get user's KYC status
      • Get selfie liveness URL
      • Get user information
      • Get user's remaining transaction limits
      • Submit KYC level 1 data
      • Validate PIX key
      • List fiat accounts
      • Create a fiat account
      • Delete a fiat account
      • Get user ramp limits
      • Get sanitized ramp eligibility
    • Authentication
      • List the user's API keys
      • Create a user-linked API key pair
      • Revoke an API key
      • Request an email OTP
      • Verify an email OTP
      • List API credentials
      • Create an API credential
      • Revoke an API credential
    • KYC and KYB
      • Get KYB attempt status
      • Create KYB document
      • Get KYB document
      • Submit API-driven KYB
      • Start hosted KYB
      • Create KYB UBO
      • Import an individual KYC token
      • Record an initial KYC attempt
      • Get customer status
      • Create a business customer
      • Create an individual customer
      • Find KYB submission details
      • Get a KYB redirect link
      • Get a KYC redirect link
      • Get KYC or KYB status
      • Mark a redirect finished
      • Mark a redirect opened
      • Retry KYC or KYB
      • Send a KYB submission
      • Send a KYC submission
      • Upload a KYB file
      • Submit KYB information
      • Upload a related-person KYB file
      • Upload a KYC file
      • Submit KYC information
      • Select active customer entity
      • Discover KYC or KYB requirements
      • Get aggregate onboarding status
    • Managed Profiles
      • List managed profiles
      • Create a managed profile
      • Delete a managed profile
      • Get a managed profile
      • List a managed profile's API credentials
      • Create a managed profile API credential
      • Revoke a managed profile API credential
    • Schemas
      • AccountMeta
      • AveniaDocumentType
      • ApiCredential
      • AveniaKYCDataUploadRequest
      • ApiCredentialErrorResponse
      • AveniaKYCDataUploadResponse
      • ApiCredentialManagedSelectorErrorResponse
      • BrlaAddress
      • ApiValidationErrorResponse
      • BrlaErrorResponse
      • BrAddress
      • BrlaGetSelfieLivenessUrlResponse
      • BrDocumentType
      • BrlaValidatePixKeyResponse
      • BrErrorResponse
      • CleanupPhase
      • BrGetSelfieLivenessUrlResponse
      • CountryCode
      • BrImportKycTokenErrorResponse
      • CreateBestQuoteRequest
      • BrImportKycTokenRequest
      • CreateQuoteRequest
      • BrImportKycTokenResponse
      • BrKYCDataUploadRequest
      • BrKYCDataUploadResponse
      • DestinationType
      • BrKybAttemptStatusResponse
      • BrKybDocumentRequest
      • ErrorResponse
      • BrKybDocumentResponse
      • FiatToken
      • BrKybDocumentUploadResponse
      • BrKybHostedResponse
      • GetRampErrorLogsResponse
      • BrKybLevel1Payload
      • GetRampHistoryResponse
      • BrManagedBadRequestResponse
      • BrUboControlRole
      • BrUboPayload
      • BrUboResponse
      • GetWidgetUrlLocked
      • BrValidatePixKeyResponse
      • GetWidgetUrlRefresh
      • KYCDataUploadFileFiles
      • KYCDocType
      • CreateApiCredentialRequest
      • KycLevel1Payload
      • CreateApiCredentialResponse
      • KycLevel1Response
      • ListUserApiKeysResponse
      • CreateManagedProfileRequest
      • Networks
      • CreateSubaccountRequest
      • OnChainToken
      • CreateSubaccountResponse
      • PaymentData
      • PaymentMethod
      • DocumentUploadEntry
      • PresignedTx
      • QuoteResponse
      • DomesticAddFiatAccountRequest
      • RampCurrency
      • DomesticCountry
      • RampDirection
      • DomesticCountryAndCustomerTypeRequest
      • RampErrorLog
      • DomesticCountryRequest
      • RampPhase
      • DomesticCreateCustomerRequest
      • RampProcess
      • DomesticCreateCustomerResponse
      • RegisterRampRequest
      • DomesticCreateFiatAccountResponse
      • SimpleStatus
      • DomesticCustomerType
      • StartKYC2Request
      • DomesticErrorResponse
      • StartKYC2Response
      • DomesticFiatAccount
      • StartRampRequest
      • DomesticFiatAccountType
      • TaxIdType
      • DomesticKybBusinessSummary
      • TriggerOfframpRequest
      • DomesticKybDetailsResponse
      • TriggerOfframpResponse
      • DomesticKybFileUploadRequest
      • UnsignedTx
      • DomesticKybRelatedPerson
      • DomesticKybRelatedPersonFileUploadRequest
      • UserApiKeyErrorResponse
      • DomesticKycFileUploadRequest
      • UserApiKeyPairResponse
      • DomesticKycStatusResponse
      • ValidatePixKeyResponse
      • DomesticManagedBadRequestResponse
      • DomesticRedirectLinkResponse
      • DomesticRedirectNotificationRequest
      • DomesticRelatedPersonFileUploadRequest
      • DomesticRetryRequest
      • DomesticRetryResponse
      • DomesticSendSubmissionRequest
      • DomesticStatus
      • DomesticStatusResponse
      • DomesticSubmissionResponse
      • DomesticSubmitKybInformationRequest
      • DomesticSubmitKycInformationRequest
      • DomesticSuccessResponse
      • DomesticValidationBadRequestResponse
      • ErrorManagedSelectorResponse
      • FlatErrorResponse
      • FlatManagedSelectorErrorResponse
      • GetKycStatusResponse
      • GetRampHistoryTransaction
      • GetUserLimitsRequest
      • GetUserLimitsResponse
      • GetUserRemainingLimitResponse
      • GetUserResponse
      • KybAttemptStatusResponse
      • KybLevel1Response
      • ListApiCredentialsResponse
      • ListManagedProfilesResponse
      • MalformedJsonErrorResponse
      • LivenessDocumentEntry
      • ManagedProfile
      • ManagedProfileErrorResponse
      • ManagedProfilePagination
      • ManagedProfileResponse
      • ManagedProfileManagerPolicy
      • ManagedSelectorErrorResponse
      • OnboardingApiErrorResponse
      • OnboardingDocumentRequirement
      • OnboardingRequirementStep
      • OnboardingRequirementsErrorResponse
      • OnboardingRequirementsResponse
      • OnboardingStatusErrorResponse
      • OnboardingStatusResponse
      • PayloadTooLargeErrorResponse
      • RampInfoResponse
      • RecordInitialKycAttemptRequest
      • SelectActiveCustomerEntityRequest
      • SelectActiveCustomerEntityResponse
      • SubmitInformationResponse
      • SubmitKybInformationRequest
      • SubmitKycInformationRequest
      • SuccessResponse
      • UpdateRampRequest
      • UserLimit
      • UserLimitPeriod
  1. Documentation

Quick Start With The SDK

This page walks through complete BRL and bank-transfer-corridor (USD, MXN, COP, ARS) ramps end-to-end using @vortexfi/sdk in Node.js or a modern browser.

Install

npm install @vortexfi/sdk
# or
bun add @vortexfi/sdk

Initialize In Node.js

import {
  VortexSdk,
  FiatToken,
  EvmToken,
  Networks,
  RampDirection
} from "@vortexfi/sdk";
import type { VortexSdkConfig } from "@vortexfi/sdk";

const config: VortexSdkConfig = {
  apiBaseUrl: "https://api.vortexfinance.co",
  publicKey: "pk_live_...",
  secretKey: "sk_live_...",
  storeEphemeralKeys: true
};

const sdk = new VortexSdk(config);

publicKey is sent as X-Public-Key (and retained in quote bodies for compatibility) for attribution, approved low-sensitivity reads, and discount eligibility. secretKey is sent as X-API-Key and must only be used server-side. Both values should come from the same API credential; a mixed pair returns 403 CREDENTIAL_MISMATCH. A valid secret may be used without a public value.

Initialize In A Browser

Browser integrations use the user's renewable Supabase session and never configure secretKey:

const sdk = new VortexSdk({
  apiBaseUrl: "https://api.vortexfinance.co",
  publicKey: "pk_live_...",
  accessTokenProvider: async () => getCurrentSession()?.accessToken
});

Your browser origin must be approved by Vortex before any request from it reaches the API; email support@vortexfinance.co to have it added, and see Authentication And API Keys. The browser build rejects secretKey at construction.

You can check the authenticated subject's sanitized corridor readiness without exposing exact limits or profile data:

const info = await sdk.getRampInfo();
console.log(info.corridors.BR?.kycStatus, info.corridors.BR?.canBuy);

Constructing VortexSdk does not open chain WebSockets. Required connections are initialized lazily when returned transactions need them. Reuse one instance per active integration flow.

BRL Onramp (Buy)

const quote = await sdk.createQuote({
  rampType: RampDirection.BUY,
  from: "pix",
  to: Networks.Polygon,
  inputAmount: "150",            // 150 BRL
  inputCurrency: FiatToken.BRL,
  outputCurrency: EvmToken.USDC
});

const { rampProcess } = await sdk.registerRamp(quote, {
  destinationAddress: "0x1234567890123456789012345678901234567890"
});

// Show the PIX QR to the user and wait for them to pay.
console.log(rampProcess.depositQrCode);

// After the user completes the PIX payment, start the ramp.
const started = await sdk.startRamp(rampProcess.id);

The user must have completed BRL KYC level 1 or higher, and the SDK's credential must be bound to that profile. The user's CPF/CNPJ is derived from the authenticated account. The taxId field is deprecated — if you still send it, it must match the tax ID on the account or registration is rejected. A technical profile without the user's eligible provider account cannot drive KYC or register the user's ramp; onboard or provision the real subject first.

BRL Offramp (Sell)

Selling crypto for BRL requires the user to sign one transaction with their own wallet. The SDK returns those transactions for you to route to the user's wallet provider.

const quote = await sdk.createQuote({
  rampType: RampDirection.SELL,
  from: Networks.Polygon,
  to: "pix",
  inputAmount: "100",            // 100 USDC
  inputCurrency: EvmToken.USDC,
  outputCurrency: FiatToken.BRL
});

const { rampProcess, unsignedTransactions } = await sdk.registerRamp(quote, {
  pixDestination: "user@example.com",
  walletAddress: "0xUSER..."
});

// unsignedTransactions contains the transactions the SDK could not sign on the
// user's behalf. Route them to the user's wallet (see below).

The PIX payout goes to pixDestination, which must belong to the user. To pay out to a different recipient, pass receiverTaxId with the recipient's CPF/CNPJ; it defaults to the user's own tax ID.

Signing The User Transaction With Wagmi

The user-owned transactions are EVM typed-data payloads or EVM transactions. Keep wallet prompts in your application and let the SDK handle classification and submission:

import { signTypedData, sendTransaction } from "@wagmi/core";

await sdk.submitUserTransactions(rampProcess.id, unsignedTransactions, {
  signTypedData: payload => signTypedData(wagmiConfig, payload),
  sendTransaction: tx => sendTransaction(wagmiConfig, tx)
});

const started = await sdk.startRamp(rampProcess.id);

Validate every field before signing: chainId, verifyingContract, value, to, and data must match what your application requested. Never sign payloads blindly.

USD, MXN, COP And ARS Ramps

USD, MXN, COP, and ARS settle through Vortex's local payment partners over the user's domestic banking rail. Pass the rail identifier as from (buy) or to (sell):

Fiat currencyRail identifierPayment rail
USD"ach"ACH bank transfer
MXN"spei"SPEI transfer
COP"ach"Colombian bank transfer
ARS"cbu"CBU bank transfer

All four corridors support buys and sells on EVM networks; AssetHub is not available for these corridors. The examples below use MXN — for the other currencies, substitute the fiat token and the rail identifier from the table. See Fiat Corridors for onboarding, fiat accounts, and limits.

Onramp (Buy)

The user pays fiat off-chain; crypto is delivered to destinationAddress on the quoted network.

import { EPaymentMethod } from "@vortexfi/sdk";

const quote = await sdk.createQuote({
  rampType: RampDirection.BUY,
  from: EPaymentMethod.SPEI,
  to: Networks.Polygon,
  network: Networks.Polygon,
  inputAmount: "201",            // 201 MXN
  inputCurrency: FiatToken.MXN,
  outputCurrency: EvmToken.USDC
});

const { rampProcess } = await sdk.registerRamp(quote, {
  destinationAddress: "0x1234567890123456789012345678901234567890",
  walletAddress: "0x1234567890123456789012345678901234567890"
  // fiatAccountId is optional for onramp
});

const started = await sdk.startRamp(rampProcess.id);

// Show the user how to pay via SPEI
console.log(started.achPaymentData);

No user-signed on-chain transactions are required for onramp. The SDK signs ephemeral transactions during registerRamp.

Quotes can be requested without any key (anonymous rate discovery). Registering through the SDK requires either a configured secretKey or an accessTokenProvider returning the current Supabase Bearer session to resolve to an onboarded profile. The same profile must have completed KYC for the corridor's country, so registration resolves to its verified payment profile automatically. A publicKey-only registration is rejected. Never expose an sk_* in browser code.

The SDK cannot mint credentials or run KYC. Onboard the real user through the Vortex app or Widget, or use Vortex's managed-profile workflow, then use a credential bound to that profile. The secret is shown only once at creation; see Authentication And API Credentials. This applies to buys and sells in all four corridors.

Offramp (Sell)

Selling crypto for fiat in these corridors requires the user to sign one or more on-chain transactions with their own wallet. The SDK returns those transactions in unsignedTransactions.

const quote = await sdk.createQuote({
  rampType: RampDirection.SELL,
  from: Networks.Polygon,
  to: EPaymentMethod.SPEI,
  network: Networks.Polygon,
  inputAmount: "10",             // 10 USDC
  inputCurrency: EvmToken.USDC,
  outputCurrency: FiatToken.MXN
});

const { rampProcess, unsignedTransactions } = await sdk.registerRamp(quote, {
  fiatAccountId: "00000000-0000-0000-0000-000000000000", // user's fiat account
  walletAddress: "0xUSER..."
});

fiatAccountId is opaque to the SDK. Create or look up the user's fiat account out-of-band and pass the ID here. It is required for offramp and optional for onramp.

Signing Offramp User Transactions

Use the SDK helper to classify, sign, broadcast, and submit each entry in unsignedTransactions:

import { signTypedData, sendTransaction } from "@wagmi/core";

await sdk.submitUserTransactions(rampProcess.id, unsignedTransactions, {
  signTypedData: payload => signTypedData(wagmiConfig, payload),
  sendTransaction: tx => sendTransaction(wagmiConfig, tx)
});

await sdk.startRamp(rampProcess.id);

For wallets that call eth_signTypedData_v4 directly, set includeDomainType: true on submitUserTransactions or pass { includeDomainType: true } to getTypedDataToSign when using the lower-level helpers.

Tracking Status

Poll for user-facing screens, use webhooks for back-office reconciliation:

const status = await sdk.getRampStatus(rampProcess.id);

See Webhooks.

Updating A Ramp

Most updates happen inside the SDK. For BRL buys, registerRamp already submits the presigned ephemeral transactions via POST /v1/ramp/update before returning. You typically only call submitUserSignature / submitUserTxHash explicitly for offramp user transactions, then startRamp.

Why The SDK Is Preferred

The SDK creates fresh ephemeral accounts per ramp, signs the transactions Vortex returns, submits ramp updates, and can persist a local backup of ephemeral secrets. This removes the most error-prone parts of a custom integration.

The default backup is unencrypted: Node.js writes ephemerals_{rampId}.json in the current working directory, while browsers write that key to same-origin localStorage. Treat either as sensitive key material. Browser storage is prototype-grade and readable by every script on the origin.

Production integrations can provide storeEphemeralKeysCallback to use encrypted or vault-backed storage instead:

const sdk = new VortexSdk({
  apiBaseUrl: "https://api.vortexfinance.co",
  secretKey: process.env.VORTEX_SECRET_KEY,
  storeEphemeralKeysCallback: async (keys, rampId) => {
    await encryptedVault.store(rampId, keys);
  }
});

The callback receives an array of { address, rampId, secret, type } entries and the ramp ID. It replaces the built-in backup, so storeEphemeralKeys has no effect when the callback is configured. The SDK awaits it during registerRamp() and stops before signing ephemeral-owned transactions if it rejects. Setting storeEphemeralKeys: false without a callback disables backup entirely and does not expose the keys elsewhere. See Ephemeral Key Custody.

For quote request races, browser token refresh, wallet-network checks, resumable payment screens, and safe polling, see Custom UI Integration.


Modified at 2026-09-08 09:47:35
Previous
Overview
Next
Authentication And API Keys
Built with