Sub-merchant Onboarding

A sub-merchant is a separate Inflow account owned by your marketplace. It has its own KYC, its own balance, and its own payout destination. The marketplace creates them, updates their profile, suspends/resumes them, and acts on their behalf.

All routes below are authenticated with your marketplace API key. Sub-merchants don't authenticate against the Inflow API directly; every action is mediated by the parent marketplace.

Creating a sub-merchant

POST /api/connect/accounts
X-Inflow-Api-Key: <inflow_apikey>
Content-Type: application/json

Request body:

FieldTypeRequiredDescription
emailstringyesSub-merchant's contact email. Must not already be used by any Inflow user.
customerType"individual" | "business"no (default "individual")Drives the verification flow: individual → KYC, business → KYB. (bridgeCustomerType is accepted as a deprecated alias.)
merchantNamestringnoDisplay name. Defaults to "SubMerchant" if omitted.
firstNamestringno (used for individuals)If omitted, derived from merchantName / email.
lastNamestringno (used for individuals)Defaults to "Merchant" if omitted.
marketplaceMetadataobjectnoArbitrary metadata you want to associate (your seller id, tier, etc.). Inflow-reserved keys are silently dropped.
redirectUrlKycstring (URL)noWhere to redirect the sub-merchant after they complete KYC. Falls back to defaultRedirectUrlKyc from your marketplace settings.

Response (201 Created):

{
  "id": "usr_01JABCDEF…",
  "kycStatus": "pending",
  "verificationType": "KYC",
  "verificationProvider": "BRIDGE",
  "nextUrl": "https://bridge.with…/onboarding?session=…",
  "nextSteps": [
    "redirect_submerchant_to_url",
    "complete_bridge_tos_and_kyc_flow",
    "check_connect_kyc_status"
  ],
  "email": "[email protected]",
  "merchantName": "Acme Coffee",
  "marketplaceMetadata": { "yourSellerId": "S-12" }
}

The response is the unified KYC contract: nextUrl and nextSteps are the single source of truth for what the marketplace should do next. See KYC Flow for the full state machine.

Individual vs. business

customerTypeVerification flowWhat happens after approval
"individual"KYC (hosted link, verificationProvider: "BRIDGE")Inflow provisions the sub-merchant's balance account automatically.
"business"KYB (hosted link, verificationProvider: "SUMSUB")Inflow finalises the business identity and provisions the sub-merchant's balance account automatically.

In both cases the sub-merchant becomes fully operable once kycReady is true on GET /api/connect/accounts/:id/kyc/status.

Pre-KYC card payins. Card payins may be accepted before KYC completes, up to a volume cap (they are auto-locked when the cap is hit). Everything else, payouts in particular, is hard-blocked until KYC is approved: X-On-Behalf-Of calls return 403 ON_BEHALF_SUBMERCHANT_NOT_OPERABLE.

Failure-tolerant semantics

If the initial KYC bootstrap fails after the sub-merchant has been created (e.g. provider timeout), the response still includes id so you don't lose track of it:

{
  "id": "usr_…",
  "kycStatus": "pending",
  "kycBootstrapError": "hosted-kyc-link timeout",
  "nextSteps": ["retry_kyc_bootstrap", "check_connect_kyc_status"]
}

The sub-merchant exists and you can retry by calling GET /api/connect/accounts/:subMerchantId/kyc/status, which re-issues the verification link.

Declared profile

For risk monitoring, you can attach a declared profile to each sub-merchant: what they sell, their pricing model and price points, expected ticket size and monthly volume, customer type (B2B / B2C) and geographies, plus website and social links. Inflow uses it to detect first-party fraud (payments that don't match what the account is supposed to sell) and to speed up compliance reviews.

ActionEndpoint
CreatePOST /api/connect/accounts/{subMerchantId}/declared-profile
ReadGET /api/connect/accounts/{subMerchantId}/declared-profile
UpdatePATCH /api/connect/accounts/{subMerchantId}/declared-profile
DeleteDELETE /api/connect/accounts/{subMerchantId}/declared-profile

All routes use your marketplace API key, without X-On-Behalf-Of. The profile is optional but recommended for every sub-merchant you onboard; see the API reference for the full field list.

Listing sub-merchants

GET /api/connect/accounts?page=1&limit=20&email=&merchantName=
X-Inflow-Api-Key: <inflow_apikey>
Query paramTypeDefaultDescription
pageint (≥ 1)1Page number, 1-indexed.
limitint (1–100)20Items per page.
emailstringnoneExact-match (case-insensitive) email filter. Useful to resolve a sub-merchant by the email you signed it up with.
merchantNamestringnoneCase-insensitive substring match on merchantName.

Response shape matches the Inflow paginated convention:

{
  "data": [ { "id": "usr_…", "email": "…", "merchantName": "…", "connectKycStatus": "approved", "stopProcessingSettlement": false, … } ],
  "meta": { "total": 42, "lastPage": 3, "currentPage": 1, "perPage": 20, "prev": null, "next": 2 }
}

Listings are always scoped to the calling marketplace; cross-marketplace reads are structurally impossible.

Reading a sub-merchant

GET /api/connect/accounts/:subMerchantId
X-Inflow-Api-Key: <inflow_apikey>

Returns the full sub-merchant profile, including:

  • Identity: email, merchantName, firstName, lastName, marketplaceMetadata.
  • Balance account fields: custodialWalletProvider, custodialWalletAddress, custodialWalletExternalId.
  • Operability: connectKycStatus (cached KYC status) and stopProcessingSettlement (suspension flag).

This read is a profile snapshot; it does not include nextUrl / nextSteps. For the live KYC progression contract (fresh verification link, next actions), call GET /api/connect/accounts/:subMerchantId/kyc/status. See KYC Flow.

404 if the sub-merchant doesn't exist or doesn't belong to your marketplace.

Updating a sub-merchant's profile

PATCH /api/connect/accounts/:subMerchantId
X-Inflow-Api-Key: <inflow_apikey>
Content-Type: application/json

Only these fields are accepted:

FieldNotes
merchantNameDisplay name.
firstNameIndividual sub-merchants only.
lastNameIndividual sub-merchants only.
marketplaceMetadataShallow-merged into the existing object. Inflow-reserved keys are silently dropped.

Anything else (email, identity / KYC provider IDs, wallet pointers, fee rates, suspension flag) is intentionally not editable here. KYC fields are tied to the verification record, fees live in your marketplace settings, and suspension uses the dedicated routes documented in Suspension and Lifecycle.

Suspend / resume

See Suspension and Lifecycle for POST /api/connect/accounts/:subMerchantId/suspend and …/resume.

End-to-end snippet

const sub = await fetch("https://api.inflowpay.com/api/connect/accounts", {
  method: "POST",
  headers: {
    "X-Inflow-Api-Key": process.env.INFLOW_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    email: seller.email,
    merchantName: seller.shopName,
    customerType: "individual",
    firstName: seller.firstName,
    lastName: seller.lastName,
    marketplaceMetadata: { yourSellerId: seller.id },
    redirectUrlKyc: `https://marketplace.example.com/onboarding/${seller.id}/done`,
  }),
}).then(r => r.json());

// Persist `sub.id` as your seller's sub-merchant id, then redirect:
res.redirect(sub.nextUrl);

When the seller comes back to your redirectUrlKyc, poll GET /api/connect/accounts/:subMerchantId/kyc/status until kycReady === true. See KYC Flow.


Did this page help you?