Outcomes

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

Pricing on results, as one operating contract. The win rate a price breaks even at, who funds the work before the end, the proof that confirms the amount, how the money is collected, the window that holds it, what reverses it, and the tail that keeps a lost deal watched.

Outcome pricing pays you on results, never on a claim. The outcome names an amount, who proves it, how it's collected and how long it stays held.

Two lines on api.forsale's deal: the outcome and its proof, then a price that charges nothing on effort:

Run
grep -n -A1 "outcome:\|price:" services/deal.ts
magic values: none
49:  outcome: { amount: 'closed_value', proof: 'payment', match: { customer: 'account', metadata: 'deal' },
50-    window: { bank: '60d', card: '120d' }, tail: '90d', due: '90d', collect: job => (job.output.billing === 'monthly' ? 'each' : 'first') },
51:  price: { usd: 0, share: '5%', of: 'closed_value', on: 'won', ai: 40,
52-    lines: { referral: { share: '1%', of: 'closed_value', to: 'referrer', on: 'won' } } },

check reads it back, down to the win rate it breaks even at:

Run
npx services.dev check services/deal.ts
magic values: none
services/deal.ts · 42 lines · nothing on effort; 5% of closed_value at won, proven by the account's payment, held 60 days by bank, 120 by card.
  outcome proof payment, read through services.dev's Stripe app on the seller's account · matched on the account's customer and metadata.deal · collect first, or each invoice when billing is monthly · due 90d · window 60d by bank, 120d by card, from each collection · tail 90d
  after   the window, a reversal of in_… is the seller's · the closer waits with the 5%
  hold    mandate · the seller's bank account or card, saved at the order up to max_usd · nothing held before won
  ai      $40.00 a deal, funded by api.forsale, won or lost · then ask
  ledger  +$11,100.00 at won on $74,000 · closer $7,400.00 (share, from the seller) · setter $250.00 · placement $50.00 · AI $11.34 (example) · you $3,388.66
  lost    +$0.00 · setter $250.00 when the meeting was held · placement $50.00, the setter's gig and the closer's · AI up to $40.00 · you −$340.00 when a closer loses it
  odds    a deal a closer loses costs $340.00, a won one leaves $3,388.66 · breaks even at 9.1% won (about 1 in 11)

Under the seller's humans_from, AI closes alone, and the whole share is yours:

Call
→ GET /owner/deals/job_7Hq1   # won by AI alone
200 · job_7Hq1 · deal · won · $1,500.00 charged, held to 2026-12-19 · magic values: none
  close     ai · committed · closed_value $30,000.00 · under humans_from, so no closer
  proof     payment · in_…5520 on the seller's Stripe account · $30,000.00 paid 20 Oct 2026
  ledger    +$1,500.00 · AI $9.12 of $40.00 · no person, no placement · you $1,490.88 before the take
  take      on $1,500.00, the whole share

From $50,000, a closer takes it, and their 10% is charged to the seller beside your 5%:

Call
→ GET /owner/deals/job_7Hq5   # won by a closer, and proven
200 · job_7Hq5 · deal · won · $11,100.00 charged, held to 2027-03-09 · magic values: none
  close     person · closer · mbr_7Hq4 · committed · closed_value $74,000.00
  proof     payment · in_…8841, the seller's own invoice, matched on the account's customer and metadata.deal · $74,000.00 paid 4 Jan 2027, net 30 from the close on 4 Dec
  outcome   verified · $74,000.00 · window 60d from the collection · closes 9 Mar 2027
  money     outcome.verified → chg_7Hq5 $11,100.00 debited off-session on the seller's bank mandate → charge.pending 4 Jan → charge.collected 8 Jan → held under job_7Hq5
  ledger    +$11,100.00 · closer $7,400.00 (share, from the seller) · setter $250.00 · placement $50.00 · AI $11.34 of $40.00 · you $3,388.66 before the take
  held      the 5% $3,700.00, the closer's $7,400.00 and the take, until the window closes

On deal.ts you fund the $340 a lost deal costs, which the break-even rests on. If the seller funds the setter instead, the deal breaks even at 2.4%, and check fails effort_charged until price.effort: 'named' puts that charge first in the OFFER. Pay runs both.

outcome.proof names who confirms the amount. Every surface labels a verified outcome apart from a self-reported one:

