Pay Phone — Build Spec / Dev Handoff v1

Date: 07/17/2026 · Status: logic locked, ready to build · One-liner: People pay to call your phone.

A marketplace for scheduled, time-boxed 1:1 video calls between fans and verified talent ("celebs"). Fans pay per call; celebs set prices and hours; the platform is the switchboard and takes a cut. Web-first for every transaction, native app as the daily surface.


0. The locked stack

LayerChoiceWhy / notes
App (iOS + Android)Expo / React NativeSame toolchain as TextingParents; one codebase both platforms. Role decided by signed-in number, not by which app.
Web (site + booking + call + my-bookings)Static + a thin API~/personal-projects/pay-phone/site/ is the built reference. Book, pay, and take the call all work in-browser.
PaymentsStripe — Connect (Express) for talent payouts, PaymentIntents for bookingApple Pay is a payment METHOD on Stripe web checkout. NO Apple IAP anywhere. Apple's cut = $0.
Live videoLiveKitSame as TextingParents: rooms, egress→R2 recording, CallKit/PushKit for native call ring.
SMSTwilioJoin links, T-15 reminders, drops. The SMS channel is the growth loop — not optional.
Recording storageCloudflare R2LiveKit egress target; MP4/AAC (iOS can't play OGG).
ModerationHive AI (or Rekognition)Server bot participant samples frames; audio→text classifier.
IdentityPhone number = account, OTP via TwilioBoth sides. See §5.
Transactional emailResendE1–E6. From hello@joinpayphone.com.

Domain: joinpayphone.com (⚠️ registration unconfirmed — verify before deploy). Entity/Apple/Stripe/LiveKit/Twilio accounts: founder, same enrollment path as TextingParents.


1. The money rules (single source of truth)


2. Booking lifecycle state machine

                    ┌─ cancel ≥24h ──────────────► REFUNDED (100%, auto)
                    │
CREATED ─pay─► PAID ─┼─ cancel <24h ─► RESCHEDULE_CREDIT (one use, 30d; →REFUNDED if no slot)
(in-hours: auto)    │
(off-hours: see §2a)└─ hold ─► CONFIRMED ─remind(T-15)─► LOBBY ─both join─► IN_CALL
                                                              │
   IN_CALL ─┬─ completes ──────────────► COMPLETED ──► SPLIT_PAID
            ├─ +extension ─────────────► COMPLETED (base+ext one settlement)
            ├─ celeb no-show (+5:00) ──► REFUNDED (100%, auto) + pickup-rate hit
            ├─ fan no-show (window end)► COMPLETED (celeb paid in full)
            ├─ conduct kill ───────────► FORFEITED (fan pays, celeb paid, ban)
            ├─ report filed ───────────► PAYOUT_HELD → T&S review → REFUNDED | SPLIT_PAID
            └─ platform tech fault ────► REFUNDED (100%) + celeb paid (platform eats it)

No-show thresholds (D2): celeb no-show fires at +5:00 past start; fan no-show fires at the scheduled window end. Both printed in the cancel policy.

Fair timer (D2): protected from the OTHER party's lateness, never your own. Celeb late → timer waits until both in → fan gets full duration → later calls drift (buffers absorb). Fan late → clock runs, 60-sec grace, then they eat it; call still ends at scheduled end.

2a. Off-hours requests (D3)

Booking outside standing hours: authorize (not capture) → fan sees PENDING → celeb accepts within min(24h from request, 24h before slot) → capture + confirm. Expire/decline → release authorization, notify fan, $0.

2b. Partial call / tech failure (D5)


3. Scheduling (D1) — per-service grid


4. Recording &amp; retention (D6)


5. Identity — phone number = account

Number does five jobs: SMS delivery (the ring), zero-friction identity (no signup wall), celeb verification (OTP against the manager-registered number mints the ✓), ban anchor, and the web↔app bridge (book/claim on web → install app → type number → everything appears).


6. Trust &amp; Safety

Real-time frame sampling (Hive) + audio→text classifier on a server bot participant. High-confidence NSFW → blur/black + kill in seconds. Report (either side) → PAYOUT_HELD → human review with recording + transcript + join log + spender history → refund/forfeit/warn/ban (reason-coded). 2-hour SLA. Conduct kill: fan forfeits, celeb paid, ban. 18+ only (ToS); App Store rating 17+ (Apple's max); 18+ attestation at checkout.


7. The screens (each links to its approved mockup)

Celeb claim (all web until live): journey S1–S7d — invite text → claim → OTP verify → menu → hours+earnings hook → Stripe Connect → live + QR → App Store bridge → first open (zero re-entry).

Celeb app (4 tabs): app-proto-v2 — Today (next call + day plan) · Hours (weekly + menu + auto-accept) · Earnings (per-call payouts, dated sessions) · More (Audience export, Archive, payouts, settings, celeb recording consent).

Fan web booking: site/ — profile → per-service grid → contact → Apple Pay/card → confirmed → SMS → lobby → call → +5 extension → rate → recording.

Fan app: journey S24–S31 — two-door welcome → number → "your bookings appeared" → notifications → pick payphones → My Payphones home → Booked → You.

P1 (new): mockups/p1-screens — report/refund (R1–R3) + web my-bookings (B1–B4).

Admin: mockups/v4/admin — Today (KPIs+feed) · Lines/roster + drill-in · Trust&Safety case view.

Emails E1–E6: mockups/v4/emails — celeb live, celeb booking, fan confirm, T-15, recording ready, refund.

Design system: mockups/design-guide — tokens, type, icons (no emoji), copy law 7.1–7.4.


8. Build order (recommended)

  1. Foundations: phone-OTP auth, Stripe Connect onboarding, the booking state machine (§2) as a tested pure module (mirror the TextingParents ledger discipline — one DB, truth-layer tests recomputing every number a user sees).
  2. Celeb claim → live (web) so supply can be onboarded.
  3. Fan web booking → payment → confirmation. Real Stripe test-mode end to end.
  4. The call: LiveKit room, fair timer, recording egress, in-call report.
  5. Notifications: Twilio SMS (confirm, T-15, drops) + push.
  6. The apps (Expo) wrapping the above; My Payphones / Today.
  7. Admin + T&S queue.
  8. Emails (Resend), then the moderation layer (Hive) before any external talent.

Verification gate (per the founder's standing rule): every number a user sees gets a test recomputing it from the source store; drive each flow end-to-end and observe behavior, not just green tests; signed-in boot smoke on iOS sim + Android emulator before any build ships.


9. Open, non-code, founder-only blockers


10. Deferred to v1.1 (not in launch)

Paid membership / paid-follow (D7 — free follow at launch), sold-out waitlist, celeb-rates-fan, account-deletion self-serve, manager bulk-onboarding tooling, celeb archive bulk export.