Payments

Stripe Connect is the payment boundary; full payout operations are still later-scope.

OpenDoc currently owns transaction state and PaymentIntent creation at the protocol boundary. Real provider payouts, refunds, disputes, and provider ledger reporting are intentionally documented as remaining work.

Current railStripe PaymentIntent
Provider entitySCP
Proof modetest/non-live

Current boundary

Accepting terms creates or returns the payment boundary.

For Transaction 1, POST /transactions/:id/accept-terms creates or returns the payment boundary. POST /transactions/:id/commit requires that boundary to allow commit.

payment_authorizedLive Stripe status requires_capture; commit allowed for manual-capture flow.
payment_succeededLive Stripe status succeeded; commit allowed.
non_live_authorizedControlled non-live proof mode only when explicitly enabled.
payment_pendingRequires payment action, confirmation, method, or processing; commit blocked.

Connect

Money flows to the Service Counterparty.

The Service Counterparty (SCP) is the legal/financial entity that receives funds. A solo provider may have a 1:1 SCP; a group practice usually has one SCP with many providers. OpenDoc care is delivered by providers, but deposits go to SCPs.

// Server-side only. Do not create Stripe PaymentIntents in partner browser code.
const intent = await stripe.paymentIntents.create({
  amount: booking.cashPriceCents,
  currency: booking.currency,
  payment_method_types: ["card"],
  application_fee_amount: applicationFeeCents,
  transfer_data: { destination: scp.stripeConnectAccountId },
  capture_method: "manual",
}, {
  idempotencyKey: `transaction1:${booking.id}:payment_intent:v1`,
});
Marketplace is not payment authority. Partner and marketplace UIs are protocol clients. The protocol owns payment boundary state, idempotency, audit, and commit permission.

Configuration

Stripe proof requires server-side secrets and a connected account.

Stripe test-mode proof is only valid when the protocol runtime has a Stripe test secret, the SCP is seeded with a test connected account, and non-live payment mode is disabled.

STRIPE_SECRET_KEY=sk_test_REPLACE_ME
STRIPE_WEBHOOK_SECRET=whsec_REPLACE_ME
OPENDOC_SEED_SCP_STRIPE_CONNECT_ACCOUNT_ID=acct_REPLACE_ME_TEST_CONNECTED
TRANSACTION1_NONLIVE_PAYMENT_ENABLED=false

Remaining work

Do not describe payout operations as finished yet.

Live Connect ownershipValidate Stripe/Connect production ownership, keys, onboarding, and connected-account custody.
Capture/releaseProve manual capture after proof of service and define settlement timing.
Webhook orderingValidate Stripe webhook ordering and payment-state readback before commit/release.
Provider ledgerBuild provider-facing payout ledger, refunds, disputes, accounting exports, and revenue reporting after the first payment spine.