proofConfirmed byLabelled
'payment'a payment on the buyer's own Stripe account, read at the orderverified
'signature'the counterparty's signature on the outcomeverified
'counterparty'the counterparty's confirmation through its own askverified
'receipt'an outside system's receipt that carries the amountverified
'self', or left outyour code's job.outcome({ amount, evidence })self-reported

'payment' reads the buyer's Stripe account through services.dev's Stripe app, installed at the order. It watches that payment through the window, so its refund or dispute fires outcome.reversed by itself. A payment outside Stripe proves by 'receipt' or 'counterparty'.

A self-reported amount never sets anyone's money alone. The buyer sees it with its evidence and can contest it inside the window, and a contested amount stays held until a credentialed peer rules. No share pay rests on 'self':

Call
→ GET /owner/jobs/job_7Hq2   # claim-appeal: an outcome your code reports
200 · job_7Hq2 · claim-appeal · delivered · $300.00 charged · magic values: none
  outcome   self-reported 9 Nov 2026 · $1,200.00 · job.outcome() with payment-notice.pdf
  contest   open to the buyer until 9 Dec 2026 · none filed
  ledger    +$99.00 at delivery · +$201.00 at outcome · AI $0.84 · you $299.16

outcome.match ties one payment to one job: it comes from the customer party and carries the job's id under metadata. The end step commits an invoice drafted that way on the buyer's account, api.forsale's pay_link, so no other sale counts.

outcome.due bounds the wait, 90 days unless set; past it, outcome.lapsed ends the outcome with nothing charged. A party that already pays the buyer answers 409 account_is_customer, whose next orders with expansion: true: the share is of what the account adds. The sales money runs it.

At outcome.verified, the share and every pay charged from: 'buyer' are collected on the buyer's mandate, one charge per seller, and held under the job. For an amount paid over time, outcome.collect times the cash; price.on stays the end:

collectCharged
'first', the defaultthe whole share, at the first payment
'each'each payment's part, each held for its own window
'full'the whole share, once the amount is paid in full
Call
→ GET /owner/deals/job_7Ht1   # collect 'each': a $74,000.00 contract paid monthly
200 · job_7Ht1 · deal · won · 3 of 12 invoices paid · $2,775.00 charged · magic values: none
  proof     payment · in_…T101 to in_…T112 on the seller's Stripe account, matched on the subscription
  each      $6,166.67 paid → $925.00 charged: the 5% $308.33 and the closer's $616.67, each held 60 days from its own payment
  held      $2,775.00 · final 11 Jan, 10 Feb and 12 Mar 2027 · 9 invoices to come
  ledger    each invoice +$925.00 · closer $616.67 · you $308.33 before the take · the first also carries the setter's $250.00, placement $50.00 and AI $11.34 · you $3,388.66 over the 12

A declined collection retries under Brand.dunning. If it stays unpaid: the buyer's next orders answer 402, flat pay stands, a share charged to the buyer is still the member's at outcome.final, and the loss is yours, with no take on it:

Call
→ GET /owner/deals/job_7Hs8   # won; the first collection was declined
200 · job_7Hs8 · deal · won · $9,300.00 collected on day 3, held to 2027-01-17 · magic values: none
  18 Nov    outcome.verified · chg_7Hs8 card declined, insufficient_funds · charge.failed
  19 Nov    ask_7Hs8 to the seller: update the card · Stripe retries on 19 and 20 Nov
  21 Nov    collected on the new card · charge.collected $9,300.00 · held under job_7Hs8
  unpaid    had the retries failed: outcome.unpaid on 2 Dec (Brand.dunning, 14 days) · the closer's $6,200.00 still theirs at outcome.final · the loss yours, with no take on it · the seller's next orders answer 402

outcome.window holds what depends on the outcome until it closes: your share, any share pay, and services.dev's take on them. Its default is the horizon of the money behind the proof, and check fails window_too_long on a window past it:

ProofWindow, unless setThe horizon it follows
A card payment'120d'how long a cardholder can dispute it
A bank payment'60d'how long a debit can be returned
A signature'30d'the counterparty's time to rescind
A receipt'7d'as any charge
Self-reported'30d'the buyer's time to contest

