Skip to content
Payments docs are in beta — the OpenAPI contract is the source of truth.API reference
VortexPayments
Esc
↑↓navigate↵open⌘Jpreview
On this page

Merchant onboarding

Collect identity, underwriting, and bank data to approve a Vortex merchant account.

Merchant onboarding

Vortex Payments handles merchant onboarding, processing, and settlement. Before a merchant account can charge or settle, its identity, underwriting, and banking information must be approved.

The flow at a glance

  1. Create a merchant account — POST /v1/merchant-accounts. The account starts in draft.
  2. Create a hosted onboarding link — POST /v1/merchant-accounts/{merchantAccountId}/onboarding-link. Send the URL to the merchant, or use it yourself in sandbox.
  3. Collect and submit data — either through the hosted page or by calling the onboarding API with the complete merchant profile and consent attestation.
  4. Track requirements — Vortex returns a list of open requirements (documents, forms, data). Each moves through pending → submitted → satisfied / failed / waived.
  5. Wait for approval — the session status moves draft → submitted → under_review → approved. Once approved, the merchant account becomes active.

If the session lands on action_required, refresh it to see the new requirements, provide them, and refresh again. rejected and restricted are terminal states that need operator support.

Required merchant identity

The merchant account create request already captures the basics:

Field Purpose
displayName Legal business name
legalEntityType CORPORATION, LLC, PARTNERSHIP, etc.
country ISO country code, e.g. USA
merchantMode processing, payout_only, or hybrid
defaultCurrency Three-letter currency, e.g. USD

For a live submission you also want:

  • businessAddress and personalAddress
  • businessTaxId (EIN) and taxId
  • doingBusinessAs, businessPhone, email
  • firstName, lastName, dateOfBirth
  • incorporationDate
  • mcc and url
  • settlementBankAccount (account number, account type, bank code, name)

Required underwriting

processing and hybrid merchants need additional underwriting data. These fields are required and the percentage distributions must sum to 100.

Field Notes
achMaxTransactionAmount Largest ACH transaction you expect
annualCardVolume Estimated annual card volume
underwriting.annualAchVolume Estimated annual ACH volume
underwriting.averageAchTransferAmount Average ACH transfer
underwriting.averageCardTransferAmount Average card transaction
underwriting.businessDescription What the business does
underwriting.cardVolumeDistribution cardPresentPercentage + mailOrderTelephoneOrderPercentage + ecommercePercentage = 100
underwriting.refundPolicy One of NO_REFUNDS, MERCHANDISE_EXCHANGE_ONLY, REFUNDS_WITHIN_30_DAYS, OTHER
underwriting.volumeDistributionByBusinessType otherVolumePercentage + consumerToConsumerVolumePercentage + businessToConsumerVolumePercentage + businessToBusinessVolumePercentage + personToPersonVolumePercentage = 100

Associated identities / beneficial owners

The people behind the business are required. Each associated identity includes identityRoles and an optional relationType:

  • control_person
  • beneficial_owner
  • representative

Each identity can also carry firstName, lastName, title, email, phone, taxId, dateOfBirth, and personalAddress.

An explicit merchant agreement consent is required. The attestation is captured at submission and includes:

  • merchantAgreementAccepted: true
  • merchantAgreementAcceptedAt — ISO 8601 UTC timestamp
  • merchantAgreementIpAddress — the merchant’s IP
  • merchantAgreementUserAgent — the merchant’s user agent

Optional fields include the payment terms, privacy policy, fee disclosure, and terms URLs that the merchant accepted.

Example create a complete merchant

import {
  createMerchantAccount,
  createVortex,
} from "@vortex-api/vortex/2026-08";

const vortex = createVortex({ apiKey: process.env.VORTEX_API_KEY });

