Payouts

The running jobjob_7Hq2 · accepted · document.fr-CA.pdf · $49.00 final

How money reaches each account, on Stripe Connect. Your share of each charge transfers to your connected account and pays out to your bank; members' pay transfers on the Pool's schedule and each account pays out daily; every deposit reconciles back to its jobs, and an account that can't be paid keeps its pay.

Payouts answer where the money goes once a charge releases. Every account is a Stripe Connect account: yours, which receives what your brand sells, and each member's, which receives their pay. services.dev holds only held dollars waiting for their fact, each tagged to its job (flow of funds).

You connect one account per brand, once, before the first live order:

Run
npx services.dev payouts
magic values: none
api.forsale · payouts · Stripe Connect
  account   acct_…F0r5 · api.forsale · verified · bank …6789
  receives  your share of each charge, one transfer when it releases · services.dev's take stays on its account, its own entry
  held      outcome money waits under its own job, outside your balance, until its window closes
  pays you  to your bank daily, two days after a charge collects
  members   pay transfers on the Pool's schedule, from each job's charge, or by a debit from your balance before any charge · each account pays out daily
  closers   weekly, on Fridays · a new closer's first 5 gigs wait 7 days (hold_first)
  health    median 2.4 days from act to bank · p90 4.1 days · 0 failed this month
What lands thereWhen
Your share of each charge your brand sellsone transfer when the charge releases
Held outcome moneywhen its window closes; until then it waits under its job, outside your balance
Refunds and chargebacksdebited from it: refunds and disputes
services.dev's takestays on services.dev's account when your share transfers, as its own entry, and returns pro rata with a refund

A fee sold on a member's own rail lands on the member's account, never on yours. Until your account is connected, a live order answers BLOCKED with the cure, and test mode pays out on the simulated rail:

captured/money-payouts.txt · 403 · magic values: none
→ POST /deals {"account":{"name":"Northwind Freight"},"value":80000,"offer":"https://seller.example/offer","max_usd":12000,"key":"northwind"}   # live, before the account is connected
{
  "type": "BLOCKED",
  "category": "unavailable",
  "code": "payouts_unconfigured",
  "reason": "Live orders need api.forsale's payout account: its charges land there, and its members are paid from it.",

A member connects one payout account at the last step of /join, and the same account serves every Pool and brand they work for. The Pool's schedule sets when pay transfers to it: from the job's charge, or, for pay that comes before any charge, such as a setter's, by a debit from your balance (money outside a charge). The account pays out to the member's bank daily, on Stripe's timing:

Run
grep -n "payouts" pools/closers.ts
magic values: none
22:  payouts: { schedule: 'weekly', hold_first: { tasks: 5, for: '7d' } },
payoutsPaid
left outtransferred every Friday, pay payable two days after the act
'same-day'each evening, once payable
'weekly'every Friday
{ schedule, hold_first: { tasks: 5, for: '7d' } }a new member's first five Tasks wait seven days, then the schedule
{ schedule, instant_fee: 'brand' | 'member' }at once when the member asks; you pay the fee unless it's 'member', and then it is Stripe's cost, shown before they choose

Pay in the Pool has each schedule's dates and the member's view of every act.

Each run carries a line per brand, so a member who works for three brands gets one deposit. Held share pay stays out of it until its window closes:

Call
→ GET /owner/pools/closers/payouts?week=2026-W47   # the owner: one week's run, Fri 20 Nov
200 · closers · week 47 · 63 closers paid · $21,480.00 · median 2.4 days from act to bank · magic values: none
  pyo_7Hq4   mbr_7Hq4   $900.00     4 gigs   setter $750.00 · nurturer $150.00
  pyo_7Hq9   mbr_7Hs1   $250.00     1 gig    setter, tsk_7Hs5, held 7 days: gig 2 of the first 5
  held       $7,400.00 · tsk_7Hw6 · the closer's share, to 12 Jan 2027 (outcome.window)

Every payout reconciles to the entries it paid, each to its job and its Stripe transfer, ending on the bank deposit:

Run
npx services.dev payouts reconcile pyo_7Hq4   # as mbr_7Hq4: from the bank deposit back to each job
magic values: none
pyo_7Hq4 · $900.00 to bank …1182 · arrived Fri 20 Nov 2026 16:41 · Stripe po_…7Hq4
  le_7Hr9p   +$250.00   setter · tsk_7Hr9 · tr_…Hr9, after py_…Hr9 debited api.forsale: a held meeting comes before any charge
  le_7Hr1p   +$250.00   setter · tsk_7Hr1 · tr_…Hr1, after py_…Hr1
  le_7Hr3p   +$250.00   setter · tsk_7Hr3 · tr_…Hr3, after py_…Hr3
  le_7Hr6p   +$150.00   nurturer · tsk_7Hr6 · tr_…Hr6, after py_…Hr6
  fees         $0.00    weekly schedule, no instant payout
  deposit    $900.00    bank …1182, 20 Nov · difference $0.00

Your own payouts reconcile the same way, with each transfer, the take and each debit as its own entry. GET /owner/payouts/:id/entries returns them, and npx services.dev jobs ledger --month 2026-11 --csv exports the month for your books.

A payout the bank returns comes back to the member's own balance, tells them with the cure, and goes out with the next payout; nothing is lost, and nothing is charged for the failure. An account Stripe restricts, waiting on a document or a tax ID, keeps accruing pay, shows pay.waiting with the cure in the delivery portal, and is paid once the account clears:

Call
→ GET /me/payouts   # as mbr_7Hs1, whose bank returned the payout
200 · mbr_7Hs1 · $250.00 in your balance · payout.failed 30 Nov: account_closed · magic values: none
  pay       back in your balance · nothing is lost, and nothing is charged for the failure
  cure      add a bank account in the delivery portal · it goes out with the next payout

Each member gives a tax ID at onboarding. Pay on your rail is reported under your brand, as its payments to the member, and a fee sold on the member's own rail is reported as the member's own sales. Each year's forms are in the delivery portal.

The time from an accepted act to the member's bank is measured, never claimed: the median and p90 per Pool, in Pool health and on the door's demand board, where members choose where to work.

captured/money-payouts.txt · 200 · magic values: none
→ GET /payouts/pyo_7Hq4   # as mbr_7Hq4
{
  "id": "pyo_7Hq4",
  "object": "payout",
  "member": "mbr_7Hq4",
  "amount": 90000,
  "currency": "usd",
EventAudienceSays
pay.accruedmember, ownerpay for an accepted act
pay.payablemember, ownerthe pay is due on the next payout
pay.waitingmember, ownerthe account can't be paid yet; the pay waits, with the cure
pay.paidmember, ownerthe pay transferred to the member's account, on the Pool's run, a line per brand
payout.paidmember, ownerthe account paid out to the bank
payout.failedmember, ownerthe bank returned the payout; it is back in the member's balance and goes out with the next one

Worked in: closing on closers.deals, one share from won to Friday's payout.

AppWhat it shows
Customer portalNothing: a buyer never sees how a member is paid
Delivery portalAccrued, held, payable and paid, the next payout's date, the account it lands in, each payout's entries and the year's tax forms
Owner consoleYour account's balance and payouts, each payout's entries, each Pool's next run, and its act-to-bank median
KeyWrittenLeft outDoes
Brand.payouts{ rail: 'stripe'; schedule?: 'same-day' | 'weekly' }rail: 'stripe', dailyYour account's rail, and how often it pays you
Pool.payouts{ at: 'act'; after?: Within } | 'same-day' | 'weekly' | { schedule; hold_first?; instant_fee? }Fridays, two days after the actWhen members' pay is payable and transferred

Paying yourself runs on every plan; a Pool's schedule and hold_first run live on Launch.