window: { bank: '60d', card: '120d' } holds each payment for its own horizon. After the window, a reversal is the buyer's to carry. A member sees the window on the teaser before they claim:

Call
→ GET /me/earnings/tsk_7Hq5   # as mbr_7Hq4, the closer, on closers.deals
200 · tsk_7Hq5 · api.forsale · closer · close · $7,400.00 · held · magic values: none
  committed Fri 4 Dec 14:02     won, awaiting the payment      deal.ended         $0.00
  proven    Mon 4 Jan 09:20     won, proven by the payment     outcome.verified   $0.00
  held      Fri 8 Jan 09:00     the seller's debit collected   charge.collected   $7,400.00
  accrues   Tue 9 Mar 2027      when the 60-day window closes  pay.accrued
  payable   Thu 11 Mar 2027     two days after                 pay.payable
  paid      Fri 12 Mar 2027     weekly, on the Pool's schedule

At the window's close, the money is final and held pay accrues:

Call
→ GET /owner/deals/job_7Hq5   # 9 Mar 2027: the window closed
200 · job_7Hq5 · deal · won · $11,100.00 · final · magic values: none
  money     outcome.final → charge.earned $11,100.00 → pay.accrued $7,400.00
  ledger    +$11,100.00 · closer $7,400.00 · setter $250.00 · placement $50.00 · AI $11.34 · you $3,388.66 before the take

Held money moves your cash, not your margin. api.forsale's November pays its setters now and its 5% in January:

captured/money-ledger.txt · magic values: none
$ npx services.dev jobs ledger --month 2026-11 --held   # api.forsale: paid on the close
api.forsale · November 2026 · 21 deals ended · 3 won, 18 lost
  collected     +$33,300.00   3 won deals: the 5% $11,100.00 and the closers' $22,200.00, by bank debit
  held          −$33,300.00   all of it, under each deal's job, final 12 Jan to 28 Jan 2027
  processing       −$15.00   $5.00 a bank debit
  pay            −$5,000.00   setters and nurturers, flat, won or lost
  placement        −$625.00   25 filled gigs on closers.deals

Held share pay reverses for one cause only: the outcome's own money going back inside the window, recorded as outcome.reversed:

Call
→ GET /owner/deals/job_7Hw6   # another won deal: its payment was refunded inside the window
200 · job_7Hw6 · deal · won · reversed · $0.00 kept · magic values: none
  proof     payment · in_…9310 refunded 3 Dec 2026, day 20 of 60
  money     outcome.reversed → chg_7Hw6 refunded $11,100.00 from the hold → the closer's $7,400.00 never left it
  ledger    +$0.00 · setter $250.00, paid at the held meeting · placement $50.00 · AI $12.02 · you −$312.02
  take      reversed with the share
What happensYour shareHeld share payservices.dev's takeFlat pay, placement
The outcome's money goes back inside the windowrefunded to the buyerreverses: it was held, never paidreversesstands
Part of it goes back inside the windowadjusts pro rata, outcome.adjustedadjusts pro rataadjustsstands
Your goodwill refund of the sharerefundedstands, and accrues at outcome.finalreversesstands
A dispute on another of your chargesnothing movesnothing movesnothing movesstands
A reversal after the windowfinalthe member'sfinalstands

A referral share moves with yours, and flat pay is never clawed back. A partial refund moves every share line by one fraction:

Call
→ GET /owner/deals/job_7Hs2   # won; the seller's customer was refunded $18,500.00 on day 31
200 · job_7Hs2 · deal · won · adjusted · $8,325.00 kept of $11,100.00 · magic values: none
  proof     payment · in_…2207 partly refunded 14 Dec 2026, day 31 of 60 · $74,000.00 → $55,500.00
  money     outcome.adjusted → chg_7Hs2 refunded $2,775.00 to the seller, pro rata
  lines     the 5% $3,700.00 → $2,775.00 · the closer's $7,400.00 → $5,550.00, still held · the take on $2,475.00
  stands    the setter's $250.00 and placement $50.00
  ledger    +$8,325.00 · closer $5,550.00 · setter $250.00 · placement $50.00 · AI $11.34 · you $2,463.66 before the take

outcome.tail keeps a lost or withdrawn deal watched, 90 days unless set, so no one marks it lost and closes it around you. A payment from that account inside the tail verifies it won and pays the roles that worked it. A revival mints a new deal with its lineage and never charges twice:

