pex

Facilitated payouts

Apex runs the money rail for partner commissions via Stripe Connect. Two critical properties:

  1. Apex never advances funds. Money only moves if the merchant has balance in their Stripe account. No platform overdraft.
  2. Money movement happens in the merchant's Stripe context. Transfers fire under {stripeAccount: merchantStripeAccountId} — Apex's platform balance is never touched.

This makes Apex a facilitator, not an escrow. The tradeoff: the partner has to wait until the merchant's Stripe balance is there + the scheduled payout cycle hits.

The shape of a payout

merchant's Stripe balance
  ↓ transfer (principal, in merchant's account context)
partner's Stripe Express account
  +
merchant's Stripe balance
  ↓ transfer (fee, in merchant's account context)
Apex Connect platform account

Two stripe.transfers.create calls per payout. Same idempotency batch (payout:<id>:principal + payout:<id>:fee). If the principal fires but the fee fails, the retry only re-attempts the fee leg.

The full lifecycle of one commission

  1. Conversion attribution — partner's link (or coupon code) drives a signup; the contact is stamped with referringAffiliateId
  2. Purchase / subscription event — commission rules evaluate the event type (install, purchase, subscription_renewal), auto-credit fires, creates an AffiliateConversion with status: "pending" (or "pending_review" if risk score ≥ 0.5)
  3. Merchant approves (or auto-approve per autoPayoutPolicy) — transitions to "approved", creates a HoldbackEntry splitting commission into available + held per tier
  4. Release cron fires past-due holdback entries (after 30 / 60 / 90 days by tier) — flips releasedAt
  5. Payout orchestrator runs per merchant's autoPayoutPolicy schedule (daily / weekly / manual) — batches all released-available entries per partner, fires the pair of transfers
  6. Held portion stays reserved — only releases + pays out after the hold window. Chargebacks in the interim debit this portion first.

Recurring subscription payouts

For subscription_renewal events, the flow repeats on every renewal cycle:

  1. Stripe fires invoice.paid for the renewal
  2. Apex matches the subscription to the original referring partner via referringAffiliateId
  3. The subscription_renewal commission rule evaluates — creates a new AffiliateConversion
  4. If maxCredits is set on the rule and the partner has already earned that many renewal commissions, the event is skipped
  5. The new conversion enters the same approval → holdback → release → payout pipeline

Partners see recurring earnings accumulate in their portal with a clear breakdown per subscription and renewal period.

autoPayoutPolicy — merchant control of when transfers fire

PolicyTrigger
manualMerchant approves each batch from /dashboard/partners/payouts/queue
autoDaily cron — every released-available balance over $0 pays out
auto_under_capWeekly cron — auto for partners under autoPayoutCapUsd, manual above

Set per-project (default) or per-program (override). Merchants choose their own cadence based on cash flow.

Insufficient balance

When the merchant's Stripe balance is short, the executor returns insufficient_balance with the shortfall USD and a 24-hour retryAtMs. The cron schedules a retry. We don't pull funds from Apex.

A graduated, non-accusatory escalation kicks in:

DayFailuresAction
01stSilent — retry in 24h
12nd (~48h)Merchant email + internal notification
23rd (~72h)Dashboard card + 2nd email + partner visibility flips per trust tier
77thOpen a support case (ruleId: merchant_cash_flow, severity: medium, not labeled as fraud). Retries pause until human review.

Automation never freezes autoPayoutPolicy. A human (Fraud Ops or account manager) is always the one who pulls that trigger.

Partner-visible state during delays

Delay visibility is tiered by trust:

Partner tierDay 0-2Day 3-6Day 7+
NEW"Your payout is processing""Your payout is still processing""This payout is delayed — our team is working with the merchant"
TRUSTED"Your payout is processing""Your merchant is topping up their Stripe balance""This payout is delayed — our team is working with the merchant"
VERIFIED"Your payout is processing""Your merchant is topping up their Stripe balance""This payout is delayed — our team is working with the merchant"

Partner-facing copy never uses the word "fraud". Merchant-facing emails use "cash flow" and "action needed" — never "fraud" — at every escalation level.

Fees

Apex charges a facilitation fee on every transfer: 25 basis points + $0.50 flat by default. Enterprise merchants can negotiate custom rates via /admin/fees. See Fee policy.

Fees are snapshotted on the HoldbackEntry at approval time. Admin edits after approval don't change what a merchant owes on already-approved commissions.

1099 tax compliance

Stripe handles 1099-NEC issuance for US partners earning $600+ in a calendar year. W-9/W-8BEN forms are collected during Stripe Express onboarding. See Tax compliance for the full flow.

Clawbacks

When a charge.refunded webhook lands, Apex:

  1. Finds every conversion linked to the paymentIntent
  2. Flips them to clawed_back
  3. Debits partner holdback entries oldest-first per applyClawback
  4. If the reserve is insufficient, logs the shortfall + flags for Fraud Ops review

Disputes (charge.dispute.created) flip the conversion to pending_review and wait for dispute resolution before debiting.