Subchapter 1.5
references/decision-matrix.mdMarkdown34 KBView on GitHub
ALWAYS use the Accounts v2 API (/v2/core/accounts) for new integrations. Do NOT use the legacy v1 API with type: 'express', type: 'standard', or type: 'custom'. These are legacy categories that bundle together responsibility, dashboard, and requirement decisions into opaque labels.
Instead, configure accounts using three independent dimensions:
express (lightweight), full (independent businesses), none (white-label)stripe (Stripe bills connected accounts) or application (platform manages billing)stripe (Stripe bears unresolved negative balances) or application (platform bears negative balances)| Business Model | Dashboard | Fees | Losses | Charge Pattern | Onboarding | Reasoning |
|---|---|---|---|---|---|---|
| Marketplace | express | application | application | Destination | Embedded | Platform owns customer relationship; platform-owned pricing + loss liability required for Express dashboard today |
| On-demand services | express | application | application | Destination | Embedded | Fast onboarding for drivers and providers; platform-owned pricing + loss liability required for Express |
| Professional services | express | application | application | Destination | Embedded | Similar to marketplace; platform-owned pricing + loss liability required for Express |
| SaaS with payments | full | stripe | stripe | Direct | Embedded | Sellers want independence, own Stripe accounts, own branding |
| Crowdfunding | express | application | application | Separate | Embedded | Multi-party splits and delayed release. Use transfer math (not application_fee_amount) and platform-owned loss liability for transfer reversals |
| Subscription platforms | express | application | application | Destination | Embedded | Recurring billing, platform manages subscriptions; platform-owned pricing + loss liability required for Express |
| E-commerce (white-label) | none | application | application | Destination or Direct | Embedded | Full branding control. Use embedded components for white-label feel. Going fully custom (no embedded components) adds significant complexity — the platform must build and maintain all connected account UX including onboarding remediation, refund and dispute flows, and ongoing requirement collection. |
| Rental marketplace | express | application | application | Destination | Embedded | Platform owns booking flow; platform-owned pricing + loss liability required for Express |
| Event ticketing | express | application | application | Destination | Embedded | Platform manages event and ticket flow; platform-owned pricing + loss liability required for Express |
| B2B platforms | none | application | application | Separate | Embedded | For complex enterprise multi-party flows, prefer Separate charges and transfers with transfer math. Don’t default to Destination in these scenarios. Often requires sales engagement for billing complexity — Stripe sales (opens in a new tab). |
Note: fees and losses columns refer to defaults.responsibilities.fees_collector and defaults.responsibilities.losses_collector in the v2 API. Values are "stripe" or "application" (your platform).
Rather than choosing a legacy “account type”, configure three independent dimensions:
If the user asks “what account type should I use?” (or similar): Reframe explicitly before giving settings: “In Accounts v2, avoid the legacy type parameter and configure behavior with explicit fields: dashboard, defaults.responsibilities.fees_collector, defaults.responsibilities.losses_collector, and the appropriate account configuration (merchant for direct charges or recipient for destination or separate flows).” Then provide the recommended field values.
Dashboard access:
What dashboard should connected accounts see?
├── No dashboard needed (fully embedded or white-label) → dashboard: "none"
├── Independent businesses needing full Stripe access → dashboard: "full"
└── Lightweight dashboard for sellers or providers → dashboard: "express" ← DEFAULTResponsibilities:
Who collects fees and bears losses?
├── Marketplace (destination or separate charges) → fees_collector: "application", losses_collector: "application"
│ Platform is merchant of record and should be responsible for paying Stripe fees
│ Platform-owned pricing + loss liability is REQUIRED for Express dashboard today
│ Platform-owned loss liability enables connected account negative balances for transfer reversals
├── SaaS (direct charges) → fees_collector: "stripe", losses_collector: "stripe" ← DEFAULT
└── White-label or enterprise → fees_collector: "application", losses_collector: "application" (use embedded components; fully custom adds significant complexity)Detailed rules:
dashboard: "full"dashboard: "express" (typical default)dashboard: "none"dashboard: "express" + fees_collector: "application" + losses_collector: "application"dashboard: "full" + fees_collector: "stripe" + losses_collector: "stripe"dashboard: "express" + fees_collector: "application" + losses_collector: "application" for both sidesHow many sellers per transaction?
├── Multiple sellers → Separate charges & transfers
└── One seller
└── Who should the customer pay at checkout?
├── Seller runs checkout (seller name on receipt or statement) → Direct charges
└── Platform runs checkout (platform name on receipt or statement) → Destination charges ← DEFAULTDetailed rules:
application_fee_amount)Some platforms run two sides of business with the same connected accounts. This is supported, but every transaction must be explicitly classified to the correct side:
When both sides share Express connected accounts, keep controller settings aligned with the allowed path in this guide: dashboard: "express" + fees_collector: "application" + losses_collector: "application" for both direct and destination or separate contexts.
Hybrid models add material complexity:
Launch the most business-critical side first, stabilize webhook and reconciliation behavior, then add the second side.
How much control over onboarding UX?
├── "Stripe handles everything" → Embedded components (recommended default)
├── "Some customization" → Embedded components with [appearance options API](/connect/embedded-appearance-options)
└── "Fully custom" → API-based — NOT RECOMMENDED for platforms integrating without dedicated Stripe guidance.
Requires building custom remediation flows. Direct to [Stripe sales](https://stripe.com/contact/sales).Detailed rules:
dashboard: "express" → Embedded components (recommended, keeps users in-app) or Stripe-hosted redirect (fallback)dashboard: "full" → Embedded components or Stripe-hosted redirectdashboard: "none" + want embedded → Embedded components (opens in a new tab)Marketplace connected accounts (destination or separate charges):
configuration.recipient (v2) — the connected account receives transfers from the platform, not direct paymentsstripe_transfers on stripe_balance so the account has a balance for receiving transfersconfiguration.merchant or card_payments — marketplace connected accounts don’t accept payments directly, and requesting merchant configuration causes longer, more arduous onboardingconfiguration.recipient.capabilities.stripe_balance.stripe_transfers.status === 'active' before initiating transfersSaaS connected accounts (direct charges):
configuration.merchant (v2) — the connected account accepts payments directly as merchant of recordcard_payments capabilityconfiguration.merchant.capabilities.card_payments.status === 'active' before processing chargesSaaS recurring fees (service fees or SaaS fees):
merchant and customer configurations in v2customer_account on SetupIntent and Subscription API calls — do NOT create a separate v1 Customer object (the customer configuration replaces it)| Q1: Model | Q3: Flow | Q4: Control | → Dashboard | → Fees and Losses | → Charges | → Onboarding |
|---|---|---|---|---|---|---|
| Marketplace | Platform collects | Stripe handles | express | application/application | Destination | Embedded |
| Marketplace | Platform collects | Some custom | express | application/application | Destination | Embedded |
| Marketplace | Platform collects | Fully custom | none | application/application | Destination | Embedded |
| Marketplace | Direct to seller | Stripe handles | full | stripe/stripe | Direct | Embedded |
| SaaS | Direct to seller | Stripe handles | full | stripe/stripe | Direct | Embedded |
| SaaS | Platform collects | Stripe handles | express | application/application | Destination | Embedded |
| On-demand | Platform collects | Stripe handles | express | application/application | Destination | Embedded |
| Crowdfunding | Platform collects | Stripe handles | express | application/application | Separate | Embedded |
| Platform + contractors | Platform collects | Stripe handles | express | application/application | Destination | Embedded |
Note: This section is directional guidance only. For detailed risk and Radar configuration, refer to the Radar documentation (opens in a new tab).
Default recommendation: Let Stripe manage risk. This usually reduces operational overhead for launch. Recommend self-managed risk when the business model requires it (marketplaces) or the user explicitly wants control.
| Business Model | Risk Owner | Radar | Stripe-Managed OK? | Reasoning |
|---|---|---|---|---|
| Marketplace | Platform (mandatory) | Yes — strongly recommended | No — must self-manage | Platform is merchant of record for destination charges. Liable for fraud and disputes. Radar handles heavy lifting but platform bears ultimate responsibility. |
| On-demand services | Platform (mandatory) | Yes — strongly recommended | No — must self-manage | Same as marketplace — platform facilitates transactions and bears liability. |
| Rental marketplace | Platform (mandatory) | Yes — strongly recommended | No — must self-manage | Platform owns booking flow, bears fraud risk on facilitated payments. |
| SaaS with payments | Stripe (recommended) | Optional | Yes — recommended | Stripe’s built-in protection handles most fraud. Platform can upgrade to Radar later if needed. |
| Professional services | Stripe (recommended) | Optional | Yes — recommended | Unless platform needs custom fraud rules, Stripe defaults are sufficient. |
| Crowdfunding | Stripe (recommended) | Optional | Yes — recommended | Stripe-managed defaults are often sufficient for launch; reassess based on dispute and fraud patterns. |
| Subscription platforms | Stripe (recommended) | Optional | Yes — recommended | Recurring billing has different risk profile — churn > fraud. Stripe’s defaults usually sufficient. |
| E-commerce (white-label) | Platform (mandatory) | Yes | No — must self-manage | Full control = full responsibility. Dashboard-none configurations need platform-managed risk. |
Key rules:
chargePattern is destination or separate, the platform is the merchant of record and MUST manage risk — but Radar does the heavy lifting.chargePattern is direct, Stripe-managed risk is available and recommended.| Charge Pattern | Fee Method | Implementation |
|---|---|---|
| Direct (Stripe owns pricing) | application_fee_amount | Strongly recommended. Charged in addition to Stripe fees that the connected account pays. The platform retains the full application fee amount. |
| Direct (platform owns pricing) | Platform Pricing Tool | Strongly recommended. Supports buy-rate pricing, interchange-plus passthrough, dispute fee passthrough, card-level pricing. |
| Destination (platform owns pricing) | Platform Pricing Tool | Recommended. Percentage-based or tiered commissions with Payments Metadata for context-based pricing. |
| Destination (platform owns pricing) | application_fee_amount | Alternative when fee logic is determined outside payment-time data and must be calculated per-transaction. |
| Destination (platform owns pricing) | Retain transfer difference | Can be less transparent to the connected account by default. Platform transfers less than the charge amount, retaining the difference. |
| Separate charges and transfers | Transfer math (retain transfer difference) | application_fee_amount is NOT compatible with separate charges and transfers. Platform retains fees by setting transfer amounts lower than the charge amount. |
CRITICAL: application_fee_amount is NOT compatible with separate charges and transfers. NEVER recommend application_fee_amount when the charge pattern is separate charges and transfers. Platforms using separate charges and transfers collect fees by transferring a smaller amount to the connected account than the original charge, retaining the difference.
For separate charges and transfers, frame fee guidance as transfer math: platform_margin = charge_amount − total_transfers_to_connected_accounts − Stripe_fees
Who pays Stripe’s processing fees is one of the determining factors in whether your platform is profitable.
Stripe charges processing fees on every transaction. Rates vary by region, card type, payment method, and negotiated terms — see stripe.com/pricing (opens in a new tab) for current rates. Who actually pays these fees depends on the charge pattern:
| Charge Pattern | Who Pays Stripe Fees | Platform Net per Transaction |
|---|---|---|
| Destination charges | Platform pays Stripe fees | application_fee_amount − Stripe_fees |
| Destination charges + on_behalf_of | Platform still pays (changes statement descriptor, merchant of record, and dispute management — see charge-patterns.md) | Same as above |
Direct charges (fees_collector: "stripe") | Connected account pays Stripe fees | application_fee_amount (platform retains full fee — Stripe fees paid by connected account) |
Direct charges (fees_collector: "application") | Platform pays Stripe fees | application_fee_amount − Stripe_fees |
| Separate charges & transfers | Platform pays Stripe fees | Must account for fees in transfer math |
Who pays Stripe fees on direct charges depends on the fees_collector (opens in a new tab) responsibility setting. When fees_collector: "stripe" (the default for SaaS), the connected account pays Stripe fees and the platform retains their full application_fee_amount. With fees_collector: "application" (used with Platform Pricing Tool and platform-owned pricing), the platform pays Stripe fees instead.
Profitability warning: If the platform’s desired fee margin is low relative to Stripe’s processing fees for their region, destination charges may cause per-transaction losses unless the application_fee_amount is set high enough to cover Stripe fees + the platform’s margin. DO NOT make definitive profit and loss claims with specific dollar amounts — pricing is situation-dependent.
Strongly recommend:
fees_collector: "application"; supports direct and destination charges, NOT separate charges and transfers)After the user specifies their platform fee, identify the charge pattern first. This question applies to destination charges only. For separate charges and transfers, don’t ask how to set application_fee_amount — use transfer math instead. For direct charges with Stripe-owned pricing (fees_collector: "stripe"), the connected account pays Stripe fees and this question is moot. For direct charges with platform-owned pricing (fees_collector: "application"), the platform pays Stripe fees — use the Platform Pricing Tool.
IMPORTANT: With destination charges, the platform ALWAYS pays Stripe’s processing fees. They are deducted from the platform’s balance, not the connected account’s. The platform can’t make connected accounts pay Stripe fees directly. The choice is how to calculate application_fee_amount.
Use Option A and Option B below as reference material for destination charges.
Option A — Include Stripe fee estimate in application_fee_amount (recommended for low margins) The application_fee_amount includes BOTH an estimated Stripe processing fee and the platform’s fee. The platform takes a larger cut to cover both its margin and Stripe’s fee. The platform’s fee percentage is preserved as net margin.
Concept: application_fee_amount = estimated Stripe processing fee + platform margin
Platform NET = the platform's full fee percentage (margin preserved — Stripe fee covered by the higher application_fee_amount)
Connected account receives = charge amount − application_fee_amountOption B — Platform fee only (platform absorbs Stripe fees) The application_fee_amount is only the platform’s cut. Stripe processing fees reduce the platform’s net. Only viable when the platform fee is substantially higher than Stripe’s processing fees.
Concept: application_fee_amount = platform fee only
Platform NET = platform fee − Stripe processing fee
Connected account receives = charge amount − application_fee_amountRecommendation output rule: choose the single most appropriate option for the specific scenario instead of always presenting both. Keep the other option as reference material and show it only when the user asks for alternatives and tradeoffs.
Decision guidance: If the platform fee appears low or uncertain relative to processing fees (check stripe.com/pricing (opens in a new tab)), recommend Option A to preserve platform margin (or switch to direct charges when appropriate). Use Option B only when fee headroom is clearly high and the platform explicitly accepts absorbing fee variance.
For destination charges, NEVER say “seller pays Stripe fees” or “connected account pays Stripe fees.” The platform always pays. The choice is whether to set a higher application_fee_amount to preserve the platform’s margin.
Minimum charge amounts: Stripe enforces minimum charge amounts by currency. For micro-payment platforms with very small transaction amounts, warn the user that:
When presenting fee recommendations:
application_fee_amount and what it should include based on the calculation choiceapplication_fee_amount)application_fee_amount is NOT set on the PaymentIntent — explicit application_fee_amount overrides the Platform Pricing Tool.application_fee_amount is NOT compatible with separate charges and transfers. NEVER recommend it for separate charges and transfers.charge_amount − total_transfers − Stripe_fees) to ensure expected platform margin.amount on the ApplicationFee object, not the charge field, for accurate fee reporting.Loss liability and risk management are TWO SEPARATE decisions. The current skill MUST NOT conflate them.
| Concept | What it means | Where configured |
|---|---|---|
| Negative balance liability | Who is financially LIABLE when disputes and chargebacks create negative balances on connected accounts | Configured when creating the connected account; may require visiting the Stripe Dashboard → Connect platform profile to acknowledge understanding of how negative balance liability works |
| Risk management | Who DETECTS and PREVENTS fraud (Radar, rules, monitoring) | Code + Dashboard (Radar settings) |
You can have Stripe own loss liability while still using Radar for fraud detection. Radar is available regardless of loss liability setting.
Recommendation depends on charge pattern:
| Business Model | Recommended Loss Liability | Why |
|---|---|---|
| Marketplace | Platform | Required for destination charges — enables connected account negative balances for transfer reversals |
| On-demand services | Platform | Same as marketplace — uses destination charges |
| Professional services | Platform | Same as marketplace — uses destination charges |
| Rental marketplace | Platform | Same as marketplace — uses destination charges |
| Event ticketing | Platform | Same as marketplace — uses destination charges |
| Crowdfunding | Platform | Uses separate charges — platform-owned loss liability enables flexible transfer reversals |
| Subscription platforms | Platform | Uses destination charges — platform-owned loss liability required |
| SaaS with payments | Stripe | SaaS platforms use direct charges — connected account is merchant of record |
| E-commerce (white-label) | Platform | Full control = full responsibility (dashboard: none, platform-managed) |
| B2B platforms | Platform | Enterprise requirements usually demand full control |
Loss liability is configured when creating connected accounts, but the platform must first visit the Stripe Dashboard → Connect platform profile (dashboard.stripe.com/settings/connect/platform-profile) to acknowledge understanding of how negative balance liability works.
The platform profile page asks about “Negative balance liability” (formerly called “loss liability”). The choice determines which account configuration combinations are available:
defaults.responsibilities.losses_collector: "stripe" in v2 APIdefaults.responsibilities.losses_collector: "application" in v2 APIWhen guiding users through this page, always:
Read the full compatibility matrix in
compatibility-matrix.md. This section is a quick reference.
These combinations are true antipatterns that Stripe will never support. Do NOT recommend them:
losses_collector: "stripe" + destination charges — Liability and fee behavior don’t align with this charge pattern. Treat as BLOCKED when losses_collector: "stripe" is selected.losses_collector: "stripe" + separate charges and transfers (including on_behalf_of) — Same negative balance mechanism as destination charges. Platform can’t recover funds from connected accounts that only receive transfers.losses_collector: "stripe" + fees_collector: "stripe" — Express dashboard requires platform to own both fees and losses (application and application). This is a hard API constraint — setting Express with Stripe-owned pricing produces an API rejection.dashboard: "full" + destination charges or separate charges and transfers — Full dashboard has reduced payment and dispute detail for destination and separate charges. Full dashboard provides complete payment and dispute management for direct charges only.fees_collector: "stripe" + losses_collector: "application" (Stripe-owned pricing + platform-owned losses) — This combination is BLOCKED for all charge types. The reverse — fees_collector: "application" + losses_collector: "stripe" — is SALES-GATED for full dashboard and BLOCKED for none and express dashboards.on_behalf_of is out of scope for this guide — redirect to docs or sales if encountered.) on_behalf_of with destination charges for marketplace use cases — Do NOT use on_behalf_of for marketplaces. on_behalf_of makes the connected account the merchant of record, but in a marketplace the platform should be merchant of record. If a user requires on_behalf_of, direct them to Stripe Connect docs (opens in a new tab) or Stripe sales (opens in a new tab).application_fee_amount with separate charges and transfers — NOT compatible. Platforms using separate charges and transfers collect fees by transferring less than the charge amount.| Business Model | Dashboard | Fees | Losses | Charge Type | Status |
|---|---|---|---|---|---|
| Marketplace | express | application | application | Destination | CAUTION — recommended path; always include Express dispute-visibility warning (see compatibility-matrix.md) |
| SaaS | full | stripe | stripe | Direct | ALLOWED — connected accounts are independent merchants |
| Enterprise | none | application | application | Any | ALLOWED — full platform control |
Any deviation from these blessed paths should trigger a compatibility check against compatibility-matrix.md. If the user’s choices lead to a BLOCKED combination, don’t present it. Explain why it fails and recommend the nearest allowed alternative.
Scope boundary: This guide supports the blessed paths above. Configurations outside these paths (full+application,
on_behalf_of, OAuth, non-payments products like Issuing, Treasury, Capital, Tax, or Terminal) should trigger sales-led detection and redirect to docs or sales.nonedashboard requires platform-owned pricing AND platform-owned losses — no othernonecombination is valid even for sold users.
dashboard: "none" + API-based) — Ongoing requirement collection burden and country-specific complexity. Only for platforms with dedicated compliance engineering.