Call
→ GET /owner/deals/job_7Hw7   # marked lost 2 Dec; the account paid on 19 Dec
200 · job_7Hw7 · deal · won by the tail · $9,300.00 charged, held to 2027-02-17 · magic values: none
  ended     lost on 2 Dec 2026, by the seller · watched for 90 days (outcome.tail)
  proof     payment · in_…3391 from Contoso Logistics, on the seller's Stripe account · $62,000.00 paid 19 Dec 2026
  outcome   verified by the tail · lost → won · the same deal, charged once
  pay       closer mbr_7Hq4, whose gig worked it · $6,200.00, held 60 days
  ledger    +$9,300.00 · closer $6,200.00 · setter $250.00 · placement $50.00 · AI $14.20 · you $2,785.80 before the take
captured/money-outcomes.txt · 200 · magic values: none
→ GET /owner/deals/job_7Hq5/outcome
{
  "object": "outcome",
  "job": "job_7Hq5",
  "amount": { "field": "closed_value", "amount": 7400000, "currency": "usd" },
  "proof": { "by": "payment", "ref": "in_…8841", "match": { "metadata": { "deal": "job_7Hq5" } }, "verified": true, "at": "2027-01-04T09:20:05Z" },
  "collect": "first",
EventWhen
outcome.reportedyour code reported an amount: self-reported
outcome.verifiedthe proof confirmed the amount; the share is collected and held
outcome.contestedthe buyer contested a self-reported amount; it stays held until a peer rules
outcome.adjustedpart of the money behind it went back; each share line moved pro rata
outcome.unpaidthe collection stayed declined when dunning ran out
outcome.lapsedno matching payment came by outcome.due; nothing is charged
outcome.finalthe window closed; held money is final and held pay accrues
outcome.reversedthe money behind it went back inside the window
AppWhat it shows
Customer portalThe amount, its proof, the share charged, the date it's final, and the contest, open until the window closes on a self-reported amount
Delivery portalA share as held, with its window's end, before the claim and after it, and the flat pay already paid
Owner consoleHeld outcome money by the date it's final, the live win rate against the break-even, and every reversal with its cause
KeyWrittenLeft outDoes
outcome.amounta money outputthe price's ofThe amount the share is of
outcome.proof'payment' | 'signature' | 'counterparty' | 'receipt' | 'self''self'Who confirms it
outcome.match{ customer?: <party input>; metadata?: string; invoice? }the job's id under metadata.<your word for job>How a payment proof finds its payment
outcome.dueWithin'90d'How long after the end the payment may come before the outcome lapses
outcome.collect'first' | 'each' | 'full''first'When the share is charged on money paid over time
outcome.windowWithin | { card?; bank? }the proof's horizonHow long outcome money stays held, from the charge's collection
outcome.contest'buyer' | false'buyer' on 'self'Who can contest a self-reported amount inside the window
outcome.tailWithin'90d'How long a lost or withdrawn deal stays watched for its payment
price.share, price.of, price.onPct, a money output, an endnoneThe share, of what, at which end
input.expansion'boolean?', declared on the ServicenoneTakes the share on what a party that already pays adds
price.usdnumberrequiredCharged at delivery and counted toward the share; 0 is nothing on effort
price.ainumber | { usd; then }a fifth of usdThe AI you fund per job: needed when usd is 0
CodeWhen
ai_unfundedcheck: usd: 0 and no ai budget
effort_chargedcheck: a usd: 0 price charges the buyer before its end, unnamed
share_pay_unverifiedcheck: share pay rests on a self-reported amount
window_too_longcheck: a window longer than its proof's horizon
tail_unprovencheck: a tail with a proof other than payment, signature or receipt
account_is_customer409 on an order: the party already pays the buyer; next offers expansion: true
proof_unconnecteddeploy --live: a payment proof whose buyer hasn't installed services.dev's Stripe app
win_rate_unmetcheck, under margin: 'strict': the last 30 days won less often than the break-even
fee_policycheck: a share your brand's fee policy forbids

Outcome prices and flat pay at an end run live on Launch, and share pay, which scales with the deal, on Team. A share charges at most the buyer's max_usd.