const { data, error } = await createMerchantAccount({
  client: vortex,
  body: {
    environment: "sandbox",
    externalMerchantRef: "acme-sandbox",
    displayName: "Acme Inc.",
    legalEntityType: "CORPORATION",
    merchantMode: "processing",
    country: "USA",
    defaultCurrency: "USD",
    businessTaxId: "12-3456789",
    businessPhone: "+1 555 0100",
    email: "finance@acme.example",
    doingBusinessAs: "Acme",
    mcc: "5411",
    url: "https://acme.example",
    achMaxTransactionAmount: 100000,
    annualCardVolume: 1000000,
    businessAddress: {
      line1: "123 Market St",
      city: "San Francisco",
      region: "CA",
      postalCode: "94105",
      country: "USA",
    },
    settlementBankAccount: {
      accountNumber: "000123456789",
      accountType: "CHECKING",
      bankCode: "121000248",
      name: "Acme Inc.",
    },
    associatedIdentities: [
      {
        identityRoles: ["owner"],
        relationType: "beneficial_owner",
        firstName: "Alice",
        lastName: "Example",
        principalPercentageOwnership: 50,
        personalAddress: {
          line1: "123 Market St",
          city: "San Francisco",
          region: "CA",
          postalCode: "94105",
          country: "USA",
        },
      },
    ],
    underwriting: {
      businessDescription: "Retail grocery",
      annualAchVolume: 500000,
      averageAchTransferAmount: 25000,
      averageCardTransferAmount: 75,
      refundPolicy: "REFUNDS_WITHIN_30_DAYS",
      cardVolumeDistribution: {
        cardPresentPercentage: 90,
        mailOrderTelephoneOrderPercentage: 0,
        ecommercePercentage: 10,
      },
      volumeDistributionByBusinessType: {
        otherVolumePercentage: 0,
        consumerToConsumerVolumePercentage: 0,
        businessToConsumerVolumePercentage: 100,
        businessToBusinessVolumePercentage: 0,
        personToPersonVolumePercentage: 0,
      },
    },
  },
});
if (error) throw new Error(JSON.stringify(error));
console.log(data.data.id); // ma_...

Send the merchant a link so they can review and consent in a browser:

import {
  createMerchantOnboardingLink,
  createVortex,
} from "@vortex-api/vortex/2026-08";

const vortex = createVortex({ apiKey: process.env.VORTEX_API_KEY });

const { data, error } = await createMerchantOnboardingLink({
  client: vortex,
  path: { merchantAccountId: "ma_..." },
  body: {
    environment: "sandbox",
    createdByRef: "operator:my-user-id",
  },
});
if (error) throw new Error(JSON.stringify(error));
console.log(data.data.hostedMerchantOnboardingUrl);

The hosted page shows the merchant the session status, open requirement count, and a refresh control. In sandbox it is the fastest way to verify the end-to-end flow.

Document uploads

When a requirement asks for a document, upload it through Vortex. Vortex relays the bytes upstream, so the merchant never resolves a provider hostname.

  • Allowed types: image/jpeg, image/png, image/tiff, application/pdf
  • Maximum size: 10 MB

For each requirement, request a pre-signed upload link, PUT the file, then refresh the requirement status. The exact upload shapes are in the API reference under the merchant-accounts onboarding routes.

Status reference

Session status

Status Meaning
draft Data collection in progress
submitted Submitted for underwriting
under_review Underwriting review in progress
action_required More information needed
approved Merchant can process and settle
rejected Merchant rejected; contact support
restricted Approved with restrictions; contact support

Requirement status

Status Meaning
pending Not yet provided
submitted Provided and awaiting review
satisfied Accepted
failed Rejected; provide again
waived Not required for this merchant

Sandbox vs. production

Sandbox onboarding runs on test rails. Approval is usually fast, and test merchant data is accepted as long as the fields are well-formed. Production onboarding follows live underwriting and can take longer.

The request body always includes environment: "sandbox" or environment: "production". The API rejects a body whose environment does not match the key (vp_test_ or vp_live_), which keeps sandbox and live data strictly separated.

Where next

Last updated on September 25, 2026

Was this page helpful?