{"openapi":"3.0.3","info":{"title":"Parity Open API","version":"0.2.0-local+stub","description":"Local shared-store API for consent-aware intents, agent quote submissions, waitlist, and SAMPLE agent seat entitlements and SAMPLE Stripe webhook stub (see SHARED_STORE.md). Partner marketplace search and health transparency remain `x-parity-status: unimplemented-stub`. Demo honesty: no live carrier bind APIs, no live MRF crawl.","contact":{"name":"Parity developers","url":"https://parity.demo/developers"},"license":{"name":"Demo / proprietary sample — not for production insurance sales"}},"servers":[{"url":"/api/v1","description":"This host — local shared-store routes implemented"},{"url":"https://parity.demo/api/v1","description":"Illustrative public host"}],"tags":[{"name":"Quotes","description":"Agent quote submissions via shared store (implemented-local). Partner /quotes/search remains a stub."},{"name":"Intents","description":"Opt-in shaped demand intents for agents — consent required (implemented-local)"},{"name":"Waitlist","description":"Growth / partner waitlist entries (implemented-local)"},{"name":"Entitlements","description":"SAMPLE agent/org seat entitlements stub (implemented-local). Not live Stripe — Insurance comparison checkout contract."},{"name":"Billing","description":"SAMPLE Stripe webhook stub (implemented-local). Grants entitlements with source stripe_sample — not live Stripe secrets or network."},{"name":"Admin","description":"Founder shared-store routes (implemented-local). Wave F: guarded by PARITY_ADMIN_TOKEN (bearer or /internal/login cookie); localhost stays open without a token."},{"name":"Health transparency","description":"Filed vs modeled facility / plan cost education (unimplemented stub)"},{"name":"Meta","description":"Spec and roadmap surfaces that do exist in the demo"}],"paths":{"/openapi.json":{"get":{"tags":["Meta"],"summary":"OpenAPI document (this file)","operationId":"getOpenApiDocument","x-parity-status":"implemented-static","responses":{"200":{"description":"OpenAPI 3.0 JSON","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/quotes/search":{"get":{"tags":["Quotes"],"summary":"Search illustrative marketplace quotes","description":"UNIMPLEMENTED STUB. Future: filter by ZIP, line (auto/home/life/…), and parity context. Will never rank by placement fee while hiding exposure regressions. For agent-submitted shared quotes on this host, use GET /quotes instead.","operationId":"searchQuotes","x-parity-status":"unimplemented-stub","parameters":[{"name":"zip","in":"query","schema":{"type":"string","pattern":"^[0-9]{5}$"},"description":"US ZIP (shaped demand scope)"},{"name":"line","in":"query","schema":{"type":"string","enum":["auto","home","life","umbrella","health","disability","pet","business","flood","earthquake","cyber"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}],"responses":{"501":{"description":"Not implemented — stub only in this demo","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StubError"}}}}}}},"/quotes":{"get":{"tags":["Quotes"],"summary":"List agent quote submissions (shared store)","description":"Implemented local shared-store list. Returns agent-submitted SAMPLE quotes with `dataMode: shared|demo`. Not live carrier APIs.","operationId":"listQuotes","x-parity-status":"implemented-local","responses":{"200":{"description":"Quote list with dataMode","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotesListResponse"}}}}}},"post":{"tags":["Quotes"],"summary":"Create agent quote submission (shared store)","description":"Implemented local shared-store create. Stores AgentQuoteSubmission — not a live bindable carrier quote.","operationId":"createQuote","x-parity-status":"implemented-local","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteCreate"}}}},"responses":{"201":{"description":"Created quote","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation error"}}}},"/intents":{"get":{"tags":["Intents"],"summary":"List anonymized opt-in intents (agent-facing)","description":"Implemented local shared-store. Returns ONLY intents with recorded consent (`shareWithAgents: true`). Agent-facing fields use anonymizedSummary. `dataMode: shared|demo`. Query `?demo=1` seeds demo intents when desired.","operationId":"listIntents","x-parity-status":"implemented-local","parameters":[{"name":"demo","in":"query","schema":{"type":"string","enum":["1"]},"description":"Force demo seed into shared store"},{"name":"metro","in":"query","schema":{"type":"string"},"description":"Metro / region filter (reserved)"},{"name":"minQuality","in":"query","schema":{"type":"number","minimum":0,"maximum":1}}],"responses":{"200":{"description":"Consented intents with dataMode","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntentsListResponse"}}}}}},"post":{"tags":["Intents"],"summary":"Create opt-in intent from household coverage work","description":"Implemented local shared-store. Requires consent object `{ shareWithAgents: true, capturedAt: ISO string, source: string }`. Without consent → 400. Never silent lead sale.","operationId":"createIntent","x-parity-status":"implemented-local","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntentCreate"}}}},"responses":{"200":{"description":"Deduped (Wave A): same normalized contact email/phone + type + ZIP within 24h → existing intent, `deduped: true`, header X-Parity-Deduped: 1. Nothing written.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntentCreateResponse"}}}},"201":{"description":"Created intent","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Missing/invalid consent or fields"}}}},"/intents/{id}":{"patch":{"tags":["Intents"],"summary":"Update intent status / lifecycle fields","description":"Implemented local shared-store PATCH for status (open|requested|contacted|declined|expired) and related fields.","operationId":"patchIntent","x-parity-status":"implemented-local","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntentPatch"}}}},"responses":{"200":{"description":"Updated intent"},"404":{"description":"Not found"}}},"get":{"tags":["Intents"],"summary":"Get one consented intent","operationId":"getIntent","x-parity-status":"implemented-local","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Agent-facing intent"},"404":{"description":"Not found or not consented"}}}},"/waitlist":{"get":{"tags":["Waitlist"],"summary":"Waitlist summary (shared store)","description":"Public callers get aggregate counts only (waitlist: []). Founder auth (PARITY_ADMIN_TOKEN bearer or session cookie) returns rows with masked emails (emailMasked); full addresses are never returned. A wrong bearer token returns 401.","operationId":"listWaitlist","x-parity-status":"implemented-local","responses":{"200":{"description":"Waitlist entries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistListResponse"}}}}}},"post":{"tags":["Waitlist"],"summary":"Append waitlist entry (shared store)","description":"Implemented local shared-store create for WaitlistEntry.","operationId":"createWaitlistEntry","x-parity-status":"implemented-local","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistCreate"}}}},"responses":{"201":{"description":"Created entry"},"400":{"description":"Validation error"}}}},"/entitlements":{"get":{"tags":["Entitlements"],"summary":"Lookup or list SAMPLE seat entitlements","description":"With ?id= or ?email= returns one record. Without query params, founder list with emails masked. SAMPLE stub only — not live Stripe.","operationId":"getEntitlements","x-parity-status":"implemented-local","parameters":[{"name":"id","in":"query","schema":{"type":"string"},"description":"Agent/org entitlement id"},{"name":"email","in":"query","schema":{"type":"string","format":"email"},"description":"Lookup by email (case-insensitive)"}],"responses":{"200":{"description":"Entitlement or masked list with honestyNote","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"No entitlement matched id/email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StubError"}}}}}},"post":{"tags":["Entitlements"],"summary":"Upsert SAMPLE stub entitlement grant","description":"Create or update an agent/org seat entitlement. Always labeled SAMPLE / not live Stripe. Contract for Insurance comparison seat checkout.","operationId":"upsertEntitlement","x-parity-status":"implemented-local","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitlementUpsert"}}}},"responses":{"200":{"description":"Updated entitlement","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitlementResponse"}}}},"201":{"description":"Created entitlement","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitlementResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StubError"}}}}}}},"/billing/stripe-webhook-stub":{"get":{"tags":["Billing"],"summary":"SAMPLE Stripe webhook stub docs","description":"Returns expected SAMPLE payload shape for checkout.session.completed. Not live Stripe — no secrets or api.stripe.com calls.","operationId":"getStripeWebhookStubDocs","x-parity-status":"implemented-local","responses":{"200":{"description":"Docs JSON with expectedPayload + example","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StripeWebhookStubDocs"}}}}}},"post":{"tags":["Billing"],"summary":"SAMPLE Stripe checkout.session.completed stub","description":"Accepts a simple SAMPLE payload and upserts an entitlement with source stripe_sample. Insurance comparison can point checkout completion here without editing /agents pages. Always labeled SAMPLE / not live Stripe.","operationId":"postStripeWebhookStub","x-parity-status":"implemented-local","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StripeWebhookStubBody"}}}},"responses":{"200":{"description":"Updated entitlement (SAMPLE grant)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StripeWebhookStubResponse"}}}},"201":{"description":"Created entitlement (SAMPLE grant)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StripeWebhookStubResponse"}}}},"400":{"description":"Missing/invalid fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StubError"}}}}}}},"/heartbeat":{"get":{"tags":["Admin"],"summary":"Shared-store heartbeat (path + counts)","description":"Implemented local. Returns ok, storePathRelative, counts, dataMode. No row payloads, emails, or secrets.","operationId":"sharedStoreHeartbeat","x-parity-status":"implemented-local","responses":{"200":{"description":"Heartbeat OK"},"503":{"description":"Store read failed"}}}},"/admin/export":{"get":{"tags":["Admin"],"summary":"Founder shared-store dump (counts + rows)","description":"Implemented local. Returns intents/quotes/waitlist counts and rows with honesty labels (demo|shared). Waitlist emails masked. No secrets. Not a live carrier feed.","operationId":"adminExportSharedStore","security":[{"ParityAdminBearer":[]},{"ParityAdminCookie":[]}],"x-parity-status":"implemented-local","responses":{"200":{"description":"Admin export JSON","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/admin/demand-pulse":{"get":{"tags":["Admin"],"summary":"Founder demand-pulse snapshot (counts only)","description":"Implemented local. Stable contract: asOf, dataMode, intents{open,claimed,declined,expired}, waitlist.bySource, quotes.count, topZips, honestyNote. claimed = requested+contacted. No PII/secrets. Not a live carrier feed.","operationId":"adminDemandPulse","security":[{"ParityAdminBearer":[]},{"ParityAdminCookie":[]}],"x-parity-status":"implemented-local","responses":{"200":{"description":"Demand-pulse JSON","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/admin/seed-demo":{"post":{"tags":["Admin"],"summary":"Seed labeled demo demand (intents/waitlist/quotes)","description":"Implemented local. Requires JSON body `{ confirm: true, force?: true }`. Seeds demo-seed intents, waitlist, and SAMPLE quotes for ops/pulse demos. dataMode is demo when only demo-labeled rows exist. Never invents live carrier money.","operationId":"adminSeedDemo","security":[{"ParityAdminBearer":[]},{"ParityAdminCookie":[]}],"x-parity-status":"implemented-local","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["confirm"],"properties":{"confirm":{"type":"boolean","example":true},"force":{"type":"boolean","description":"Replace store with demo pack only","example":true}}}}}},"responses":{"200":{"description":"Seed result with counts + dataMode"},"400":{"description":"confirm required"}}},"get":{"tags":["Admin"],"summary":"Seed labeled demo demand (confirm query)","description":"Implemented local. Requires `?confirm=1`; optional `force=1` replaces store with demo pack. Same honesty as POST — demo labels only, not live money.","operationId":"adminSeedDemoGet","security":[{"ParityAdminBearer":[]},{"ParityAdminCookie":[]}],"x-parity-status":"implemented-local","parameters":[{"name":"confirm","in":"query","required":true,"schema":{"type":"string","enum":["1","true","yes"]}},{"name":"force","in":"query","schema":{"type":"string","enum":["1","true","yes"]}}],"responses":{"200":{"description":"Seed result with counts + dataMode"},"400":{"description":"confirm required"}}}},"/admin/revenue":{"get":{"tags":["Admin"],"summary":"Founder seats / MRR snapshot","description":"Implemented local (Wave D). Live MRR counts only stripe_live + livemode + active entitlements, priced with the MODELED table. SAMPLE and Stripe test-mode figures are labeled modeled — not money. No emails or secrets.","operationId":"adminRevenue","x-parity-status":"implemented-local","security":[{"ParityAdminBearer":[]},{"ParityAdminCookie":[]}],"responses":{"200":{"description":"Revenue snapshot (header X-Parity-Live-Mrr-Usd)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevenueSnapshot"}}}},"401":{"description":"Admin token required (remote, token set)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAuthError"}}}},"503":{"description":"PARITY_ADMIN_TOKEN unset and request not local","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAuthError"}}}}}}},"/admin/integrity":{"get":{"tags":["Admin"],"summary":"Shared-store integrity report","description":"Implemented local (Wave E). Schema validation + duplicate/orphan detection. Ids only — no PII. 200 when no errors (warnings allowed), 503 when errors (header X-Parity-Integrity-Ok).","operationId":"adminIntegrity","x-parity-status":"implemented-local","security":[{"ParityAdminBearer":[]},{"ParityAdminCookie":[]}],"responses":{"200":{"description":"No integrity errors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrityReport"}}}},"401":{"description":"Admin token required (remote, token set)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAuthError"}}}},"503":{"description":"Integrity errors (IntegrityReport with ok:false) — or admin guard refusal (AdminAuthError) when the token is unset and the request is not local","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/IntegrityReport"},{"$ref":"#/components/schemas/AdminAuthError"}]}}}}}}},"/admin/session":{"get":{"tags":["Admin"],"summary":"Founder session status","description":"Wave F. Returns { tokenConfigured, authenticated, via }. Never returns the token. Exempt from the guard.","operationId":"adminSessionStatus","x-parity-status":"implemented-local","responses":{"200":{"description":"Session status","content":{"application/json":{"schema":{"type":"object","properties":{"tokenConfigured":{"type":"boolean"},"authenticated":{"type":"boolean"},"via":{"type":"string","nullable":true,"enum":["token","cookie","local-open"]},"login":{"type":"string","example":"/internal/login"}}}}}}}},"post":{"tags":["Admin"],"summary":"Founder sign-in / sign-out","description":"Wave F. Form or JSON `{ token, next }` → sets httpOnly SameSite=Strict signed cookie `parity_admin` (12h) and 303 to `next` (only /internal* or /api/v1/admin/*). `logout=1` clears it. JSON callers get JSON. Exempt from the guard.","operationId":"adminSession","x-parity-status":"implemented-local","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"token":{"type":"string"},"next":{"type":"string"},"logout":{"type":"string","enum":["1"]}}}},"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"next":{"type":"string"},"logout":{"type":"string","enum":["1","true"]}}}}}},"responses":{"200":{"description":"JSON sign-in/out OK (cookie set/cleared)"},"303":{"description":"Form sign-in/out redirect (cookie set/cleared; errors redirect to /internal/login?error=…)"},"401":{"description":"JSON: token mismatch"},"503":{"description":"JSON: PARITY_ADMIN_TOKEN not configured"}}}},"/billing/status":{"get":{"tags":["Billing"],"summary":"Billing mode (sample|live) + config presence booleans","description":"Implemented local (Wave C). mode is live only when STRIPE_WEBHOOK_SECRET is set. Returns booleans and counts — never secret values, price ids, or emails.","operationId":"getBillingStatus","x-parity-status":"implemented-local","responses":{"200":{"description":"Billing status (header X-Parity-Billing-Mode)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingStatus"}}}}}}},"/billing/stripe-webhook":{"get":{"tags":["Billing"],"summary":"Live Stripe webhook docs (enabled flag, handled events)","description":"Implemented local (Wave C). Never returns secrets.","operationId":"getStripeWebhookDocs","x-parity-status":"implemented-local","responses":{"200":{"description":"Docs JSON: endpoint, enabled, handledEvents, requires, planResolution, note"}}},"post":{"tags":["Billing"],"summary":"Signature-verified Stripe webhook (OFF unless STRIPE_WEBHOOK_SECRET is set)","description":"Implemented local (Wave C). Verifies `Stripe-Signature` (HMAC-SHA256 over `${t}.${rawBody}`, 300s tolerance). Handles checkout.session.completed, customer.subscription.created|updated|deleted → entitlements with source stripe_live. Idempotent on retries; out-of-order events never roll state back; unhandled events → 200 applied:false. Not behind the founder guard — protected by the Stripe signature.","operationId":"postStripeWebhook","x-parity-status":"implemented-local","parameters":[{"name":"Stripe-Signature","in":"header","required":true,"schema":{"type":"string","example":"t=1700000000,v1=<hex>"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Raw Stripe Event (signature computed over the exact bytes)"}}}},"responses":{"200":{"description":"Received — { received, applied, duplicateEvent?, staleEvent?, event, livemode?, entitlement? } or applied:false with reason"},"400":{"description":"missing_signature | malformed_signature | timestamp_out_of_tolerance | signature_mismatch | invalid_json"},"503":{"description":"stripe_live_disabled — STRIPE_WEBHOOK_SECRET not set (default)"}}}},"/health/transparency":{"get":{"tags":["Health transparency"],"summary":"Facility / procedure price points with provenance","description":"UNIMPLEMENTED STUB. Future: ZIP-scoped facility prices with mandatory `filed` | `modeled` provenance. Will not claim live hospital rates without ingest. See HEALTH_DATA.md and /app/health in the demo UI.","operationId":"getHealthTransparency","x-parity-status":"unimplemented-stub","parameters":[{"name":"zip","in":"query","schema":{"type":"string","pattern":"^[0-9]{5}$"}},{"name":"query","in":"query","schema":{"type":"string"},"description":"Drug / procedure name or code"},{"name":"provenance","in":"query","schema":{"type":"string","enum":["filed","modeled","any"],"default":"any"}}],"responses":{"501":{"description":"Not implemented — stub only in this demo","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StubError"}}}}}}}},"components":{"schemas":{"StubError":{"type":"object","required":["error","status","docs"],"properties":{"error":{"type":"string","example":"unimplemented_stub"},"status":{"type":"integer","example":501},"message":{"type":"string","example":"This Parity Open API path is documented but not implemented in the demo."},"docs":{"type":"string","example":"/api/v1"}}},"IntentShareConsent":{"type":"object","required":["shareWithAgents","capturedAt","source"],"properties":{"shareWithAgents":{"type":"boolean","enum":[true],"description":"Must be true — opt-in only"},"capturedAt":{"type":"string","format":"date-time","description":"ISO-8601 timestamp when consent was captured"},"source":{"type":"string","description":"Surface that captured consent (advisor, compare, api, …)"}}},"IntentCreate":{"type":"object","required":["zip","type","consent"],"properties":{"zip":{"type":"string","pattern":"^[0-9]{5}$"},"type":{"type":"string","description":"PolicyType or bundle"},"timeline":{"type":"string","enum":["ready_now","30_days","exploring"]},"parityGap":{"type":"number"},"budgetAnnual":{"type":"number"},"qualityScore":{"type":"number"},"anonymizedSummary":{"type":"string"},"householdSize":{"type":"integer","minimum":1},"exposureFlags":{"type":"array","items":{"type":"string"}},"consent":{"$ref":"#/components/schemas/IntentShareConsent"},"contact":{"$ref":"#/components/schemas/IntentContact"},"email":{"type":"string","format":"email","description":"Alias for contact.email (private; never agent-facing)"},"phone":{"type":"string","description":"Alias for contact.phone (private; normalized to 10–15 digits)"},"isDemo":{"type":"boolean","description":"Callers may set true; cannot force false (demo heuristic still applies)"}}},"IntentContact":{"type":"object","description":"Private contact (Wave A). Never returned to agents; POST echoes masked contactOnFile only. Malformed → 400 invalid_contact. Enables 24h dedupe.","properties":{"email":{"type":"string","format":"email"},"phone":{"type":"string","description":"10–15 digits after normalization; leading US 1 stripped"}}},"IntentCreateResponse":{"type":"object","properties":{"intent":{"type":"object","description":"Agent-facing intent (contact stripped; isDemo + actionable additive)"},"dataMode":{"type":"string","enum":["shared","demo"]},"deduped":{"type":"boolean"},"contactOnFile":{"type":"object","properties":{"emailMasked":{"type":"string"},"phoneMasked":{"type":"string"}}}}},"IntentPatch":{"type":"object","properties":{"status":{"type":"string","enum":["open","requested","contacted","declined","expired"]},"declineReason":{"type":"string"},"anonymizedSummary":{"type":"string"},"slaHours":{"type":"integer"}}},"IntentsListResponse":{"type":"object","required":["dataMode","intents","count"],"properties":{"dataMode":{"type":"string","enum":["shared","demo"]},"intents":{"type":"array","items":{"type":"object"}},"count":{"type":"integer"}}},"QuoteCreate":{"type":"object","required":["agentName","agency","carrier","type","annualPremium"],"properties":{"agentName":{"type":"string"},"agency":{"type":"string"},"carrier":{"type":"string"},"type":{"type":"string"},"annualPremium":{"type":"number"},"limits":{"type":"object"},"notes":{"type":"string"}}},"QuotesListResponse":{"type":"object","required":["dataMode","quotes","count"],"properties":{"dataMode":{"type":"string","enum":["shared","demo"]},"quotes":{"type":"array","items":{"type":"object"}},"count":{"type":"integer"},"note":{"type":"string"}}},"WaitlistCreate":{"type":"object","required":["name","email","source"],"properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"},"company":{"type":"string"},"role":{"type":"string"},"source":{"type":"string","enum":["employers","carriers","report","careers","partners","growth","agents"]},"notes":{"type":"string"},"partnerCode":{"type":"string"}}},"WaitlistListResponse":{"type":"object","required":["dataMode","waitlist","count"],"properties":{"dataMode":{"type":"string","enum":["shared","demo"]},"access":{"type":"string","enum":["public","founder"]},"waitlist":{"type":"array","description":"Empty for public callers. Founder rows mask emails (emailMasked).","items":{"type":"object"}},"count":{"type":"integer"},"bySource":{"type":"object","additionalProperties":{"type":"integer"}},"note":{"type":"string"}}},"EntitlementUpsert":{"type":"object","properties":{"id":{"type":"string","description":"Agent/org key (optional on create)"},"email":{"type":"string","format":"email"},"plan":{"type":"string","enum":["free","solo","agency","pro"]},"seats":{"type":"integer","minimum":1,"maximum":100},"source":{"type":"string","enum":["stub","stripe_sample"],"description":"Always SAMPLE — never live Stripe"}}},"EntitlementResponse":{"type":"object","required":["dataMode","entitlement","honestyNote","created","note"],"properties":{"dataMode":{"type":"string","enum":["shared","demo"]},"entitlement":{"type":"object"},"created":{"type":"boolean"},"honestyNote":{"type":"string"},"note":{"type":"string"}}},"StripeWebhookStubBody":{"type":"object","description":"SAMPLE checkout.session.completed payload (not a real Stripe Event)","required":["event","email","plan"],"properties":{"event":{"type":"string","enum":["checkout.session.completed"]},"email":{"type":"string","format":"email"},"plan":{"type":"string","enum":["solo","agency","pro"]},"seats":{"type":"integer","minimum":1},"sessionId":{"type":"string","example":"cs_test_sample_agency"}}},"StripeWebhookStubDocs":{"type":"object","properties":{"endpoint":{"type":"string","example":"/api/v1/billing/stripe-webhook-stub"},"methods":{"type":"array","items":{"type":"string"}},"sample":{"type":"boolean","enum":[true]},"notLiveStripe":{"type":"boolean","enum":[true]},"honestyNote":{"type":"string"},"expectedPayload":{"type":"object"},"example":{"$ref":"#/components/schemas/StripeWebhookStubBody"},"sourceOnGrant":{"type":"string","enum":["stripe_sample"]},"note":{"type":"string"}}},"StripeWebhookStubResponse":{"type":"object","required":["sample","notLiveStripe","event","dataMode","entitlement","created","honestyNote"],"properties":{"sample":{"type":"boolean","enum":[true]},"notLiveStripe":{"type":"boolean","enum":[true]},"event":{"type":"string","enum":["checkout.session.completed"]},"sessionId":{"type":"string"},"dataMode":{"type":"string","enum":["shared","demo"]},"entitlement":{"type":"object"},"created":{"type":"boolean"},"honestyNote":{"type":"string"},"note":{"type":"string"}}},"AdminAuthError":{"type":"object","required":["error","message"],"properties":{"error":{"type":"string","enum":["admin_auth_required","admin_token_unset_nonlocal","admin_token_too_short"]},"message":{"type":"string"},"login":{"type":"string","example":"/internal/login"}}},"BillingStatus":{"type":"object","required":["mode","liveWebhook","sampleStub","priceIdsConfigured","secretKeyMode","entitlements","honestyNote"],"properties":{"mode":{"type":"string","enum":["sample","live"]},"liveWebhook":{"type":"object","properties":{"endpoint":{"type":"string","example":"/api/v1/billing/stripe-webhook"},"enabled":{"type":"boolean"},"webhookSecretConfigured":{"type":"boolean"},"handledEvents":{"type":"array","items":{"type":"string"}}}},"sampleStub":{"type":"object","properties":{"endpoint":{"type":"string"},"enabled":{"type":"boolean"}}},"priceIdsConfigured":{"type":"object","properties":{"solo":{"type":"boolean"},"agency":{"type":"boolean"},"pro":{"type":"boolean"}}},"secretKeyMode":{"type":"string","nullable":true,"enum":["live","test","unknown"]},"entitlements":{"type":"object","properties":{"stripeLive":{"type":"integer"},"stripeLiveLivemode":{"type":"integer"},"stripeLiveTestmode":{"type":"integer"},"sample":{"type":"integer"}}},"honestyNote":{"type":"string"}}},"RevenueSnapshot":{"type":"object","required":["asOf","currency","mrr","liveEntitlementsExist","honestyNote"],"properties":{"asOf":{"type":"string","format":"date-time"},"currency":{"type":"string","enum":["usd"]},"priceTable":{"type":"object","description":"MODELED per-seat monthly prices"},"byPlan":{"type":"array","items":{"type":"object"}},"split":{"type":"object","description":"Totals per bucket: stripeLive | stripeTestMode | sample"},"mrr":{"type":"object","properties":{"liveUsd":{"type":"number","description":"Real money only (stripe_live + livemode + active)"},"stripeTestModeUsd":{"type":"number","description":"MODELED — not money"},"modeledSampleUsd":{"type":"number","description":"MODELED SAMPLE — not money"}}},"liveEntitlementsExist":{"type":"boolean"},"canceledLive":{"type":"integer"},"honestyNote":{"type":"string"}}},"IntegrityReport":{"type":"object","required":["ok","checkedAt","storeKind","counts","summary","issues"],"properties":{"ok":{"type":"boolean"},"checkedAt":{"type":"string","format":"date-time"},"storeKind":{"type":"string","enum":["json","sqlite"]},"counts":{"type":"object","additionalProperties":{"type":"integer"}},"summary":{"type":"object","properties":{"errors":{"type":"integer"},"warnings":{"type":"integer"}}},"issues":{"type":"array","items":{"type":"object","description":"Ids only — severity error|warning, code, collection, ids/message"}},"note":{"type":"string"}}}},"securitySchemes":{"ParityAdminBearer":{"type":"http","scheme":"bearer","description":"Wave F founder guard for /admin/* and /internal/*: `Authorization: Bearer <PARITY_ADMIN_TOKEN>`. Localhost is open when PARITY_ADMIN_LOCAL_OPEN is not 0; remote requests get 503 when the token is unset."},"ParityAdminCookie":{"type":"apiKey","in":"cookie","name":"parity_admin","description":"Signed 12h session cookie set by POST /admin/session (/internal/login)."},"PartnerApiKey":{"type":"apiKey","in":"header","name":"X-Parity-Key","description":"Reserved for a future partner key. Not issued and not validated in this demo."}}},"x-parity-demo":{"implementedInUi":["/app/shop","/agents/inbox","/app/health","/developers","/api/v1"],"implementedLocalApi":["GET|POST /api/v1/intents","PATCH|GET /api/v1/intents/{id}","GET|POST /api/v1/quotes","GET|POST /api/v1/waitlist","GET|POST /api/v1/entitlements","GET /api/v1/admin/export","GET /api/v1/admin/demand-pulse","POST|GET /api/v1/admin/seed-demo","GET /api/v1/heartbeat","GET /api/v1/admin/revenue","GET /api/v1/admin/integrity","GET|POST /api/v1/admin/session","GET /api/v1/billing/status","GET|POST /api/v1/billing/stripe-webhook","GET|POST /api/v1/billing/stripe-webhook-stub"],"sharedStore":"data/shared-store.json","nextMilestones":["Origin hosted product","Live MRF ingest (labeled filed vs modeled)","Auth + consumer-controlled sync","Licensed agent verification","Implement partner Open API behind consent and rate limits"]}}