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
Authorization: Bearer <inflow_apikey>
Content-Type: application/json

Request body:

FieldTypeRequiredDescription
emailstringyesSub-merchant's contact email. Must not already be used by any Inflow user.
bridgeCustomerType"individual" | "business"no (default "individual")Drives the verification flow: individual → KYC, business → KYB.
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):

{
  "subMerchantId": "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 contractnextUrl 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

bridgeCustomerTypeVerification flowWhat happens after approval
"individual"KYC (hosted link)Inflow provisions the sub-merchant's wallet automatically.
"business"KYB (hosted link)Inflow finalises the business identity and provisions the sub-merchant's wallet automatically.

In both cases the sub-merchant is not operable until kycStatus = "approved". X-On-Behalf-Of calls return 403 ON_BEHALF_SUBMERCHANT_NOT_OPERABLE until then.

Failure-tolerant semantics

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

{
  "subMerchantId": "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.

Listing sub-merchants

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

Response shape matches the Inflow paginated convention:

{
  "data": [ { "id": "usr_…", "email": "…", "merchantName": "…", "kycStatus": "approved", … } ],
  "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
Authorization: Bearer <inflow_apikey>

Returns the full sub-merchant profile, including:

  • Identity: email, merchantName, firstName, lastName, marketplaceMetadata.
  • Wallet info: provider, address.
  • Operability: kycStatus, suspended, plus a fresh nextUrl / nextSteps if KYC is still in progress.

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
Authorization: Bearer <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.xyz/api/connect/accounts", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.INFLOW_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    email: seller.email,
    merchantName: seller.shopName,
    bridgeCustomerType: "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.subMerchantId` against your seller, then redirect:
res.redirect(sub.nextUrl);

When the seller comes back to your redirectUrlKyc, poll GET /api/connect/accounts/:subMerchantId/kyc/status until kycStatus === "approved" — see KYC Flow.