{"openapi":"3.1.0","info":{"title":"Silicon Zombies API","version":"v1","description":"Shared REST contract for the web platform and Flutter clients. VIP access is enforced server-side."},"servers":[{"url":"https://zombies.necodex.dev/api/v1","description":"Preview"}],"tags":[{"name":"Auth"},{"name":"Home"},{"name":"Content"},{"name":"Events"},{"name":"Community"},{"name":"Live"},{"name":"Podcast"},{"name":"Notifications"},{"name":"Billing"},{"name":"Admin"},{"name":"Webhooks"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"opaque session token"}},"schemas":{"SuccessEnvelope":{"type":"object","required":["data"],"properties":{"data":{},"requestId":{"type":"string"}}},"ErrorEnvelope":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{},"requestId":{"type":"string"}}}}}},"responses":{"ApiError":{"description":"Safe error envelope: { error: { code, message, details?, requestId? } }.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"UpsellRequired":{"description":"VIP membership required; response includes an upsell payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Unauthorized":{"description":"Authentication required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Forbidden":{"description":"Insufficient permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"ValidationError":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"paths":{"/health":{"get":{"tags":["Auth"],"summary":"Service health","responses":{"200":{"description":"Healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}}}},"/auth/login":{"post":{"tags":["Auth"],"summary":"Create an opaque session from email and password","responses":{"201":{"description":"{ data: { token, expiresAt, actor } }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"401":{"description":"Invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/auth/register":{"post":{"tags":["Auth"],"summary":"Create a Human account and opaque session","responses":{"201":{"description":"{ data: { token, expiresAt, actor } }","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"409":{"description":"Email already registered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/auth/session":{"post":{"summary":"Rotate the current opaque session","security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Session created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/me":{"get":{"summary":"Get the current member profile and membership state","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Member profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/home":{"get":{"tags":["Home"],"summary":"Public home composition; optional bearer token personalizes locks and RSVP state","responses":{"200":{"description":"Live status, event cards, catalogue and public community posts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}}}},"/content":{"get":{"tags":["Content"],"summary":"List published content; access is the entitlement source of truth and tags are descriptive metadata","responses":{"200":{"description":"Published content array with access: free|vip, tags, and locked state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}}}},"/content/{id}/stream":{"get":{"summary":"Get a short-lived audio URL; shared preview redirects to a generated WAV fixture when PREVIEW_MODE=true","security":[{"bearerAuth":[]}],"responses":{"302":{"description":"Redirect to signed media or a preview URL. The response has a Location header and no JSON body."},"403":{"description":"VIP upsell required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Content not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/vip/apply":{"post":{"tags":["Auth"],"summary":"Submit a Zombie VIP application","responses":{"201":{"description":"Application created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/events":{"get":{"tags":["Events"],"summary":"List events with optional tier-aware booking availability","responses":{"200":{"description":"Public events with VIP-first booking state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}}}},"/events/{id}/rsvp":{"post":{"summary":"Create an RSVP or waitlist entry","security":[{"bearerAuth":[]}],"responses":{"201":{"description":"RSVP created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"403":{"description":"VIP-first window active","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/spaces":{"get":{"tags":["Community"],"summary":"List community spaces, including VIP locks","responses":{"200":{"description":"Public spaces and locked VIP-space metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}}}},"/spaces/{id}/messages":{"get":{"summary":"List messages in a space","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}}},"post":{"summary":"Post to a space; requires Zombie VIP","security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Message created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"403":{"description":"VIP upsell required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/live":{"get":{"tags":["Live"],"summary":"Get current live-stream state with optional VIP lock metadata","responses":{"200":{"description":"Public live state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}}}},"/podcast":{"get":{"tags":["Podcast"],"summary":"Get local Spotify-shaped preview show metadata; replace with a provider adapter when configured","responses":{"200":{"description":"Preview podcast show and episode mapping","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}}}},"/preview/luma/events":{"get":{"tags":["Events"],"summary":"Get secret-free normalized Luma preview sync data","responses":{"200":{"description":"Preview-only Luma adapter payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}}}},"/live/{id}/chat-ticket":{"post":{"summary":"Create a five-minute VIP ticket for the API Gateway WebSocket chat; shared preview returns a clearly marked non-connectable ticket","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"WebSocket URL and chat ticket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"403":{"description":"VIP membership required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"Live chat not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/preview/audio":{"get":{"tags":["Content"],"summary":"Shared-preview generated audio fixture. It exists only when PREVIEW_MODE=true and is the redirect target of an authorized stream request.","responses":{"200":{"description":"audio/wav fixture"},"404":{"description":"Preview mode disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/notifications":{"get":{"summary":"List the current member's notifications","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}}}},"/notifications/{id}/read":{"post":{"summary":"Mark one notification read","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}}}},"/push-tokens":{"post":{"summary":"Register an Expo device token","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}}},"delete":{"summary":"Remove an Expo device token","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}}}},"/billing/status":{"get":{"summary":"Get server-authoritative subscription status","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Membership and latest subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}},"tags":["Billing"]}},"/billing/checkout":{"post":{"summary":"Create a hosted Stripe Checkout session after VIP approval","security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Checkout URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"403":{"description":"VIP approval required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"tags":["Billing"]}},"/billing/mobile-payment-sheet":{"post":{"summary":"Create an Android or eligible iOS PaymentSheet subscription flow","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Existing incomplete PaymentSheet subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"201":{"description":"PaymentSheet parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"403":{"description":"VIP approval or iOS external billing disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"tags":["Billing"]}},"/billing/portal":{"post":{"summary":"Create a Stripe customer-portal session","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Portal URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"404":{"description":"No manageable subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"tags":["Billing"]}},"/admin/content":{"post":{"summary":"Create or update content","security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Content saved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"403":{"description":"Editor permission required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"tags":["Admin"]}},"/admin/applications":{"get":{"summary":"List VIP applications","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}},"tags":["Admin"]}},"/admin/applications/{id}/approve":{"post":{"summary":"Approve an application and create Stripe Checkout","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}},"tags":["Admin"]}},"/admin/applications/{id}/reject":{"post":{"summary":"Reject an application","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}},"tags":["Admin"]}},"/admin/events/{id}/checkin":{"post":{"summary":"Check in an attendee or promote a waitlisted RSVP","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}},"tags":["Admin"]}},"/admin/messages/{id}":{"delete":{"summary":"Remove a message","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}},"tags":["Admin"]},"patch":{"summary":"Pin or unpin a message","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}},"tags":["Admin"]}},"/admin/reports":{"get":{"summary":"List moderation reports","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}},"tags":["Admin"]},"patch":{"summary":"Resolve a report","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}},"tags":["Admin"]}},"/admin/live/start":{"post":{"summary":"Mark a YouTube stream live","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}},"tags":["Admin"]}},"/admin/live/end":{"post":{"summary":"End a live stream","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}},"tags":["Admin"]}},"/admin/live/{id}/sync":{"post":{"summary":"Synchronize live status and viewers from YouTube","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}},"tags":["Admin"]}},"/admin/metrics":{"get":{"summary":"Get revenue, subscription, and retention metrics","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}},"tags":["Admin"]}},"/admin/integrations":{"get":{"summary":"Get secret-free external integration readiness","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}}},"tags":["Admin"]}},"/webhooks/stripe":{"post":{"tags":["Webhooks"],"summary":"Receive verified Stripe events","responses":{"204":{"description":"Accepted"},"400":{"description":"Invalid signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/webhooks/luma":{"post":{"tags":["Webhooks"],"summary":"Receive Luma events after configured signature verification","responses":{"204":{"description":"Accepted"},"400":{"description":"Invalid signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"Webhook verification not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}}}}