Approving payouts

Your partners drive conversions. The conversions sit as pending until you approve them — approval is your fraud gate, and it's the one manual step. Once approved, Apex handles the rest: a short holdback window, then an automatic payout on your schedule from your connected Stripe balance. In short: you approve who gets paid; Apex handles when. (Set the cadence — or switch to fully manual — under Workspace settings → Partner network.)

Where to find the queue

  • Dashboard: /dashboard/partners/payouts/queue
  • SDK: apex.listPendingPayouts()
  • MCP: list_pending_payouts

What the queue looks like

Needs your approval comes first: every pending sale, oldest first, with the partner, what they earned it for, the date, the commission, and any flags Apex has on that partner. Sales Apex is holding for review are counted under it but not listed. You can't approve those until the review ends.

Below that are the commissions you already approved that haven't been paid yet, grouped by age:

BucketAgeWhy it matters
0-30 daysRecentNormal: most are inside their holdback window
30-60 daysStaleCheck what's holding them up
60+ daysOverduePartners have waited a long time, and partner trust is at risk

Each approved row says where its money is: held, waiting for the next payout, or in a payout now.

Reviewing + approving

Dashboard

  1. Open the queue
  2. Under Needs your approval, tick the sales you want to approve
  3. Click Approve selected. The approved sales move down into the age groups, where you can follow them until they're paid. Anything that couldn't be approved is reported in the message at the top.

SDK: approve last week's sales

const queue = await apex.listPendingPayouts();
const weekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
const lastWeek = queue.awaitingApproval.items.filter(
  c => Date.parse(c.occurredAt) >= weekAgo,
);
const result = await apex.approvePayouts(lastWeek.map(c => c.id));
console.log(
  `Approved ${result.approved.length}, skipped ${result.skipped.length}`,
);

A sale that's already approved comes back in skipped with the reason already_approved.

What approval does

For each approved conversion:

  1. Status flips pending → approved
  2. A HoldbackEntry is created, splitting the commission into available + held per the partner's tier (25% held for NEW, 15% for TRUSTED, 5% for VERIFIED)
  3. Fee is snapshotted at current rates (25 bps + $0.50 default) — admin edits after this don't change what you owe
  4. approvedAt is stamped

What approval does NOT do

It does not fire the Stripe transfer. The transfer happens later per your autoPayoutPolicy cycle. Reasons:

  • Partners on NEW tier have a 90-day first-payout hold
  • Batching per (partner, cycle) minimizes Stripe fees
  • The holdback window for the held portion has to elapse before full transfer

Rejecting

When a conversion looks wrong (duplicate, suspected fraud, out-of-spec), reject it. In the dashboard, tick it and click Reject selected, either under Needs your approval or in the age groups. A sale that's already in a payout can't be rejected. From code:

await apex.rejectPayouts([conversionId], "Duplicate purchase — customer service issue");

Rejection:

  • Flips the conversion to reversed
  • Opens a low-severity audit case so patterns surface if one partner gets repeatedly rejected
  • Does NOT count against the partner's trust score directly

If you're rejecting for clear fraud, open a case via /admin/fraud-ops instead — that path triggers the trust-tier regression logic.

Setting your payout cadence

Your merchant-level autoPayoutPolicy determines when transfers fire. Pick per-program via SDK:

await apex.updateProgram(programId, {
  autoPayoutPolicy: "auto_under_cap",
  autoPayoutCapUsd: 500,
});

Three options:

  • manual — approved commissions pay out when you press Pay now in Organization settings → Payouts (default)
  • auto — daily, all approved/released commissions transfer automatically
  • auto_under_cap — weekly; a payout to one partner larger than autoPayoutCapUsd waits for Pay now. With no cap set, every payout goes out weekly (this is what the Weekly and Monthly schedules in settings save)

Handling shortfalls

If your Stripe balance is short when the scheduled transfer fires, Apex retries in 24 hours. After two failures (~48h), you get an email. See Facilitated payouts → Insufficient balance for the full escalation ladder.

You'll never get an automated "fraud" notification for a shortfall. If you legitimately ran short, Apex treats it as cash flow. Only a human at Apex can reclassify it as fraud after manual review.

Partner-side visibility

By default, partners see "processing" messaging for the first 72 hours of a delay. After that, verified / trusted partners see the reason ("merchant is topping up"), but NEW-tier partners still see masked messaging. The word "fraud" never appears on partner-facing copy.

This is intentional — cash flow issues aren't partner issues.