{"openapi":"3.1.0","info":{"title":"Creed API","description":"Creed API - Christian AI Chatbot","version":"1.0.0"},"paths":{"/":{"get":{"tags":["health"],"summary":"Hello World","operationId":"hello_world__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"tags":["health"],"summary":"Health Check","description":"Health check endpoint for monitoring and load balancers","operationId":"health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health/sse-canary":{"get":{"tags":["health"],"summary":"Sse Canary","description":"Diagnostic SSE stream to verify the ingress path (DO App Platform edge)\ndelivers Server-Sent Events incrementally instead of buffering or killing\nlong-lived responses. Each event carries the server-side elapsed time so a\nclient can compare emission time vs arrival time and spot buffering.\n\nTest with: curl -N -H \"x-api-key: <admin key>\" \"https://api.usecreed.com/health/sse-canary\"","operationId":"sse_canary_health_sse_canary_get","parameters":[{"name":"duration_s","in":"query","required":false,"schema":{"type":"integer","maximum":300,"minimum":1,"description":"How long to keep the stream open","default":120,"title":"Duration S"},"description":"How long to keep the stream open"},{"name":"interval_s","in":"query","required":false,"schema":{"type":"number","maximum":10.0,"minimum":0.2,"description":"Seconds between events","default":1.0,"title":"Interval S"},"description":"Seconds between events"},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health/chat-model":{"get":{"tags":["health"],"summary":"Check Chat Model Health","description":"Health check for a specific chat model.\n\nRuns the full chat pipeline (fetch user details, memories, chat history,\nbuild system instruction, call LLM) but skips all database writes.\nReturns model status, latency breakdown, and a response preview.","operationId":"check_chat_model_health_health_chat_model_get","parameters":[{"name":"model","in":"query","required":true,"schema":{"type":"string","description":"Model name, e.g. 'gemini-2.5-flash', 'openai:gpt-4o', 'azure:gpt-4o-mini'","title":"Model"},"description":"Model name, e.g. 'gemini-2.5-flash', 'openai:gpt-4o', 'azure:gpt-4o-mini'"},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"User ID for fetching real user context (reads only, no writes)","title":"User Id"},"description":"User ID for fetching real user context (reads only, no writes)"},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bible-progress/append":{"post":{"tags":["bible-progress"],"summary":"Append Bible Progress","description":"Append a chapter to user's Bible reading progress.\nCalled when a user completes reading a chapter.\n\nThis endpoint is idempotent - duplicate chapters will not be added.\nCreates a new progress record if none exists, or updates the existing one.","operationId":"append_bible_progress_api_bible_progress_append_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppendProgressRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/bible-progress":{"get":{"tags":["bible-progress"],"summary":"Get Bible Progress","description":"Get user's complete Bible reading progress.\n\nReturns the user's reading progress including:\n- Progress map (book_id -> completed chapters)\n- Last read position metadata\n- Timestamps","operationId":"get_bible_progress_api_bible_progress_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BibleProgressResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chatbot":{"post":{"tags":["chatbot"],"summary":"Chatbot Endpoint","operationId":"chatbot_endpoint_api_chatbot_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chatbot/stream":{"post":{"tags":["chatbot"],"summary":"Chatbot Stream Endpoint","description":"Streamed variant of /chatbot: emits the reply as SSE paragraph events so\nthe first bubble renders as soon as the first paragraph is generated. The\nbuffered /chatbot endpoint is unchanged and remains the fallback for old\napp versions and for client-side retry.\n\nEvents: meta {conversation_id, protocol} → paragraph {index, text}* →\ndone {conversation_id, paragraphs, sources, bible_verses} | error {code,\nmessage, paragraphs_emitted}. Comment lines (\": ping\") are heartbeats.\n\nMid-stream provider failure emits an error event and persists nothing —\nthe client discards the partial bubbles and retries fresh.\n\nrequest.sendAudio is deliberately ignored here: voiceover for streamed\nreplies is fetched separately by the client (/tts), since audio for a\nreply that is still generating can't be inlined into the SSE stream.","operationId":"chatbot_stream_endpoint_api_chatbot_stream_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chats":{"get":{"tags":["chatbot"],"summary":"Get User Chats","description":"Get all chats for the current authenticated user","operationId":"get_user_chats_api_chats_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Limit"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chats/{chat_id}/messages":{"get":{"tags":["chatbot"],"summary":"Get Chat Messages","description":"Get messages for a specific chat\n\nArgs:\n    chat_id: The chat ID\n    current_user: Authenticated user from dependency injection\n    recent: If True, returns the most recent N messages. If False (default), returns oldest N messages.\n    limit: Maximum number of messages to return (default 100)","operationId":"get_chat_messages_api_chats__chat_id__messages_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","title":"Chat Id"}},{"name":"recent","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Recent"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/test":{"get":{"tags":["chatbot"],"summary":"Test Auth","description":"Test endpoint to verify authentication is working","operationId":"test_auth_api_auth_test_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/public/test":{"get":{"tags":["chatbot"],"summary":"Test Public","description":"Public test endpoint that doesn't require authentication","operationId":"test_public_api_public_test_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/chat/suggestions":{"get":{"tags":["chatbot"],"summary":"Get Chat Suggestions","description":"Get chat suggestions for the Christian companion app in user's preferred language.\n\nIf conversation_id is provided and has messages, returns contextual suggestions.\nOtherwise returns static suggestions.","operationId":"get_chat_suggestions_api_chat_suggestions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"conversation_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestionsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/chatbot/compact":{"post":{"tags":["chatbot"],"summary":"Compact Conversation","description":"Trigger conversation compaction inline. Called after a successful chat message.","operationId":"compact_conversation_api_chatbot_compact_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompactRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompactResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/seo/biblical-chat":{"post":{"tags":["seo"],"summary":"Seo Biblical Chat Endpoint","operationId":"seo_biblical_chat_endpoint_api_seo_biblical_chat_post","parameters":[{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeoBiblicalChatRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeoBiblicalChatResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sanctum/api/chatbot":{"post":{"tags":["sanctum-chatbot"],"summary":"Chatbot Endpoint","operationId":"chatbot_endpoint_sanctum_api_chatbot_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sanctum/api/chats":{"get":{"tags":["sanctum-chatbot"],"summary":"Get User Chats","description":"Get all chats for the current authenticated user","operationId":"get_user_chats_sanctum_api_chats_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Limit"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sanctum/api/chats/{chat_id}/messages":{"get":{"tags":["sanctum-chatbot"],"summary":"Get Chat Messages","description":"Get messages for a specific chat","operationId":"get_chat_messages_sanctum_api_chats__chat_id__messages_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","title":"Chat Id"}},{"name":"recent","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Recent"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sanctum/api/chat/suggestions":{"get":{"tags":["sanctum-chatbot"],"summary":"Get Chat Suggestions","description":"Get chat suggestions for the Christian companion app in user's preferred language.","operationId":"get_chat_suggestions_sanctum_api_chat_suggestions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"conversation_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestionsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sanctum/api/chatbot/compact":{"post":{"tags":["sanctum-chatbot"],"summary":"Compact Conversation","description":"Trigger conversation compaction inline. Called after a successful chat message.","operationId":"compact_conversation_sanctum_api_chatbot_compact_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompactRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompactResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/livekit/create":{"post":{"tags":["livekit"],"summary":"Create Room With Metadata","description":"Create a new LiveKit room with the provided room_id and generate an access token.\n\nThis endpoint:\n1. Creates a new LiveKit room using the provided room_id as the room name\n2. Generates an access token for the participant\n3. Returns room details and the access token","operationId":"create_room_with_metadata_api_livekit_create_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRoomRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-prayer":{"post":{"tags":["prayers"],"summary":"Generate Daily Prayer","description":"Generate a daily prayer (text only).\n\nThis endpoint creates a personalized prayer (approximately 1 minute long) that ends with \"Amen\".\nAudio is fetched separately via the /daily-prayer/audio endpoint to improve response time.\n\nWhen `for_names` is supplied the prayer is intercessory — written for those\npeople rather than for the user — and bypasses the daily prayer cache so it\nneither replays nor overwrites the user's own daily prayer.\n\nArgs:\n    request: Prayer request (sendAudio flag is ignored)\n    current_user: Authenticated user\n    \nReturns:\n    PrayerResponse containing prayer_text only (audio_base64 will be None)","operationId":"generate_daily_prayer_api_daily_prayer_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrayerRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrayerResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-prayer/audio":{"get":{"tags":["prayers"],"summary":"Get Daily Prayer Audio","description":"Get daily prayer audio, generating it if not already cached.\n\nThis endpoint retrieves the daily prayer audio from the database if it exists,\nor generates both the prayer text and audio if not cached.\n\nArgs:\n    current_user: Authenticated user\n    \nReturns:\n    PrayerResponse containing prayer_text and audio_base64","operationId":"get_daily_prayer_audio_api_daily_prayer_audio_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrayerResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prayer-library/{topic}":{"get":{"tags":["prayer-library"],"summary":"Get Library Prayer","description":"Fetch a pre-generated prayer from the library for a given topic.\n\nThe language and voice are resolved from the user's profile preferences.\nDefaults to English (\"en\") and \"v1-openai-alloy\" if not set.\n\nArgs:\n    topic: One of the 12 supported prayer topics (case-sensitive).\n    current_user: Authenticated user (provides preferred_language and preferred_voice).\n\nReturns:\n    PrayerLibraryResponse with prayer text and audio URL.","operationId":"get_library_prayer_api_prayer_library__topic__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"topic","in":"path","required":true,"schema":{"type":"string","title":"Topic"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrayerLibraryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tts":{"post":{"tags":["tts"],"summary":"Text To Speech","description":"Convert text to speech using the user's preferred TTS provider.\n\nArgs:\n    request: TTS request containing text\n    current_user: Authenticated user\n\nReturns:\n    TTSResponse containing base64 encoded audio data","operationId":"text_to_speech_api_tts_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TTSRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TTSResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/tts.mp3":{"get":{"tags":["tts"],"summary":"Text To Speech Streaming","description":"Convert text to speech using OpenAI TTS and stream the audio as MP3.\n\nArgs:\n    text: Text to convert (query parameter)\n    voice: Optional voice override (VOICE_1, VOICE_2, etc)\n    current_user: Authenticated user\n\nReturns:\n    StreamingResponse with MP3 audio data","operationId":"text_to_speech_streaming_api_tts_mp3_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"text","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":4000,"description":"Text to convert to speech (max 400 words)","title":"Text"},"description":"Text to convert to speech (max 400 words)"},{"name":"voice","in":"query","required":false,"schema":{"type":"string","description":"Voice override (VOICE_1, VOICE_2, etc). If not provided, uses user's preferred voice","title":"Voice"},"description":"Voice override (VOICE_1, VOICE_2, etc). If not provided, uses user's preferred voice"},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-devotional":{"get":{"tags":["daily-devotional"],"summary":"Get Daily Devotionals","description":"Fetch today's daily devotional using the user's preferred language by default.\n\nlocale_override can be used for testing to force a specific locale.","operationId":"get_daily_devotionals_api_daily_devotional_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"locale_override","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Locale Override"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DailyDevotionalResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests":{"get":{"tags":["daily-quests"],"summary":"Get Daily Quests","description":"Get daily_prayer_completed for the authenticated user.","operationId":"get_daily_quests_api_daily_quests_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DailyQuestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/discord-joined":{"post":{"tags":["daily-quests"],"summary":"Mark Discord Joined","description":"Mark discord as joined for the authenticated user.","operationId":"mark_discord_joined_api_daily_quests_discord_joined_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/verse-interacted":{"post":{"tags":["daily-quests"],"summary":"Mark Verse Interacted","description":"Mark daily verse as interacted for the authenticated user.\nThis is a daily quest that resets each day.","operationId":"mark_verse_interacted_api_daily_quests_verse_interacted_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/prompt-completed":{"post":{"tags":["daily-quests"],"summary":"Mark Prompt Completed","description":"Mark daily prompt as completed for the authenticated user.\nThis is a daily quest that resets each day.","operationId":"mark_prompt_completed_api_daily_quests_prompt_completed_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/devotional-interacted":{"post":{"tags":["daily-quests"],"summary":"Mark Devotional Interacted","description":"Mark daily devotional as interacted for the authenticated user.\nThis is a daily quest that resets each day.","operationId":"mark_devotional_interacted_api_daily_quests_devotional_interacted_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/prayer-wall-opened":{"post":{"tags":["daily-quests"],"summary":"Mark Prayer Wall Opened","description":"Mark prayer wall as opened for the authenticated user.\nThis is a one-off quest that only rewards on first completion.","operationId":"mark_prayer_wall_opened_api_daily_quests_prayer_wall_opened_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/widget-tutorial-completed":{"post":{"tags":["daily-quests"],"summary":"Mark Widget Tutorial Completed","description":"Mark widget tutorial as completed for the authenticated user.","operationId":"mark_widget_tutorial_completed_api_daily_quests_widget_tutorial_completed_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/prayer-reminder-completed":{"post":{"tags":["daily-quests"],"summary":"Mark Prayer Reminder Completed","description":"Mark prayer reminder as completed for the authenticated user.","operationId":"mark_prayer_reminder_completed_api_daily_quests_prayer_reminder_completed_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/customize-completed":{"post":{"tags":["daily-quests"],"summary":"Mark Customize Completed","description":"Mark customize as completed for the authenticated user.","operationId":"mark_customize_completed_api_daily_quests_customize_completed_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/share-creed-completed":{"post":{"tags":["daily-quests"],"summary":"Mark Share Creed Completed","description":"Mark share creed as completed for the authenticated user.","operationId":"mark_share_creed_completed_api_daily_quests_share_creed_completed_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/sponsor-completed":{"post":{"tags":["daily-quests"],"summary":"Mark Sponsor Completed","description":"Mark sponsor as completed for the authenticated user.","operationId":"mark_sponsor_completed_api_daily_quests_sponsor_completed_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/add-church-completed":{"post":{"tags":["daily-quests"],"summary":"Mark Add Church Completed","description":"Mark add-church special quest as completed for the authenticated user.","operationId":"mark_add_church_completed_api_daily_quests_add_church_completed_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/start-friend-streak-completed":{"post":{"tags":["daily-quests"],"summary":"Mark Start Friend Streak Completed","description":"Mark start-friend-streak special quest as completed for the authenticated user.","operationId":"mark_start_friend_streak_completed_api_daily_quests_start_friend_streak_completed_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/faith-lock-completed":{"post":{"tags":["daily-quests"],"summary":"Mark Faith Lock Completed","description":"Mark faith-lock special quest as completed for the authenticated user.","operationId":"mark_faith_lock_completed_api_daily_quests_faith_lock_completed_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/artist-of-the-week-completed":{"post":{"tags":["daily-quests"],"summary":"Mark Artist Of The Week Completed","description":"Mark artist-of-the-week special quest as completed for the authenticated user.","operationId":"mark_artist_of_the_week_completed_api_daily_quests_artist_of_the_week_completed_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/commit-to-mass-completed":{"post":{"tags":["daily-quests"],"summary":"Mark Commit To Mass Completed","description":"Mark commit-to-mass as completed for the authenticated user.\nThis is a weekly quest that resets each Monday.","operationId":"mark_commit_to_mass_completed_api_daily_quests_commit_to_mass_completed_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/{quest_key}/claim":{"post":{"tags":["daily-quests"],"summary":"Claim Quest Reward","description":"Mark a completed quest's reward as claimed for the authenticated user.\nThe actual token grant is performed by the client (preserving the existing\nearnReward animation + analytics flow); this endpoint only records that\nthe reward has been claimed for the current period.","operationId":"claim_quest_reward_api_daily_quests__quest_key__claim_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"quest_key","in":"path","required":true,"schema":{"type":"string","title":"Quest Key"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-quests/prompts":{"get":{"tags":["daily-quests"],"summary":"Get Daily Prompts","description":"Return 3 prompts for today. Selection is stable per user per day.","operationId":"get_daily_prompts_api_daily_quests_prompts_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional locale override (en, es, pt). When set, prompts are returned in this language without requiring an updated profile. Falls back to preferred_language when omitted or invalid.","title":"Lang"},"description":"Optional locale override (en, es, pt). When set, prompts are returned in this language without requiring an updated profile. Falls back to preferred_language when omitted or invalid."},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/auth/link":{"post":{"summary":"Link Oauth","operationId":"link_oauth_api_auth_link_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkOAuthRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-gratitudes-journal":{"get":{"tags":["gratitude"],"summary":"Get Daily Gratitudes","description":"Fetch all gratitude journals for the authenticated user.","operationId":"get_daily_gratitudes_api_daily_gratitudes_journal_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GratitudeJournalResponse"},"title":"Response Get Daily Gratitudes Api Daily Gratitudes Journal Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-gratitude":{"post":{"tags":["gratitude"],"summary":"Add Daily Gratitude","description":"Add a daily gratitude journal for the authenticated user.","operationId":"add_daily_gratitude_api_daily_gratitude_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddGratitudeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GratitudeJournalResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-gratitude/{gratitude_id}":{"patch":{"tags":["gratitude"],"summary":"Update Daily Gratitude","description":"Update an existing gratitude journal entry for the authenticated user.","operationId":"update_daily_gratitude_api_daily_gratitude__gratitude_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"gratitude_id","in":"path","required":true,"schema":{"type":"integer","title":"Gratitude Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGratitudeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GratitudeJournalResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["gratitude"],"summary":"Delete Daily Gratitude","description":"Delete a gratitude journal entry for the authenticated user.","operationId":"delete_daily_gratitude_api_daily_gratitude__gratitude_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"gratitude_id","in":"path","required":true,"schema":{"type":"integer","title":"Gratitude Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-gratitude/recent/{user_id}":{"get":{"tags":["gratitude"],"summary":"Get User Recent Gratitude","description":"Get the most recent gratitude journal entry for a user.\nVerifies that the user has journal_share enabled.\nAnyone can view if journal_share is enabled (no friendship required).\nReturns None if:\n- User has journal_share disabled\n- No gratitude journal exists","operationId":"get_user_recent_gratitude_api_daily_gratitude_recent__user_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GratitudeJournalResponse"},{"type":"null"}],"title":"Response Get User Recent Gratitude Api Daily Gratitude Recent  User Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/daily-gratitude/recent/{user_id}/list":{"get":{"tags":["gratitude"],"summary":"Get User Recent Gratitudes List","description":"Get the most recent gratitude journal entries for a user (up to `limit`).\nVerifies that the user has journal_share enabled.\nReturns empty list if journal_share is disabled or no entries exist.","operationId":"get_user_recent_gratitudes_list_api_daily_gratitude_recent__user_id__list_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"default":5,"title":"Limit"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GratitudeJournalResponse"},"title":"Response Get User Recent Gratitudes List Api Daily Gratitude Recent  User Id  List Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prayer-journals":{"get":{"tags":["prayer-journal"],"summary":"Get Prayer Journals","description":"Fetch all prayer journals for the authenticated user.","operationId":"get_prayer_journals_api_prayer_journals_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PrayerJournalResponse"},"title":"Response Get Prayer Journals Api Prayer Journals Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prayer-journal":{"post":{"tags":["prayer-journal"],"summary":"Add Prayer Journal","description":"Add a new prayer journal entry for the authenticated user.","operationId":"add_prayer_journal_api_prayer_journal_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddPrayerJournalRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrayerJournalResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prayer-journal/{prayer_journal_id}":{"delete":{"tags":["prayer-journal"],"summary":"Delete Prayer Journal","description":"Delete a prayer journal entry for the authenticated user.","operationId":"delete_prayer_journal_api_prayer_journal__prayer_journal_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prayer_journal_id","in":"path","required":true,"schema":{"type":"integer","title":"Prayer Journal Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/shared-prayers":{"post":{"tags":["shared-prayers"],"summary":"Create Shared Prayers","description":"Store a prayer once per person it is about to be shared with.","operationId":"create_shared_prayers_api_shared_prayers_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSharedPrayersRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSharedPrayersResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/shared-prayers/{prayer_id}":{"get":{"tags":["shared-prayers"],"summary":"Get Shared Prayer","description":"Fetch a shared prayer by id.\n\nAny signed-in user may read one — the recipient is a different person from\nthe sender, and often brand new, but the app assigns them an anonymous\naccount on first open so a session always exists. Knowing the id is what\ngrants access, the same as any share link.","operationId":"get_shared_prayer_api_shared_prayers__prayer_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prayer_id","in":"path","required":true,"schema":{"type":"string","title":"Prayer Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SharedPrayerResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/learning-plans/catalog":{"get":{"tags":["learning-plans"],"summary":"List Catalog","operationId":"list_catalog_api_learning_plans_catalog_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang"}},{"name":"include_reflections","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Reflections"}},{"name":"include_premium","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Premium"}},{"name":"include_bodies","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Include Bodies"}},{"name":"include_starter_count","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Starter Count"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/Plan"}},{"$ref":"#/components/schemas/LearningPlanCatalog"}],"title":"Response List Catalog Api Learning Plans Catalog Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/learning-plans/instances":{"get":{"tags":["learning-plans"],"summary":"List Instances","operationId":"list_instances_api_learning_plans_instances_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LearningPlanInstance"},"title":"Response List Instances Api Learning Plans Instances Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["learning-plans"],"summary":"Create Instance","operationId":"create_instance_api_learning_plans_instances_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartInstanceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LearningPlanInstance"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/learning-plans/instances/{instance_id}/segments":{"post":{"tags":["learning-plans"],"summary":"Mark Segment Complete","operationId":"mark_segment_complete_api_learning_plans_instances__instance_id__segments_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"instance_id","in":"path","required":true,"schema":{"type":"string","title":"Instance Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkSegmentRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LearningPlanInstance"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/learning-plans/instances/{instance_id}/reflections":{"get":{"tags":["learning-plans"],"summary":"List Reflections","operationId":"list_reflections_api_learning_plans_instances__instance_id__reflections_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"instance_id","in":"path","required":true,"schema":{"type":"string","title":"Instance Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LearningPlanReflection"},"title":"Response List Reflections Api Learning Plans Instances  Instance Id  Reflections Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/learning-plans/instances/{instance_id}/reflections/{day_index}":{"put":{"tags":["learning-plans"],"summary":"Save Reflection","description":"Create or edit one day's reflection row. Idempotent, so the client can\nre-save freely as the user edits or re-answers.","operationId":"save_reflection_api_learning_plans_instances__instance_id__reflections__day_index__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"instance_id","in":"path","required":true,"schema":{"type":"string","title":"Instance Id"}},{"name":"day_index","in":"path","required":true,"schema":{"type":"integer","title":"Day Index"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveReflectionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LearningPlanReflection"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/journal":{"get":{"tags":["journal"],"summary":"Get Journal","description":"Fetch the combined Journal screen payload for the authenticated user\n(gratitudes, prayer journals and saved Bible verses) in a single call.\n\nBacked by the `get_journal_bundle(p_user_id uuid)` Postgres function which\nreturns everything plus `latest_change` in a single round-trip. Freshness is\nmanaged client-side via per-source stale signals; the server holds no cache.","operationId":"get_journal_api_journal_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JournalBundleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prayer-wall":{"post":{"tags":["prayer-wall"],"summary":"Submit Prayer","description":"Submit a prayer to the prayer wall. AI validates and generates expanded prayer. Returns the prayer for user approval (not scheduled yet).","operationId":"submit_prayer_api_prayer_wall_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitPrayerRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrayerWall"}}}},"400":{"description":"Prayer rejected or cooldown active","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Failed to submit prayer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["prayer-wall"],"summary":"Get Current Prayers","description":"Get scheduled prayers (start_time >= now and not expired). Pass `lang` (en/es/pt/de/fr) to receive translated title/prayer text.","operationId":"get_current_prayers_api_prayer_wall_get","parameters":[{"name":"include_is_bot","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Is Bot"}},{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PrayerWall"},"title":"Response Get Current Prayers Api Prayer Wall Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prayer-wall/{prayer_id}/approve":{"post":{"tags":["prayer-wall"],"summary":"Approve Prayer","description":"Approve a prayer to be scheduled on the prayer wall. Returns updated list of scheduled prayers.","operationId":"approve_prayer_api_prayer_wall__prayer_id__approve_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prayer_id","in":"path","required":true,"schema":{"type":"integer","title":"Prayer Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PrayerWall"},"title":"Response Approve Prayer Api Prayer Wall  Prayer Id  Approve Post"}}}},"400":{"description":"Already approved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Prayer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prayer-wall/{prayer_id}/reject":{"post":{"tags":["prayer-wall"],"summary":"Reject Prayer","description":"Reject a prayer (removes it from the system).","operationId":"reject_prayer_api_prayer_wall__prayer_id__reject_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prayer_id","in":"path","required":true,"schema":{"type":"integer","title":"Prayer Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveRejectResponse"}}}},"400":{"description":"Cannot reject approved prayer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Prayer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prayer-wall/expire-cron":{"post":{"tags":["prayer-wall"],"summary":"Expire Prayers Cron","description":"Cron endpoint to expire old prayers. Run every 10-20 minutes. Runs in background.","operationId":"expire_prayers_cron_api_prayer_wall_expire_cron_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/prayer-wall/generate-bot-cron":{"post":{"tags":["prayer-wall"],"summary":"Generate Bot Prayers Cron","description":"Cron endpoint to generate bot prayers if queue is low. Runs in background.","operationId":"generate_bot_prayers_cron_api_prayer_wall_generate_bot_cron_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/prayer-wall-paginated":{"get":{"tags":["prayer-wall"],"summary":"Get Prayers Paginated","description":"Get all prayers with pagination. Pass `lang` (en/es/pt/de/fr) to receive translated title/prayer text.","operationId":"get_prayers_paginated_api_prayer_wall_paginated_get","parameters":[{"name":"include_is_bot","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Is Bot"}},{"name":"include_count","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Count"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrayerWallPaginatedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prayer-wall/me":{"get":{"tags":["prayer-wall"],"summary":"Get My Prayers","description":"Get all prayers submitted by the authenticated user, ordered by most recent first.","operationId":"get_my_prayers_api_prayer_wall_me_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PrayerWall"},"title":"Response Get My Prayers Api Prayer Wall Me Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prayer-wall/upcoming-count":{"get":{"tags":["prayer-wall"],"summary":"Get Upcoming Count","description":"Count of approved, non-expired prayers currently scheduled on the wall.","operationId":"get_upcoming_count_api_prayer_wall_upcoming_count_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrayingCountResponse"}}}}}}},"/api/prayer-wall/praying-count":{"get":{"tags":["prayer-wall"],"summary":"Get Praying Count","description":"Get the number of people currently praying. Updates every 15 minutes.","operationId":"get_praying_count_api_prayer_wall_praying_count_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrayingCountResponse"}}}}}}},"/api/prayer-wall/{prayer_id}":{"get":{"tags":["prayer-wall"],"summary":"Get Prayer By Id","description":"Fetch a single approved prayer by id. Pass `lang` (en/es/pt/de/fr) to receive translated title/prayer text.","operationId":"get_prayer_by_id_api_prayer_wall__prayer_id__get","parameters":[{"name":"prayer_id","in":"path","required":true,"schema":{"type":"integer","title":"Prayer Id"}},{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrayerWall"}}}},"404":{"description":"Prayer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/prayer-wall/{prayer_id}/comments":{"post":{"tags":["prayer-wall"],"summary":"Submit Comment","description":"Submit a comment on a prayer. AI validates comment. Returns success if valid.","operationId":"submit_comment_api_prayer_wall__prayer_id__comments_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prayer_id","in":"path","required":true,"schema":{"type":"integer","title":"Prayer Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitCommentRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitCommentResponse"}}}},"400":{"description":"Comment rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Failed to submit comment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["prayer-wall"],"summary":"Get Prayer Comments","description":"Get bot-approved comments for a prayer.","operationId":"get_prayer_comments_api_prayer_wall__prayer_id__comments_get","parameters":[{"name":"prayer_id","in":"path","required":true,"schema":{"type":"integer","title":"Prayer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PrayerWallComment"},"title":"Response Get Prayer Comments Api Prayer Wall  Prayer Id  Comments Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/generate-image":{"post":{"tags":["image-generation"],"summary":"Generate Image","description":"Generate an image using OpenAI's image generation API.\n\nThis endpoint accepts an image upload and various parameters to transform\nthe image according to the provided prompt and style settings.","operationId":"generate_image_api_generate_image_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_generate_image_api_generate_image_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageGenerationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/streaks":{"get":{"tags":["streaks"],"summary":"Get Streaks","description":"Get the current streak count for the authenticated user.","operationId":"get_streaks_api_streaks_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StreakResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/streaks/extend":{"post":{"tags":["streaks"],"summary":"Update Oneoff Event","description":"Update one-off daily event completion for a user.\n\nAuthentication methods:\n1. Regular user auth via Bearer token\n2. Admin auth via X-API-Key and X-User-ID headers\n\nThis will update the last_oneoff_daily_event timestamp and trigger streak calculation.\nUses user's timezone from current_user if available, otherwise queries user_info table.\n\nQuery parameters:\n- restore: If true, restore a broken streak by incrementing the last active streak instead of starting fresh.\n\nRequest body (optional):\n- useFreeOffer: If true, increment the free_restore_count when restoring.\n- txnId: Transaction ID if the user paid for the restore.","operationId":"update_oneoff_event_api_streaks_extend_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"restore","in":"query","required":false,"schema":{"type":"boolean","description":"If true, restore a broken streak by incrementing the last active streak instead of starting fresh","default":false,"title":"Restore"},"description":"If true, restore a broken streak by incrementing the last active streak instead of starting fresh"},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/StreakRestoreRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StreakResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/streaks/send-reminders-cron":{"post":{"tags":["streaks"],"summary":"Send Streak Reminders Cron","description":"Cron endpoint to send solo streak loss reminders (iOS Live Activity + Android chronometer).\n\nSends reminders to users at 10 PM local time who:\n- Haven't completed their daily quest today\n- Have an active streak (streak_count > 0)\n- Have a live activity token (iOS) or push token (Android)\n- Haven't received a reminder today\n\nRequires x-api-key header for authentication.","operationId":"send_streak_reminders_cron_api_streaks_send_reminders_cron_post","parameters":[{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Dev-only: target a single user (bypasses time-window/dedup). Rejected outside development.","title":"User Id"},"description":"Dev-only: target a single user (bypasses time-window/dedup). Rejected outside development."},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/verses/save":{"post":{"tags":["verses"],"summary":"Save Verse","description":"Save a Bible verse to the user's profile.\nPrevents duplicate verses from being saved.","operationId":"save_verse_api_verses_save_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveVerseRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveVerseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/verses":{"get":{"tags":["verses"],"summary":"Get Saved Verses","description":"Get all saved verses for the current user.","operationId":"get_saved_verses_api_verses_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSavedVersesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["verses"],"summary":"Delete Saved Verse","description":"Delete a saved verse from the user's profile.","operationId":"delete_saved_verse_api_verses_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveVerseRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveVerseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/schedule-daily":{"post":{"tags":["scheduled-notifications"],"summary":"Schedule Daily Notifications","description":"Daily cron job endpoint to schedule notifications for all users.\nThis should be called once per day (e.g., at midnight UTC).\n\nFor each user with push tokens:\n- Randomly selects a time slot (morning/noon/night)\n- Schedules a notification with content appropriate for that time\n- Respects user's timezone for scheduling\n\nTasks are queued in Redis and processed by Celery workers.\nUse days_ahead to override the default 2-day lead time.\n\nRequires x-api-key header for authentication.","operationId":"schedule_daily_notifications_api_scheduled_notifications_admin_schedule_daily_post","parameters":[{"name":"days_ahead","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Days ahead to schedule for (default: 2)","title":"Days Ahead"},"description":"Days ahead to schedule for (default: 2)"},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/send-due":{"post":{"tags":["scheduled-notifications"],"summary":"Send Due Notifications","description":"5-minute cron job endpoint to send all due notifications.\nThis should be called every 5 minutes.\n\nChecks for all pending notifications scheduled for current time or earlier and sends them.\nUpdates notification status to 'sent' or 'failed' accordingly.\n\nTasks are queued in Redis and processed by Celery workers.\n\nRequires x-api-key header for authentication.","operationId":"send_due_notifications_api_scheduled_notifications_admin_send_due_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/generate-content":{"post":{"tags":["scheduled-notifications"],"summary":"Generate Content","description":"Hourly cron job endpoint to pre-generate notification content.\nBy default processes a 1-hour time slice 47-48 hours ahead.\nUse start_hours_ahead and end_hours_ahead query params to override.\n\nFor each notification in the slice:\n- Determines type (personalized vs template) via probability\n- Template: inserts content directly into DB\n- Personalized: submits Gemini batch (results collected via retry)\n\nRequires x-api-key header for authentication.","operationId":"generate_content_api_scheduled_notifications_admin_generate_content_post","parameters":[{"name":"start_hours_ahead","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Hours ahead of now for window start (default: 47)","title":"Start Hours Ahead"},"description":"Hours ahead of now for window start (default: 47)"},{"name":"end_hours_ahead","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Hours ahead of now for window end (default: 48)","title":"End Hours Ahead"},"description":"Hours ahead of now for window end (default: 48)"},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/send-prayer-wall-daily":{"post":{"tags":["Email Notifications"],"summary":"Send Prayer Wall Daily","description":"Daily cron job endpoint to send the prayer wall email to the Resend signup segment.\nCall once per day (e.g. at a fixed time).\n\nFetches last N approved prayers, picks best for engagement via LLM, then sends\na broadcast using the Resend dashboard template and RESEND_SEGMENT_ID.\nBroadcast is scheduled for 11:00 AM EST.\n\nRequires x-api-key header for authentication.","operationId":"send_prayer_wall_daily_api_scheduled_notifications_admin_send_prayer_wall_daily_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/send-daily-devotional-daily":{"post":{"tags":["Email Notifications"],"summary":"Send Daily Devotional Daily","description":"Daily cron job endpoint to send the daily devotional email to the Resend signup segment.\nCall once per day (e.g. at a fixed time).\n\nFetches today's devotional for the configured language, then sends a broadcast\nusing the Resend daily devotional template and RESEND_SEGMENT_ID.\nBroadcast is scheduled for 7:00 AM EST.\n\nRequires x-api-key header for authentication.","operationId":"send_daily_devotional_daily_api_scheduled_notifications_admin_send_daily_devotional_daily_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/sync-signup-audience":{"post":{"tags":["Email Notifications"],"summary":"Sync Signup Audience","description":"Cron job endpoint to sync recent signups to the Resend signup audience.\nTrigger every 6 hours (e.g. 00:00, 06:00, 12:00, 18:00 UTC) for contiguous 6-hour windows with no overlap.\nEach run processes users created in the preceding 6-hour window.\n\nRequires x-api-key header for authentication.","operationId":"sync_signup_audience_api_scheduled_notifications_admin_sync_signup_audience_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/prayer-wall-daily/debug/selected-prayer":{"get":{"tags":["Email Notifications"],"summary":"Debug Selected Prayer","description":"Debug: get last N approved prayers and pick best for engagement (LLM or fallback).\nReturns the chosen prayer only. No side effects besides optional LLM call.\nRequires x-api-key header for authentication.","operationId":"debug_selected_prayer_api_scheduled_notifications_admin_prayer_wall_daily_debug_selected_prayer_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":100,"minimum":1},{"type":"null"}],"description":"Number of recent prayers to consider; defaults to 20","title":"Limit"},"description":"Number of recent prayers to consider; defaults to 20"},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/resend/debug/create-contact":{"post":{"tags":["Email Notifications"],"summary":"Debug Resend Create Contact","description":"Debug: create a contact in Resend (for testing). Returns the Resend API response\n(object + id). Optionally add the contact to RESEND_SEGMENT_ID via add_to_segment.\nRequires x-api-key header for authentication.","operationId":"debug_resend_create_contact_api_scheduled_notifications_admin_resend_debug_create_contact_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendCreateContactRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/prayer-wall-daily/debug/preview-broadcast":{"post":{"tags":["Email Notifications"],"summary":"Debug Preview Broadcast","description":"Debug: fetch Resend template, substitute name/prayer/prayer_request, return subject and HTML.\nDoes not create or send a broadcast. Requires x-api-key header for authentication.","operationId":"debug_preview_broadcast_api_scheduled_notifications_admin_prayer_wall_daily_debug_preview_broadcast_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrayerWallBroadcastVarsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/prayer-wall-daily/debug/send-broadcast":{"post":{"tags":["Email Notifications"],"summary":"Debug Send Broadcast","description":"Debug: send prayer wall broadcast with given variables. Uses RESEND_SEGMENT_ID;\nset it to your test segment when testing. Requires x-api-key header.","operationId":"debug_send_broadcast_api_scheduled_notifications_admin_prayer_wall_daily_debug_send_broadcast_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrayerWallBroadcastVarsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/daily-devotional-daily/debug/preview-broadcast":{"post":{"tags":["Email Notifications"],"summary":"Debug Preview Daily Devotional Broadcast","description":"Debug: fetch Resend daily devotional template, substitute variables, return subject and HTML.\nDoes not create or send a broadcast. Requires x-api-key header for authentication.","operationId":"debug_preview_daily_devotional_broadcast_api_scheduled_notifications_admin_daily_devotional_daily_debug_preview_broadcast_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DailyDevotionalBroadcastVarsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/daily-devotional-daily/debug/send-broadcast":{"post":{"tags":["Email Notifications"],"summary":"Debug Send Daily Devotional Broadcast","description":"Debug: send daily devotional broadcast with given variables. Uses RESEND_SEGMENT_ID.\nRequires x-api-key header for authentication.","operationId":"debug_send_daily_devotional_broadcast_api_scheduled_notifications_admin_daily_devotional_daily_debug_send_broadcast_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DailyDevotionalBroadcastVarsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/test":{"post":{"tags":["scheduled-notifications"],"summary":"Test Notification","description":"Generate a test notification for a user.\nShows exactly what would be generated by the production batch system.\n\nArgs:\n- x-user-id (header): The user ID to generate notification for\n- sendToDevice (body): If true, actually sends the notification to the user's device. Default: false\n- deliveryMethod (body): \"push\" for regular push notification, \"live_activity\" for iOS Live Activity. Default: \"push\"\n- notificationType (body): \"personalized\", \"prayer\", or \"journaling\". Default: \"personalized\"\n- timeOfDay (body): \"morning\", \"noon\", \"evening\", \"night\", or \"generic\". Default: \"generic\"\n- interruptionLevel (body): Optional Expo iOS interruption level for push tests. Use \"time-sensitive\" to test Time Sensitive notifications.\n\nReturns:\n- notification_type: Type of notification generated\n- notification: The generated title and body\n- memories_count: How many memories were used (only for personalized)\n- sent_to_device: Whether notification was sent to device\n- delivery_method: How the notification was delivered\n\nRequires x-api-key header for authentication.","operationId":"test_notification_api_scheduled_notifications_admin_test_post","parameters":[{"name":"x-user-id","in":"header","required":true,"schema":{"type":"string","title":"X-User-Id"}},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestNotificationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/test-live-activity":{"post":{"tags":["scheduled-notifications"],"summary":"Test Live Activity","description":"Trigger a Live Activity on a user's device for testing.\n\nPick a variant from the Swagger \"Examples\" dropdown (prayer / church /\ndevotional / custom reminder, streak, or standard) and send. Reminders carry\nthe per-subtype artwork (via the deep link's reminderType), the weekly streak\nbubbles, and the interactive snooze.\n\n- x-user-id (header): user to send the Live Activity to (must have a stored\n  live_activity_tokens pushToStart token)\n- Requires x-api-key header for authentication.","operationId":"test_live_activity_api_scheduled_notifications_admin_test_live_activity_post","parameters":[{"name":"x-user-id","in":"header","required":true,"schema":{"type":"string","title":"X-User-Id"}},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestLiveActivityRequest"},"examples":{"prayer_reminder":{"summary":"Reminder · Prayer","value":{"notificationType":"reminder","reminderType":"prayer","title":"Prayer time","body":"Begin your prayer time now","streakDays":[true,true,false,true,false,false,false],"includeSnooze":true}},"church_reminder":{"summary":"Reminder · Church","value":{"notificationType":"reminder","reminderType":"church","title":"Church time, friend","body":"Your church family misses you","streakDays":[true,false,true,true,false,true,false],"includeSnooze":true}},"devotional_reminder":{"summary":"Reminder · Devotional","value":{"notificationType":"reminder","reminderType":"devotional","title":"Today's Devotional","body":"Open now to read and reflect.","streakDays":[false,true,true,true,true,false,false],"includeSnooze":true}},"custom_reminder":{"summary":"Reminder · Custom","value":{"notificationType":"reminder","reminderType":"custom","title":"Reminder","body":"Take a moment with God today.","streakDays":[true,true,true,false,false,false,false],"includeSnooze":true}},"streak":{"summary":"Streak","value":{"notificationType":"streak","title":"Streak Reminder","body":"Keep your streak with God","streakCount":42}},"standard":{"summary":"Standard","value":{"notificationType":"standard","title":"A moment with Lenny","body":"Tap to continue your journey"}}}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scheduled-notifications/admin/test-android-chronometer":{"post":{"tags":["scheduled-notifications"],"summary":"Test Android Chronometer","description":"Send the Android streak-saver chronometer push to one user's device for testing.\n\nAndroid counterpart of /admin/test-live-activity: fires the exact Expo data push the\nstreak-loss cron sends (type=\"streak\" + the user's local-midnight deadline); the app's\nnative FCM handler renders the ongoing countdown notification. Deliberately BYPASSES\nthe android_streak_chronometer_enabled feature flag so the flow stays testable in\nproduction while the cron is dormant — single-user only, so there is no broadcast risk.\n\n- x-user-id (header): user to send to (must have stored Expo push_tokens)\n- Body (optional): {\"streakCount\": N} to override the count shown; defaults to 7.\n- Requires x-api-key header for authentication.","operationId":"test_android_chronometer_api_scheduled_notifications_admin_test_android_chronometer_post","parameters":[{"name":"x-user-id","in":"header","required":true,"schema":{"type":"string","title":"X-User-Id"}},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/TestAndroidChronometerRequest"},{"type":"null"}],"title":"Request"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cron-tasks/admin/schedule-daily":{"post":{"tags":["cron-tasks"],"summary":"Schedule Daily Cron Tasks","description":"Daily cron job endpoint to schedule next_run_at for all daily tasks.\nShould be called once per day (e.g., at midnight UTC).\n\nQueues a Celery task to:\n- Fetch all active daily tasks\n- Calculate next_run_at based on user timezone + schedule_time\n- Update next_run_at in database\n\nRequires x-api-key header for authentication.","operationId":"schedule_daily_cron_tasks_api_cron_tasks_admin_schedule_daily_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cron-tasks/admin/schedule-weekly":{"post":{"tags":["cron-tasks"],"summary":"Schedule Weekly Cron Tasks","description":"Weekly cron job endpoint to schedule next_run_at for all weekly tasks.\nShould be called once per week (e.g., Sunday midnight UTC).\n\nQueues a Celery task to:\n- Fetch all active weekly tasks\n- Calculate next_run_at based on user timezone + schedule_day + schedule_time\n- Update next_run_at in database\n\nRequires x-api-key header for authentication.","operationId":"schedule_weekly_cron_tasks_api_cron_tasks_admin_schedule_weekly_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/cron-tasks/admin/process":{"post":{"tags":["cron-tasks"],"summary":"Process Cron Tasks","description":"5-minute cron job endpoint to process all due cron tasks.\nShould be called every 5 minutes.\n\nQueues a Celery task to:\n- Fetch all active tasks where next_run_at is within the 5-minute window\n- Process each task based on type (e.g., send live activity for reminders)\n\nRequires x-api-key header for authentication.","operationId":"process_cron_tasks_api_cron_tasks_admin_process_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reminders":{"post":{"tags":["reminders"],"summary":"Create Reminder","description":"Create a new reminder.\n\nSubtypes:\n- prayer: Daily prayer reminder (uses fixed templates)\n- church: Church reminder (uses fixed templates)\n- devotional: Daily devotional reminder (uses fixed templates)\n- custom: Custom reminder (requires custom_text)\n\nSchedule types:\n- daily: Runs every day at schedule_time\n- weekly: Runs every week on schedule_day at schedule_time","operationId":"create_reminder_api_reminders_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReminderRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["reminders"],"summary":"List Reminders","description":"List all reminders for the current user.","operationId":"list_reminders_api_reminders_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reminders/snooze":{"post":{"tags":["reminders"],"summary":"Snooze Reminder","description":"Snooze a reminder: schedule a follow-up reminder Live Activity in `minutes`.\n\nPublic/unauthenticated: the native \"remind me later\" App Intent has no user\nsession, so it posts the user_id + task_id embedded in the Live Activity and\nwe trust them. The action is benign (re-sends a reminder the user already has)\nand task_id is an unguessable UUID.","operationId":"snooze_reminder_api_reminders_snooze_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnoozeReminderRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reminders/{reminder_id}":{"get":{"tags":["reminders"],"summary":"Get Reminder","description":"Get a single reminder by ID.","operationId":"get_reminder_api_reminders__reminder_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"reminder_id","in":"path","required":true,"schema":{"type":"string","title":"Reminder Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["reminders"],"summary":"Update Reminder","description":"Update an existing reminder.","operationId":"update_reminder_api_reminders__reminder_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"reminder_id","in":"path","required":true,"schema":{"type":"string","title":"Reminder Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateReminderRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["reminders"],"summary":"Delete Reminder","description":"Delete a reminder.","operationId":"delete_reminder_api_reminders__reminder_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"reminder_id","in":"path","required":true,"schema":{"type":"string","title":"Reminder Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/update":{"patch":{"tags":["users"],"summary":"Update User Info","description":"Update user information in the user_info table.\nAccepts any key-value pairs to update flexible user data.\n\nArgs:\n    update_payload: Dictionary with any fields to update\n    current_user: Current authenticated user from dependency\n\nReturns:\n    Dict with success status, message, and updated data","operationId":"update_user_info_api_users_update_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Update Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update User Info Api Users Update Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/users/delete-account":{"delete":{"tags":["users"],"summary":"Delete User Account","description":"Delete user account.\nCurrently this only clears push notification tokens.\nIn the future, this can be extended to handle full account deletion.\n\nReturns:\n    Dict with success status and message","operationId":"delete_user_account_api_users_delete_account_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete User Account Api Users Delete Account Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/user-item-preferences":{"get":{"tags":["user-item-preferences"],"summary":"Get User Item Preferences","description":"Fetch the current user's cosmetic/display preferences from the\nuser_item_preferences table. Returns a record with null fields if no row exists.","operationId":"get_user_item_preferences_api_user_item_preferences_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get User Item Preferences Api User Item Preferences Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["user-item-preferences"],"summary":"Update User Item Preferences","description":"Update user cosmetic/display preferences in the user_item_preferences table.\nUpserts on user_id so a row is created on first write.","operationId":"update_user_item_preferences_api_user_item_preferences_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserItemPreferencesRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update User Item Preferences Api User Item Preferences Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/live-activity/push-to-start-token":{"post":{"tags":["live-activity"],"summary":"Store Push To Start Token","description":"Store a Live Activity pushToStart token for the authenticated user.\nAccepts expired JWTs (signature is still verified).\nValidates token format only — no APNs call is made.","operationId":"store_push_to_start_token_api_live_activity_push_to_start_token_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorePushToStartTokenRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorePushToStartTokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/live-activity/send-call-nudge-cron":{"post":{"tags":["live-activity"],"summary":"Send Call Nudge Cron","description":"Cron endpoint to send call nudge Live Activity notifications.\nCall nudges are Live Activity notifications for AI incoming calls.\n\nSends call nudges to eligible users who:\n- Have completed onboarding\n- Signed up at least 1 week ago\n- Have live activity tokens\n- Have not yet received a call nudge this ISO week (1 per week max)\n\nEach run randomly samples ~2.9% of eligible users so nudges land on\na random day of the week, averaging 1 nudge per user per week.\n\nRequires x-api-key header for authentication.","operationId":"send_call_nudge_cron_api_live_activity_send_call_nudge_cron_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/config":{"get":{"tags":["config"],"summary":"Get Config","description":"Get dynamic configuration and feature flags.","operationId":"get_config_api_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigResponse"}}}}}}},"/api/dream-goal/resource":{"get":{"tags":["dream-goal"],"summary":"Get User Dream Goal Resource","description":"Get the latest unread dream goal resource for the current user.\n\nReturns personalized articles and resources found through LLM web search\nbased on the user's dream goal.\n\nReturns:\n    Dictionary with:\n    - success: boolean indicating operation success\n    - message: descriptive status message\n    - resource: single resource object with title, description, and URL (or None if none found)","operationId":"get_user_dream_goal_resource_api_dream_goal_resource_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get User Dream Goal Resource Api Dream Goal Resource Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dream-goal/resource/{resource_id}":{"patch":{"tags":["dream-goal"],"summary":"Mark Resource As Read","description":"Mark a dream goal resource as read.\n\nThis endpoint allows users to mark specific resources as read, which:\n- Updates the resource status in the database\n- Provides clear feedback on the operation result\n\nArgs:\n    resource_id: Unique identifier of the resource to mark as read\n\nReturns:\n    Dictionary with success status and descriptive message","operationId":"mark_resource_as_read_api_dream_goal_resource__resource_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"resource_id","in":"path","required":true,"schema":{"type":"integer","title":"Resource Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Mark Resource As Read Api Dream Goal Resource  Resource Id  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dream-goal/test-process":{"post":{"tags":["dream-goal"],"summary":"Process Dream Goal","description":"Process the user's dream goal and find relevant resources.\n\nThis endpoint:\n1. Queues the dream goal processing as a background task\n2. Uses Gemini with Google Search to find and save relevant resources\n3. Returns immediately without waiting for completion\n\nReturns:\n    Dictionary with success status indicating processing has been started","operationId":"process_dream_goal_api_dream_goal_test_process_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Process Dream Goal Api Dream Goal Test Process Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/dream-goal/test-dream-goal":{"post":{"tags":["dream-goal"],"summary":"Test Dream Goal","description":"Test endpoint to search for article for a dream goal.","operationId":"test_dream_goal_api_dream_goal_test_dream_goal_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestDreamGoalRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Test Dream Goal Api Dream Goal Test Dream Goal Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/referrals/code":{"get":{"tags":["referrals"],"summary":"Get Or Create Referral Code","description":"Get the authenticated user's referral code, creating one if it doesn't exist.\nIf the user has an active code, it will be returned.\nIf not, a new code will be created and returned.\n\nReturns:\n    ReferralCodeResponse with code details","operationId":"get_or_create_referral_code_api_referrals_code_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferralCodeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/referrals/redeem":{"post":{"tags":["referrals"],"summary":"Redeem Referral Code","description":"Redeem a referral code to get premium access.\n\nRestrictions:\n- Users cannot redeem their own codes\n- Users can only redeem one code (cannot redeem if already redeemed)\n- Code must be active and not expired\n\nArgs:\n    request: RedeemCodeRequest with the token (the actual code)\n\nReturns:\n    RedeemCodeResponse with success status and access expiry","operationId":"redeem_referral_code_api_referrals_redeem_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedeemCodeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedeemCodeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/referrals/claim-reward":{"post":{"tags":["referrals"],"summary":"Claim Referrer Reward","description":"Claim the referrer reward for a specific redemption.\n\nThis endpoint allows referrers to claim their 1 month premium reward\nwhen someone uses their referral code. The reward is stacked on top\nof any existing subscription.\n\nArgs:\n    request: ClaimRewardRequest with the redemption_id\n\nReturns:\n    ClaimRewardResponse with success status and message","operationId":"claim_referrer_reward_api_referrals_claim_reward_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimRewardRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimRewardResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/referrals/redemptions":{"get":{"tags":["referrals"],"summary":"Get User Redemptions","description":"Get all redemptions for the authenticated user's referral code.\n\nThis endpoint returns a list of all users who have redeemed the current user's\nreferral code, including the claim status of each redemption.\n\nReturns:\n    RedemptionsResponse with list of redemptions and counts","operationId":"get_user_redemptions_api_referrals_redemptions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedemptionsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/referrals/redeem-promo":{"post":{"tags":["referrals"],"summary":"Redeem Promo Code","description":"Redeem a system-generated referral code.\n\nValidates the code against the referral_codes table (case-insensitive), then grants\nRevenueCat premium for the duration configured on the code (week / month / year),\nstacking on top of any existing subscription. The grant is recorded in referral_grants.\n\nRestrictions:\n- Code must exist in referral_codes and have status = 'active'\n- User cannot redeem the same code more than once (no limit on redeeming different codes)\n\nArgs:\n    request: RedeemSystemCodeRequest with the code\n\nReturns:\n    RedeemSystemCodeResponse with success status and message","operationId":"redeem_promo_code_api_referrals_redeem_promo_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedeemPromoCodeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedeemPromoCodeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sponsorship/guardian/preferences":{"post":{"tags":["sponsorship"],"summary":"Upsert Sponsor Profile","description":"Create or update the current user's sponsor profile.","operationId":"upsert_sponsor_profile_api_sponsorship_guardian_preferences_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SponsorProfileRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Upsert Sponsor Profile Api Sponsorship Guardian Preferences Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["sponsorship"],"summary":"Get Sponsor Profile","description":"Fetch the current user's sponsor profile.","operationId":"get_sponsor_profile_api_sponsorship_guardian_preferences_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Sponsor Profile Api Sponsorship Guardian Preferences Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sponsorship/pool/join":{"post":{"tags":["sponsorship"],"summary":"Join Sponsorship Pool","description":"Add the current user to the sponsorship waiting pool.","operationId":"join_sponsorship_pool_api_sponsorship_pool_join_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Join Sponsorship Pool Api Sponsorship Pool Join Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sponsorship/pool/leave":{"post":{"tags":["sponsorship"],"summary":"Leave Sponsorship Pool","description":"Remove the current user from the sponsorship waiting pool.","operationId":"leave_sponsorship_pool_api_sponsorship_pool_leave_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Leave Sponsorship Pool Api Sponsorship Pool Leave Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sponsorship/pool/status":{"get":{"tags":["sponsorship"],"summary":"Get Pool Status","description":"Get the current user's sponsorship pool status.\nReturns the pool record with a 'status' field, or {'status': null} if\nthe user has never joined.","operationId":"get_pool_status_api_sponsorship_pool_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Pool Status Api Sponsorship Pool Status Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sponsorship/pool/assign":{"post":{"tags":["sponsorship"],"summary":"Assign Sponsorships","description":"Admin endpoint: assign unassigned sponsorship slots to waiting pool users\nand send push notifications to newly sponsored recipients.","operationId":"assign_sponsorships_api_sponsorship_pool_assign_post","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":250,"title":"Limit"}},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Assign Sponsorships Api Sponsorship Pool Assign Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sponsorship/kindness-wall":{"get":{"tags":["sponsorship"],"summary":"Get Kindness Wall","description":"Fetch recent sponsorships shared on the kindness wall.","operationId":"get_kindness_wall_api_sponsorship_kindness_wall_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Kindness Wall Api Sponsorship Kindness Wall Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sponsorship/ramp/status":{"get":{"tags":["sponsorship"],"summary":"Get Ramp Status","description":"Get the current user's ramp sponsorship status.\n\nReturns null if the user has never been ramp-sponsored.\nReturns the record with active=true if currently within the sponsorship window,\nor active=false if the sponsorship has expired.","operationId":"get_ramp_status_api_sponsorship_ramp_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"title":"Response Get Ramp Status Api Sponsorship Ramp Status Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gifts/code":{"post":{"tags":["gifts"],"summary":"Create Gift Code","description":"Create a new gift code for the authenticated user.\n\nThis endpoint creates a gift code that can be shared with others.\nThe gift code grants 1 year of premium access when redeemed.\n\nArgs:\n    request: CreateGiftCodeRequest with RevenueCat product and purchase IDs\n\nReturns:\n    CreateGiftCodeResponse with the generated gift code","operationId":"create_gift_code_api_gifts_code_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGiftCodeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGiftCodeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gifts/my-codes":{"get":{"tags":["gifts"],"summary":"Get My Gift Codes","description":"Get all gift codes created by the authenticated user.\n\nThis endpoint returns a list of all gift codes the user has created,\nincluding their redemption status.\n\nReturns:\n    MyGiftCodesResponse with list of gift codes and counts","operationId":"get_my_gift_codes_api_gifts_my_codes_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyGiftCodesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gifts/redeem":{"post":{"tags":["gifts"],"summary":"Redeem Gift Code","description":"Redeem a gift code to receive 1 year of premium access.\n\nThe premium access is stacked on top of any existing subscription.\nUsers cannot redeem their own gift codes.\n\nArgs:\n    request: RedeemGiftCodeRequest with the gift code\n\nReturns:\n    RedeemGiftCodeResponse with success status and message","operationId":"redeem_gift_code_api_gifts_redeem_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedeemGiftCodeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedeemGiftCodeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends":{"get":{"tags":["friends"],"summary":"Get My Friends","description":"Get all friends for the current user with their profile information.\n\nArgs:\n    current_user: Current authenticated user from dependency\n\nReturns:\n    Dict with list of friends","operationId":"get_my_friends_api_friends_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get My Friends Api Friends Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/requests":{"get":{"tags":["friends"],"summary":"Get My Friend Requests","description":"Get all pending friend requests received by the current user.\n\nArgs:\n    current_user: Current authenticated user from dependency\n\nReturns:\n    Dict with list of pending friend requests","operationId":"get_my_friend_requests_api_friends_requests_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get My Friend Requests Api Friends Requests Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/requests/sent":{"get":{"tags":["friends"],"summary":"Get My Sent Friend Requests","description":"Get all pending friend requests sent by the current user.\n\nArgs:\n    current_user: Current authenticated user from dependency\n\nReturns:\n    Dict with list of pending sent friend requests","operationId":"get_my_sent_friend_requests_api_friends_requests_sent_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get My Sent Friend Requests Api Friends Requests Sent Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/search/{user_id}":{"get":{"tags":["friends"],"summary":"Search User","description":"Search for a user by ID and check if already friends.\n\nArgs:\n    user_id: ID of the user to search for\n    allow_self_search: If true, allow looking up the authenticated user by their own ID\n    current_user: Current authenticated user from dependency\n\nReturns:\n    Dict with user info and friendship status","operationId":"search_user_api_friends_search__user_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"allow_self_search","in":"query","required":false,"schema":{"type":"boolean","description":"When true, searching for your own user ID returns your profile instead of an error.","default":false,"title":"Allow Self Search"},"description":"When true, searching for your own user ID returns your profile instead of an error."},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Search User Api Friends Search  User Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/request/send/{receiver_id}":{"post":{"tags":["friends"],"summary":"Send Friend Request","description":"Send a friend request to another user.\n\nArgs:\n    receiver_id: ID of the user to send friend request to\n    current_user: Current authenticated user from dependency\n\nReturns:\n    Dict with the created friend request","operationId":"send_friend_request_api_friends_request_send__receiver_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"receiver_id","in":"path","required":true,"schema":{"type":"string","title":"Receiver Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Send Friend Request Api Friends Request Send  Receiver Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/nudge/{friend_id}":{"post":{"tags":["friends"],"summary":"Nudge Friend","description":"Send a push notification nudge to a friend.\n\nTitle is the current user's first name; body is the text from the request body.","operationId":"nudge_friend_api_friends_nudge__friend_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"friend_id","in":"path","required":true,"schema":{"type":"string","title":"Friend Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NudgeFriendRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Nudge Friend Api Friends Nudge  Friend Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/auto-add/{sender_id}":{"post":{"tags":["friends"],"summary":"Auto Add Friend","description":"Directly add a user as a friend without a request/accept flow.\n\nThe caller is the receiver — they include the sender_id (the user who shared their ID).\nThe sender receives the notification.","operationId":"auto_add_friend_api_friends_auto_add__sender_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sender_id","in":"path","required":true,"schema":{"type":"string","title":"Sender Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Auto Add Friend Api Friends Auto Add  Sender Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/remove/{friend_id}":{"post":{"tags":["friends"],"summary":"Remove Friend","description":"Remove an existing friendship with another user.\n\nEnds any active friend streak partnership with the friend (best effort)\nbefore removing the bidirectional friendship rows.","operationId":"remove_friend_api_friends_remove__friend_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"friend_id","in":"path","required":true,"schema":{"type":"string","title":"Friend Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Remove Friend Api Friends Remove  Friend Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/request/accept/{request_id}":{"post":{"tags":["friends"],"summary":"Accept Friend Request","description":"Accept a friend request by ID.\n\nArgs:\n    request_id: ID of the friend request\n    current_user: Current authenticated user from dependency\n\nReturns:\n    Dict with success status and friendship details","operationId":"accept_friend_request_api_friends_request_accept__request_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}},{"name":"enable_grants","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Enable Grants"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Accept Friend Request Api Friends Request Accept  Request Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/request/reject/{request_id}":{"post":{"tags":["friends"],"summary":"Reject Friend Request","description":"Reject a friend request by ID.\n\nArgs:\n    request_id: ID of the friend request\n    current_user: Current authenticated user from dependency\n\nReturns:\n    Dict with success status","operationId":"reject_friend_request_api_friends_request_reject__request_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Reject Friend Request Api Friends Request Reject  Request Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/request/cancel/{request_id}":{"post":{"tags":["friends"],"summary":"Cancel Friend Request","description":"Cancel a friend request by ID (sender can cancel their own sent request).\n\nArgs:\n    request_id: ID of the friend request\n    current_user: Current authenticated user from dependency\n\nReturns:\n    Dict with success status","operationId":"cancel_friend_request_api_friends_request_cancel__request_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Cancel Friend Request Api Friends Request Cancel  Request Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/streaks/auto-start/{sender_id}":{"post":{"tags":["friends"],"summary":"Auto Start Streak","description":"Directly add a user as a friend and immediately start an active streak.\n\nThe caller is the receiver — they include the sender_id (the user who shared their ID).\nThe sender receives the notifications.","operationId":"auto_start_streak_api_friends_streaks_auto_start__sender_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sender_id","in":"path","required":true,"schema":{"type":"string","title":"Sender Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Auto Start Streak Api Friends Streaks Auto Start  Sender Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/streaks":{"get":{"tags":["friends"],"summary":"List Friend Streaks","description":"List active friend streak partnerships for the current user.","operationId":"list_friend_streaks_api_friends_streaks_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Friend Streaks Api Friends Streaks Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/streaks/requests":{"get":{"tags":["friends"],"summary":"Get Friend Streak Requests Incoming","description":"Pending friend streak requests received by the current user.","operationId":"get_friend_streak_requests_incoming_api_friends_streaks_requests_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Friend Streak Requests Incoming Api Friends Streaks Requests Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/streaks/requests/sent":{"get":{"tags":["friends"],"summary":"Get Friend Streak Requests Sent","description":"Pending friend streak requests sent by the current user.","operationId":"get_friend_streak_requests_sent_api_friends_streaks_requests_sent_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Friend Streak Requests Sent Api Friends Streaks Requests Sent Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/streaks/{friend_id}":{"get":{"tags":["friends"],"summary":"Get Friend Streak With Friend","description":"Get active friend streak row + partner profile for one friend.","operationId":"get_friend_streak_with_friend_api_friends_streaks__friend_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"friend_id","in":"path","required":true,"schema":{"type":"string","title":"Friend Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Friend Streak With Friend Api Friends Streaks  Friend Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/streaks/request/send/{receiver_id}":{"post":{"tags":["friends"],"summary":"Send Friend Streak Request","description":"Send a friend streak request (must already be friends).","operationId":"send_friend_streak_request_api_friends_streaks_request_send__receiver_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"receiver_id","in":"path","required":true,"schema":{"type":"string","title":"Receiver Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Send Friend Streak Request Api Friends Streaks Request Send  Receiver Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/streaks/request/accept/{request_id}":{"post":{"tags":["friends"],"summary":"Accept Friend Streak Request","description":"Accept a pending friend streak request.","operationId":"accept_friend_streak_request_api_friends_streaks_request_accept__request_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Accept Friend Streak Request Api Friends Streaks Request Accept  Request Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/streaks/request/reject/{request_id}":{"post":{"tags":["friends"],"summary":"Reject Friend Streak Request","description":"Reject a pending friend streak request.","operationId":"reject_friend_streak_request_api_friends_streaks_request_reject__request_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Reject Friend Streak Request Api Friends Streaks Request Reject  Request Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/streaks/request/cancel/{request_id}":{"post":{"tags":["friends"],"summary":"Cancel Friend Streak Request","description":"Cancel a pending friend streak request (sender only).","operationId":"cancel_friend_streak_request_api_friends_streaks_request_cancel__request_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Cancel Friend Streak Request Api Friends Streaks Request Cancel  Request Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/streaks/end/{friend_id}":{"post":{"tags":["friends"],"summary":"End Friend Streak","description":"End an active friend streak partnership with the given friend.","operationId":"end_friend_streak_api_friends_streaks_end__friend_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"friend_id","in":"path","required":true,"schema":{"type":"string","title":"Friend Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response End Friend Streak Api Friends Streaks End  Friend Id  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/friends/streaks/send-reminders-cron":{"post":{"tags":["friends"],"summary":"Send Friend Streak Reminders Cron","description":"Cron endpoint to send friend streak loss reminders via Expo push.\n\nPOST /api/friends/streaks/send-reminders-cron\n\nFor each active streak pair (streak_count >= 2) at risk of expiring,\nnotifies the partner who has completed today to nudge their friend.\nWhen neither has completed, user_a (canonical first partner) is notified.\nUsers with multiple at-risk pairs receive one grouped notification.\n\nRuns at 10 PM–11:45 PM local time (cron every 30 minutes).\nRequires x-api-key header for authentication.","operationId":"send_friend_streak_reminders_cron_api_friends_streaks_send_reminders_cron_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/group-chat/provision":{"post":{"tags":["group-chat"],"summary":"Provision Group Chat","description":"Idempotently provisions:\n  1. A Mattermost team for the user's church (if missing)\n  2. A Mattermost user for the caller (if missing)\n  3. Membership in the team\n  4. A fresh PAT for the user\n\nReturns the credentials the RN client needs to connect via WebSocket.","operationId":"provision_group_chat_api_group_chat_provision_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvisionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/group-chat/me":{"get":{"tags":["group-chat"],"summary":"Get My Identity","description":"Returns existing mappings without creating anything. Useful for debugging.","operationId":"get_my_identity_api_group_chat_me_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdentityResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/group-chat/members":{"post":{"tags":["group-chat"],"summary":"Get Group Chat Members","description":"Resolve a batch of Mattermost user ids to app-side profile fields\n(first_name, last_name, profile_picture). Used by the client to render\navatars/names without leaking other PII.","operationId":"get_group_chat_members_api_group_chat_members_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembersRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembersResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/group-chat-city/provision":{"post":{"tags":["group-chat-city"],"summary":"Provision City Group Chat","description":"Idempotently provisions the caller into their city's private channel:\n  1. A Mattermost channel for the user's city (if missing)\n  2. A Mattermost user for the caller (if missing, shared with /group-chat)\n  3. Membership in the global team and the city channel\n  4. A fresh PAT for the user\n\nThe city allow-list is enforced here rather than only in the client, so an\noutdated or tampered build can't provision itself into a city we haven't\nlaunched.","operationId":"provision_city_group_chat_api_group_chat_city_provision_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CityProvisionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/group-chat-city/me":{"get":{"tags":["group-chat-city"],"summary":"Get My City Identity","description":"Returns existing mappings without creating anything. Useful for debugging.","operationId":"get_my_city_identity_api_group_chat_city_me_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CityIdentityResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/group-chat-city/members":{"post":{"tags":["group-chat-city"],"summary":"Get City Group Chat Members","description":"Resolve a batch of Mattermost user ids to app-side profile fields\n(first_name, last_name, profile_picture, church_name). Used by the client to\nrender avatars/names without leaking other PII.","operationId":"get_city_group_chat_members_api_group_chat_city_members_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CityMembersRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CityMembersResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/social-feed/friends":{"get":{"tags":["social-feed"],"summary":"Get Friends Social Feed","description":"Return social feed events from the authenticated user's friends,\nordered by most recent first.","operationId":"get_friends_social_feed_api_social_feed_friends_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SocialFeedEventResponse"},"title":"Response Get Friends Social Feed Api Social Feed Friends Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/social-feed/church":{"get":{"tags":["social-feed"],"summary":"Get Church Social Feed","description":"Return social feed events from all members of a church, ordered by most recent\nfirst. If `church_id` is provided, return events for that church; otherwise fall\nback to the authenticated user's home church.","operationId":"get_church_social_feed_api_social_feed_church_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":10,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"church_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"Church Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SocialFeedEventResponse"},"title":"Response Get Church Social Feed Api Social Feed Church Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/churches/suggestions":{"get":{"tags":["churches"],"summary":"Get Church Suggestions","description":"Get top 10 church suggestions matching the search query.\nSplits query into words and matches each word against search_text.\nReturns empty list if query is empty.","operationId":"get_church_suggestions_api_churches_suggestions_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"Search query string","default":"","title":"Q"},"description":"Search query string"},{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"City to prioritize results from","title":"City"},"description":"City to prioritize results from"},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"State ISO code to prioritize results from","title":"State"},"description":"State ISO code to prioritize results from"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChurchSuggestionsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/churches/in-bounds":{"get":{"tags":["churches"],"summary":"Get Churches In Bounds","operationId":"get_churches_in_bounds_api_churches_in_bounds_get","parameters":[{"name":"north","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"title":"North"}},{"name":"south","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"title":"South"}},{"name":"east","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"title":"East"}},{"name":"west","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"title":"West"}},{"name":"zoom","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":22,"minimum":0},{"type":"null"}],"title":"Zoom"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":500,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChurchesInBoundsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/churches/{church_id}":{"get":{"tags":["churches"],"summary":"Get Church By Id","operationId":"get_church_by_id_api_churches__church_id__get","parameters":[{"name":"church_id","in":"path","required":true,"schema":{"type":"integer","title":"Church Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChurchDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/churches/google/autocomplete":{"post":{"tags":["churches"],"summary":"Google Autocomplete","operationId":"google_autocomplete_api_churches_google_autocomplete_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleAutocompleteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleAutocompleteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/churches/google/preview":{"post":{"tags":["churches"],"summary":"Google Preview","operationId":"google_preview_api_churches_google_preview_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GooglePreviewRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GooglePreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/churches/google/select":{"post":{"tags":["churches"],"summary":"Google Select","operationId":"google_select_api_churches_google_select_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleSelectRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleSelectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/churches/validate-and-submit":{"post":{"tags":["churches"],"summary":"Validate And Submit Church","operationId":"validate_and_submit_church_api_churches_validate_and_submit_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChurchValidationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChurchValidationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/churches/send-rsvp-reminders-cron":{"post":{"tags":["churches"],"summary":"Send Church Rsvp Reminders Cron","description":"Cron endpoint to send weekend Mass commitment reminders.\nRuns every hour on Friday and Saturday (UTC).\nPer-user local time filtering (>= 5 PM) is handled inside the task.","operationId":"send_church_rsvp_reminders_cron_api_churches_send_rsvp_reminders_cron_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/churches/just-validate":{"post":{"tags":["churches"],"summary":"Just Validate Church","operationId":"just_validate_church_api_churches_just_validate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChurchValidationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChurchValidationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/spotlight/seen":{"get":{"tags":["spotlight"],"summary":"Get Seen","operationId":"get_seen_api_spotlight_seen_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SeenEntry"},"title":"Response Get Seen Api Spotlight Seen Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["spotlight"],"summary":"Mark Seen","operationId":"mark_seen_api_spotlight_seen_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkSeenRequest"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/church-announcements":{"get":{"tags":["church-announcements"],"summary":"Get Announcements","operationId":"get_announcements_api_church_announcements_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Limit"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AnnouncementResponse"},"title":"Response Get Announcements Api Church Announcements Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/church-announcements/{announcement_id}":{"get":{"tags":["church-announcements"],"summary":"Get Announcement","operationId":"get_announcement_api_church_announcements__announcement_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"announcement_id","in":"path","required":true,"schema":{"type":"integer","title":"Announcement Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnnouncementResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/church-admin/login":{"post":{"tags":["church-admin"],"summary":"Login","operationId":"login_api_church_admin_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/church-admin/profile":{"get":{"tags":["church-admin"],"summary":"Get Profile","operationId":"get_profile_api_church_admin_profile_get","parameters":[{"name":"ca_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ca Session"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/church-admin/logout":{"post":{"tags":["church-admin"],"summary":"Logout","operationId":"logout_api_church_admin_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/church-admin/church":{"get":{"tags":["church-admin"],"summary":"Get Church Preview","description":"What the church's profile currently shows in the app: service times,\nupcoming events (website-crawled + admin-submitted), and basic info.","operationId":"get_church_preview_api_church_admin_church_get","parameters":[{"name":"ca_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ca Session"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChurchPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/church-admin/events":{"post":{"tags":["church-admin"],"summary":"Create Event","operationId":"create_event_api_church_admin_events_post","parameters":[{"name":"ca_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ca Session"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEventRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChurchAdminEventResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["church-admin"],"summary":"List Events","operationId":"list_events_api_church_admin_events_get","parameters":[{"name":"ca_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ca Session"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ChurchAdminEventResponse"},"title":"Response List Events Api Church Admin Events Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/church-admin/events/{event_id}":{"delete":{"tags":["church-admin"],"summary":"Delete Event","operationId":"delete_event_api_church_admin_events__event_id__delete","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"integer","title":"Event Id"}},{"name":"ca_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ca Session"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/church-admin/announcements":{"post":{"tags":["church-admin"],"summary":"Create Announcement","operationId":"create_announcement_api_church_admin_announcements_post","parameters":[{"name":"ca_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ca Session"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAnnouncementRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnnouncementResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["church-admin"],"summary":"List Announcements","operationId":"list_announcements_api_church_admin_announcements_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Limit"}},{"name":"ca_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ca Session"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AnnouncementResponse"},"title":"Response List Announcements Api Church Admin Announcements Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/church-admin/announcements/{announcement_id}":{"get":{"tags":["church-admin"],"summary":"Get Announcement","operationId":"get_announcement_api_church_admin_announcements__announcement_id__get","parameters":[{"name":"announcement_id","in":"path","required":true,"schema":{"type":"integer","title":"Announcement Id"}},{"name":"ca_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ca Session"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnnouncementResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["church-admin"],"summary":"Delete Announcement","operationId":"delete_announcement_api_church_admin_announcements__announcement_id__delete","parameters":[{"name":"announcement_id","in":"path","required":true,"schema":{"type":"integer","title":"Announcement Id"}},{"name":"ca_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ca Session"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/time-spent":{"post":{"tags":["time-spent"],"summary":"Submit Time","description":"Submit time spent to track time in the app.","operationId":"submit_time_api_time_spent_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitTimeSpentRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitTimeSpentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["time-spent"],"summary":"Get Total Time Spent","description":"Get total time spent by the user across all sessions.\nReturns time in minutes.","operationId":"get_total_time_spent_api_time_spent_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TotalTimeSpentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leaderboard/country":{"get":{"tags":["leaderboard"],"summary":"Get Country Leaderboard","description":"Get the country-level leaderboard based on streak count.\nReturns users from the same country as the authenticated user.","operationId":"get_country_leaderboard_api_leaderboard_country_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaderboardResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leaderboard/church":{"get":{"tags":["leaderboard"],"summary":"Get Church Leaderboard","description":"Get the community leaderboard based on streak count.\nReturns users from the authenticated user's church PLUS their friends\n(community view used by the main LeaderboardView).\n\nNote: This is the church + friends view. For a leaderboard restricted\nto members of a specific church only, use GET /leaderboard/by-church/{church_id}.","operationId":"get_church_leaderboard_api_leaderboard_church_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaderboardResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leaderboard/by-church/{church_id}":{"get":{"tags":["leaderboard"],"summary":"Get Leaderboard By Church","description":"Get the streak leaderboard for a specific church id.\nReturns all users in that church, ranked by streak count.\nUsed by the church map detail view, and by the church-admin dashboard\n(authenticated with the church-admin session cookie for its own church).","operationId":"get_leaderboard_by_church_api_leaderboard_by_church__church_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"church_id","in":"path","required":true,"schema":{"type":"integer","title":"Church Id"}},{"name":"ca_session","in":"cookie","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ca Session"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaderboardResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/leaderboard/global":{"get":{"tags":["leaderboard"],"summary":"Get Global Leaderboard","description":"Get the global leaderboard based on streak count.\nReturns all users ranked by their streak count.","operationId":"get_global_leaderboard_api_leaderboard_global_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaderboardResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/live-streams/active":{"get":{"tags":["live-streams"],"summary":"Get Active Stream","operationId":"get_active_stream_api_live_streams_active_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveStreamResponse"}}}}}}},"/api/live-streams/start":{"post":{"tags":["live-streams"],"summary":"Start Stream","operationId":"start_stream_api_live_streams_start_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartStreamRequest","default":{}}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Start Stream Api Live Streams Start Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/live-streams/stop":{"post":{"tags":["live-streams"],"summary":"Stop Stream","operationId":"stop_stream_api_live_streams_stop_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Stop Stream Api Live Streams Stop Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/live-streams/{stream_id}/comments":{"post":{"tags":["live-streams"],"summary":"Submit Live Stream Comment","description":"Submit a comment on a live stream.","operationId":"submit_live_stream_comment_api_live_streams__stream_id__comments_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"stream_id","in":"path","required":true,"schema":{"type":"integer","title":"Stream Id"}},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitLiveStreamCommentRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitLiveStreamCommentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["live-streams"],"summary":"Get Live Stream Comments","description":"Get comments for a live stream. Pass `since` for incremental fetching.","operationId":"get_live_stream_comments_api_live_streams__stream_id__comments_get","parameters":[{"name":"stream_id","in":"path","required":true,"schema":{"type":"integer","title":"Stream Id"}},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO timestamp — return only comments after this time","title":"Since"},"description":"ISO timestamp — return only comments after this time"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LiveStreamComment"},"title":"Response Get Live Stream Comments Api Live Streams  Stream Id  Comments Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/achievements/all":{"get":{"tags":["achievements"],"summary":"Get All Achievements","description":"Fetch all active achievements available in the system.","operationId":"get_all_achievements_api_achievements_all_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AchievementResponse"},"title":"Response Get All Achievements Api Achievements All Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/achievements":{"get":{"tags":["achievements"],"summary":"Get User Achievements","description":"Fetch all achievements unlocked by the authenticated user.\n\nReturns achievements with their details in chronological order (most recent first).","operationId":"get_user_achievements_api_achievements_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserAchievementResponse"},"title":"Response Get User Achievements Api Achievements Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/achievements/unlock":{"post":{"tags":["achievements"],"summary":"Unlock Achievement","description":"Manually unlock an achievement for the authenticated user.\n\n- **achievement_key**: The unique key of the achievement to unlock (e.g., 'BIBLE_READ_10')\n\nReturns a success message with the unlocked achievement details.","operationId":"unlock_achievement_api_achievements_unlock_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnlockAchievementRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Unlock Achievement Api Achievements Unlock Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gamification/rewards":{"get":{"tags":["gamification"],"summary":"Get Rewards","description":"Get all active token rewards.\n\nReturns a list of all active rewards with their token amounts.","operationId":"get_rewards_api_gamification_rewards_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RewardResponse"},"title":"Response Get Rewards Api Gamification Rewards Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gamification/rewards/earn":{"post":{"tags":["gamification"],"summary":"Earn Reward","description":"Award tokens to the user for completing a reward source.\n\n- **reward_key**: The reward key identifier (e.g., 'quest_daily_reading', 'achievement_bible_read_10')\n\nThis endpoint is called when a user completes a quest, achievement, daily login, etc.\nThe token amount is determined by the reward configuration in the database.","operationId":"earn_reward_api_gamification_rewards_earn_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EarnRewardRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EarnTokensResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gamification/tokens/earn":{"post":{"tags":["gamification"],"summary":"Earn Tokens","description":"Award a custom amount of tokens to the user directly.\n\n- **amount**: Number of tokens to award\n- **source**: Label describing the source of the award\n\nThis endpoint bypasses reward configuration and awards tokens directly.","operationId":"earn_tokens_api_gamification_tokens_earn_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EarnTokensRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EarnTokensResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gamification/tokens/transactions":{"get":{"tags":["gamification"],"summary":"Get Transactions","description":"Get transaction history for the authenticated user.\n\nReturns a list of token transactions (both earned and spent) with details.","operationId":"get_transactions_api_gamification_tokens_transactions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Number of transactions to return","default":50,"title":"Limit"},"description":"Number of transactions to return"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Number of transactions to skip","default":0,"title":"Offset"},"description":"Number of transactions to skip"},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TokenTransactionResponse"},"title":"Response Get Transactions Api Gamification Tokens Transactions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gamification/tokens/products":{"get":{"tags":["gamification"],"summary":"Get Token Products","description":"Get the active token product catalog available for purchase.\n\nReturns purchasable token packs keyed by a stable default id, along with\nthe underlying App Store / Play Store product ids for each platform.","operationId":"get_token_products_api_gamification_tokens_products_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenProductsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gamification/items":{"get":{"tags":["gamification"],"summary":"Get Shop Items","description":"Get all currently available shop items.\n\nReturns items that are currently available (within their availability window).\nUse /items/unlocked endpoint to determine which items the user owns.","operationId":"get_shop_items_api_gamification_items_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"pricing_variant","in":"query","required":false,"schema":{"$ref":"#/components/schemas/PricingVariant","description":"Which price to return as token_price -- 'paid_tokens' for the paid_token_exp treatment cohort","default":"default"},"description":"Which price to return as token_price -- 'paid_tokens' for the paid_token_exp treatment cohort"},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ItemResponse"},"title":"Response Get Shop Items Api Gamification Items Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gamification/items/unlocked":{"get":{"tags":["gamification"],"summary":"Get Unlocked Items","description":"Get all items unlocked by the authenticated user with full item details.\n\nReturns a list of unlocked items with full marketplace details plus unlock timestamps.","operationId":"get_unlocked_items_api_gamification_items_unlocked_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"pricing_variant","in":"query","required":false,"schema":{"$ref":"#/components/schemas/PricingVariant","description":"Which price to return as token_price -- 'paid_tokens' for the paid_token_exp treatment cohort","default":"default"},"description":"Which price to return as token_price -- 'paid_tokens' for the paid_token_exp treatment cohort"},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UnlockedItemResponse"},"title":"Response Get Unlocked Items Api Gamification Items Unlocked Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gamification/items/purchase":{"post":{"tags":["gamification"],"summary":"Purchase Item","description":"Purchase an item with tokens.\n\n- **item_key**: The unique key of the item to purchase (e.g., 'theme_ocean', 'frame_gold')\n\nThis endpoint validates the user's token balance, deducts the tokens,\nand grants the item to the user. Returns the new balance and item details.","operationId":"purchase_item_api_gamification_items_purchase_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"pricing_variant","in":"query","required":false,"schema":{"$ref":"#/components/schemas/PricingVariant","description":"Which price to charge -- 'paid_tokens' for the paid_token_exp treatment cohort","default":"default"},"description":"Which price to charge -- 'paid_tokens' for the paid_token_exp treatment cohort"},{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemActionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemActionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/gamification/items/unlock":{"post":{"tags":["gamification"],"summary":"Unlock Item","description":"Unlock an item for the user without spending tokens.\n\n- **item_key**: The unique key of the item to unlock (e.g., 'theme_premium_dark', 'icon_special_event')\n\nThis endpoint is for unlocking premium items, special event items, or other\nitems that don't require token payment. No transaction is created.","operationId":"unlock_item_api_gamification_items_unlock_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-user-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-User-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemActionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemActionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/webhooks/revenuecat":{"post":{"tags":["webhooks"],"summary":"Revenuecat Webhook","description":"Single entry point for all RevenueCat webhook events.\n\nRevenueCat sends every event for the app to this one endpoint regardless\nof product. Each domain service owns its own product-id/event-type\nfiltering and no-ops on events that aren't relevant to it, so the event\nis simply handed to every domain that consumes RevenueCat events.\n\nProcessing is awaited rather than backgrounded, and unexpected errors are\nintentionally left to propagate (see each service's handle_* method) so a\ngenuine failure surfaces as a non-2xx response and RevenueCat retries\ndelivery. All DB writes here are idempotent, so a retry is always safe --\nthis also means a crash mid-processing just results in RC redelivering,\nrather than the event being silently lost.","operationId":"revenuecat_webhook_api_webhooks_revenuecat_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Revenuecat Webhook Api Webhooks Revenuecat Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/b2b/chatbot":{"post":{"tags":["b2b"],"summary":"Chat","operationId":"chat_api_b2b_chatbot_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2BChatRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2BChatResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/analytics":{"get":{"tags":["Admin Analytics"],"summary":"Get Analytics","description":"Start analytics generation in background and send results to Slack.\nReturns immediately to avoid timeout issues.\n\nProcess:\n1. Returns success response immediately\n2. Runs analytics in background (identifies top users, analyzes messages)\n3. Sends formatted report to Slack webhook\n\nThe Slack report will include:\n- Key insights and patterns\n- Top users list with message counts\n- Urgent concerns and recommendations\n- Spiritual themes and engagement insights","operationId":"get_analytics_admin_analytics_get","parameters":[{"name":"days_back","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"description":"Number of days to look back","default":7,"title":"Days Back"},"description":"Number of days to look back"},{"name":"user_limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"description":"Number of top users to analyze","default":20,"title":"User Limit"},"description":"Number of top users to analyze"},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/attribution/cost-per-trial":{"get":{"tags":["Admin Attribution"],"summary":"Get Cost Per Trial","operationId":"get_cost_per_trial_admin_attribution_cost_per_trial_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"enum":["7","30","90","180"],"type":"string","default":"30","title":"Days"}},{"name":"grouping","in":"query","required":false,"schema":{"enum":["day","week","month"],"type":"string","default":"day","title":"Grouping"}},{"name":"platform","in":"query","required":false,"schema":{"enum":["all","ios","android"],"type":"string","default":"all","title":"Platform"}},{"name":"refresh","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Refresh"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/attribution/cost-per-subscriber":{"get":{"tags":["Admin Attribution"],"summary":"Get Cost Per Subscriber","operationId":"get_cost_per_subscriber_admin_attribution_cost_per_subscriber_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"enum":["7","30","90","180"],"type":"string","default":"30","title":"Days"}},{"name":"grouping","in":"query","required":false,"schema":{"enum":["day","week","month"],"type":"string","default":"day","title":"Grouping"}},{"name":"platform","in":"query","required":false,"schema":{"enum":["all","ios","android"],"type":"string","default":"all","title":"Platform"}},{"name":"refresh","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Refresh"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/attribution/d8-roas":{"get":{"tags":["Admin Attribution"],"summary":"Get D7 Roas","operationId":"get_d7_roas_admin_attribution_d8_roas_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"enum":["7","30","90","180"],"type":"string","default":"30","title":"Days"}},{"name":"grouping","in":"query","required":false,"schema":{"enum":["day","week","month"],"type":"string","default":"day","title":"Grouping"}},{"name":"platform","in":"query","required":false,"schema":{"enum":["all","ios","android"],"type":"string","default":"all","title":"Platform"}},{"name":"refresh","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Refresh"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/attribution/d7-roas":{"get":{"tags":["Admin Attribution"],"summary":"Get D7 Roas","operationId":"get_d7_roas_admin_attribution_d7_roas_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"enum":["7","30","90","180"],"type":"string","default":"30","title":"Days"}},{"name":"grouping","in":"query","required":false,"schema":{"enum":["day","week","month"],"type":"string","default":"day","title":"Grouping"}},{"name":"platform","in":"query","required":false,"schema":{"enum":["all","ios","android"],"type":"string","default":"all","title":"Platform"}},{"name":"refresh","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Refresh"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/attribution/global-roas":{"get":{"tags":["Admin Attribution"],"summary":"Get Global Roas","operationId":"get_global_roas_admin_attribution_global_roas_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"enum":["7","30","90","180"],"type":"string","default":"30","title":"Days"}},{"name":"grouping","in":"query","required":false,"schema":{"enum":["day","week","month"],"type":"string","default":"day","title":"Grouping"}},{"name":"platform","in":"query","required":false,"schema":{"enum":["all","ios","android"],"type":"string","default":"all","title":"Platform"}},{"name":"refresh","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Refresh"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/attribution/trial-to-paid-conversion":{"get":{"tags":["Admin Attribution"],"summary":"Get Trial To Paid Conversion","operationId":"get_trial_to_paid_conversion_admin_attribution_trial_to_paid_conversion_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"enum":["7","30","90","180"],"type":"string","default":"30","title":"Days"}},{"name":"grouping","in":"query","required":false,"schema":{"enum":["day","week","month"],"type":"string","default":"day","title":"Grouping"}},{"name":"platform","in":"query","required":false,"schema":{"enum":["all","ios","android"],"type":"string","default":"all","title":"Platform"}},{"name":"refresh","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Refresh"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/attribution/meta-spend":{"get":{"tags":["Admin Attribution"],"summary":"Get Meta Spend","operationId":"get_meta_spend_admin_attribution_meta_spend_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"enum":["7","30","90","180"],"type":"string","default":"30","title":"Days"}},{"name":"grouping","in":"query","required":false,"schema":{"enum":["day","week","month"],"type":"string","default":"day","title":"Grouping"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/azure-openai-test":{"post":{"tags":["azure-openai-test"],"summary":"Azure Openai Test","description":"Isolated test endpoint for Azure OpenAI chat completions.\nDoes not touch existing services - used only for validation.","operationId":"azure_openai_test_api_azure_openai_test_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AzureChatRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AzureChatResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/azure-tts-test":{"post":{"tags":["azure-tts-test"],"summary":"Azure Tts Test","description":"Isolated test endpoint for Azure OpenAI TTS.\nReturns audio bytes directly for testing.","operationId":"azure_tts_test_api_azure_tts_test_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AzureTTSRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AchievementResponse":{"properties":{"id":{"type":"string","title":"Id"},"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"type":{"type":"string","title":"Type"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"stackable":{"type":"boolean","title":"Stackable"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"threshold":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Threshold"}},"type":"object","required":["id","key","title","type","stackable"],"title":"AchievementResponse","description":"Achievement response model (public-facing)."},"ActiveStreamResponse":{"properties":{"stream":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Stream"}},"type":"object","title":"ActiveStreamResponse"},"AddGratitudeRequest":{"properties":{"gratitude_text":{"type":"string","title":"Gratitude Text"}},"type":"object","required":["gratitude_text"],"title":"AddGratitudeRequest"},"AddPrayerJournalRequest":{"properties":{"prayer_text":{"type":"string","title":"Prayer Text"},"topic":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Topic"}},"type":"object","required":["prayer_text"],"title":"AddPrayerJournalRequest"},"AnnouncementResponse":{"properties":{"id":{"type":"integer","title":"Id"},"title":{"type":"string","title":"Title"},"short_description":{"type":"string","title":"Short Description"},"long_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Long Description"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["id","title","short_description","created_at"],"title":"AnnouncementResponse"},"AppendProgressRequest":{"properties":{"book_id":{"type":"string","title":"Book Id","description":"Book ID (e.g., '1' for Genesis, '40' for Matthew)"},"book_code":{"type":"string","title":"Book Code","description":"Book code (e.g., 'GEN', 'MAT', 'JOH')"},"chapter":{"type":"integer","exclusiveMinimum":0.0,"title":"Chapter","description":"Chapter number to append"},"version":{"type":"string","title":"Version","description":"Bible version (e.g., 'KJV', 'NIV', 'ESV')"}},"type":"object","required":["book_id","book_code","chapter","version"],"title":"AppendProgressRequest","description":"Request model for appending Bible reading progress."},"ApproveRejectResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"prayer_id":{"type":"integer","title":"Prayer Id"}},"type":"object","required":["success","prayer_id"],"title":"ApproveRejectResponse"},"AzureChatRequest":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"AzureChatRequest"},"AzureChatResponse":{"properties":{"text":{"type":"string","title":"Text"},"model":{"type":"string","title":"Model"},"success":{"type":"boolean","title":"Success"}},"type":"object","required":["text","model","success"],"title":"AzureChatResponse"},"AzureTTSRequest":{"properties":{"text":{"type":"string","title":"Text"},"voice":{"type":"string","title":"Voice","default":"echo"}},"type":"object","required":["text"],"title":"AzureTTSRequest"},"B2BChatRequest":{"properties":{"message":{"type":"string","title":"Message"},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"},"church_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Church Name"},"church_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Church Url"},"bible_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bible Version"}},"type":"object","required":["message"],"title":"B2BChatRequest"},"B2BChatResponse":{"properties":{"reply":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reply"},"conversation_id":{"type":"string","title":"Conversation Id"},"bible_verses":{"items":{"type":"string"},"type":"array","title":"Bible Verses","default":[]},"sources":{"anyOf":[{"items":{"$ref":"#/components/schemas/Source"},"type":"array"},{"type":"null"}],"title":"Sources"},"thoughts":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thoughts"}},"type":"object","required":["conversation_id"],"title":"B2BChatResponse"},"BibleProgressResponse":{"properties":{"id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Id"},"user_id":{"type":"string","title":"User Id"},"progress":{"additionalProperties":{"items":{"type":"integer"},"type":"array"},"type":"object","title":"Progress","description":"Map of book_id to list of completed chapters"},"last_read_from":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Last Read From","description":"Last read position metadata"},"chapters_read":{"type":"integer","title":"Chapters Read","description":"Total number of chapters read","default":0},"books_read":{"type":"integer","title":"Books Read","description":"Total number of books fully completed (all chapters read)","default":0},"bible_read_percentage":{"type":"number","title":"Bible Read Percentage","description":"Percentage of Bible completed (0-100)","default":0.0},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["user_id","progress"],"title":"BibleProgressResponse","description":"Response model for Bible reading progress."},"Body_generate_image_api_generate_image_post":{"properties":{"image":{"type":"string","format":"binary","title":"Image"},"prompt":{"type":"string","title":"Prompt"},"style":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Style"},"scene":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scene"},"input_fidelity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Input Fidelity","default":"high"},"background":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Background","default":"auto"},"output_format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Output Format","default":"png"},"quality":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quality","default":"high"},"size":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Size","default":"1024x1024"},"n":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"N","default":1}},"type":"object","required":["image","prompt"],"title":"Body_generate_image_api_generate_image_post"},"ChatRequest":{"properties":{"message":{"type":"string","title":"Message","default":""},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"},"sendAudio":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Sendaudio","default":false},"newUser":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Newuser","default":false},"promptKey":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Promptkey","description":"Used alongside daily topic quest"},"image_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Image Ids"},"retriedFromStream":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Retriedfromstream","description":"Set by the client when re-sending a message whose streamed attempt failed. The stream route already saved the user message and counted the quota, so the buffered route must not do either again. Contract: the client sets this ONLY after receiving the stream's meta event — meta is emitted after the save/increment phase, so it is the signal that both actually happened. A stream that failed before meta (HTTP error, dropped connection) persisted nothing and must be retried WITHOUT this flag.","default":false}},"type":"object","title":"ChatRequest"},"ChatResponse":{"properties":{"reply":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reply"},"conversation_id":{"type":"string","title":"Conversation Id"},"bible_verses":{"items":{"type":"string"},"type":"array","title":"Bible Verses","default":[]},"sources":{"anyOf":[{"items":{"$ref":"#/components/schemas/Source"},"type":"array"},{"type":"null"}],"title":"Sources"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"audio_base64":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Audio Base64"}},"type":"object","required":["conversation_id"],"title":"ChatResponse"},"ChurchAdminEventResponse":{"properties":{"id":{"type":"integer","title":"Id"},"title":{"type":"string","title":"Title"},"date":{"type":"string","title":"Date"},"start_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Time"},"end_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Time"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"event_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Url"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["id","title","date","created_at"],"title":"ChurchAdminEventResponse"},"ChurchAnnouncement":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"},"date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"first_seen_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Seen At"}},"type":"object","title":"ChurchAnnouncement"},"ChurchDetailResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"church":{"$ref":"#/components/schemas/ChurchResult"}},"type":"object","required":["success","church"],"title":"ChurchDetailResponse"},"ChurchDonationLink":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"donation_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Donation Url"}},"type":"object","title":"ChurchDonationLink"},"ChurchMapPointResult":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"latitude":{"type":"number","title":"Latitude"},"longitude":{"type":"number","title":"Longitude"},"user_count":{"type":"integer","title":"User Count","default":0}},"type":"object","required":["id","latitude","longitude"],"title":"ChurchMapPointResult"},"ChurchMassTime":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"day_of_week":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Day Of Week"},"start_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Time"},"end_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Time"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"mass_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mass Url"}},"type":"object","title":"ChurchMassTime"},"ChurchPreviewDonationLink":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"donation_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Donation Url"}},"type":"object","title":"ChurchPreviewDonationLink"},"ChurchPreviewEvent":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date"},"start_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Time"},"end_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Time"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"event_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Url"},"source":{"type":"string","title":"Source","default":"website"},"admin_event_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Admin Event Id"}},"type":"object","title":"ChurchPreviewEvent"},"ChurchPreviewMassTime":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"day_of_week":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Day Of Week"},"start_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Time"},"end_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Time"},"mass_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mass Url"}},"type":"object","title":"ChurchPreviewMassTime"},"ChurchPreviewResponse":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"google_formatted_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Google Formatted Address"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"},"denomination":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Denomination"},"cached_photo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cached Photo Url"},"mass_times":{"items":{"$ref":"#/components/schemas/ChurchPreviewMassTime"},"type":"array","title":"Mass Times","default":[]},"upcoming_events":{"items":{"$ref":"#/components/schemas/ChurchPreviewEvent"},"type":"array","title":"Upcoming Events","default":[]},"donation_links":{"items":{"$ref":"#/components/schemas/ChurchPreviewDonationLink"},"type":"array","title":"Donation Links","default":[]}},"type":"object","required":["id"],"title":"ChurchPreviewResponse"},"ChurchResult":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"zip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zip"},"state_iso":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State Iso"},"state_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State Name"},"country_iso":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Iso"},"country_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Name"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"},"rating":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rating"},"google_user_ratings_total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Google User Ratings Total"},"google_formatted_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Google Formatted Address"},"cached_photo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cached Photo Url"},"user_count":{"type":"integer","title":"User Count","default":0},"mass_times":{"anyOf":[{"items":{"$ref":"#/components/schemas/ChurchMassTime"},"type":"array"},{"type":"null"}],"title":"Mass Times"},"upcoming_events":{"anyOf":[{"items":{"$ref":"#/components/schemas/ChurchUpcomingEvent"},"type":"array"},{"type":"null"}],"title":"Upcoming Events"},"donation_links":{"anyOf":[{"items":{"$ref":"#/components/schemas/ChurchDonationLink"},"type":"array"},{"type":"null"}],"title":"Donation Links"},"denomination":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Denomination"},"site_announcements":{"anyOf":[{"items":{"$ref":"#/components/schemas/ChurchAnnouncement"},"type":"array"},{"type":"null"}],"title":"Site Announcements"}},"type":"object","required":["id"],"title":"ChurchResult"},"ChurchSuggestionsResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"churches":{"items":{"$ref":"#/components/schemas/ChurchResult"},"type":"array","title":"Churches"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["success","churches","count"],"title":"ChurchSuggestionsResponse"},"ChurchUpcomingEvent":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date"},"start_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Time"},"end_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Time"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"event_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Url"}},"type":"object","title":"ChurchUpcomingEvent"},"ChurchValidationRequest":{"properties":{"name":{"type":"string","title":"Name"},"city":{"type":"string","title":"City"},"state":{"type":"string","title":"State"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"}},"type":"object","required":["name","city","state"],"title":"ChurchValidationRequest"},"ChurchValidationResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"valid":{"type":"boolean","title":"Valid"},"duplicate":{"type":"boolean","title":"Duplicate"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"church_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Church Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"zip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zip"},"state_iso":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State Iso"},"state_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State Name"},"country_iso":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Iso"},"country_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Name"},"step_timings":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"title":"Step Timings"}},"type":"object","required":["success","valid","duplicate"],"title":"ChurchValidationResponse"},"ChurchesInBoundsResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"churches":{"items":{"$ref":"#/components/schemas/ChurchMapPointResult"},"type":"array","title":"Churches"},"count":{"type":"integer","title":"Count"},"limit":{"type":"integer","title":"Limit"},"truncated":{"type":"boolean","title":"Truncated"}},"type":"object","required":["success","churches","count","limit","truncated"],"title":"ChurchesInBoundsResponse"},"CityIdentityResponse":{"properties":{"mattermost_url":{"type":"string","title":"Mattermost Url"},"team_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Team Id"},"channel_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel Id"},"user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id"},"has_identity":{"type":"boolean","title":"Has Identity"}},"type":"object","required":["mattermost_url","team_id","channel_id","user_id","has_identity"],"title":"CityIdentityResponse"},"CityMemberProfile":{"properties":{"mm_user_id":{"type":"string","title":"Mm User Id"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"profile_picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Picture"},"church_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Church Name"}},"type":"object","required":["mm_user_id","first_name","last_name","profile_picture","church_name"],"title":"CityMemberProfile"},"CityMembersRequest":{"properties":{"mm_user_ids":{"items":{"type":"string"},"type":"array","title":"Mm User Ids"}},"type":"object","required":["mm_user_ids"],"title":"CityMembersRequest"},"CityMembersResponse":{"properties":{"members":{"items":{"$ref":"#/components/schemas/CityMemberProfile"},"type":"array","title":"Members"}},"type":"object","required":["members"],"title":"CityMembersResponse"},"CityProvisionResponse":{"properties":{"mattermost_url":{"type":"string","title":"Mattermost Url"},"team_id":{"type":"string","title":"Team Id"},"channel_id":{"type":"string","title":"Channel Id"},"user_id":{"type":"string","title":"User Id"},"access_token":{"type":"string","title":"Access Token"}},"type":"object","required":["mattermost_url","team_id","channel_id","user_id","access_token"],"title":"CityProvisionResponse"},"ClaimRewardRequest":{"properties":{"redemption_id":{"type":"integer","exclusiveMinimum":0.0,"title":"Redemption Id","description":"The ID of the redemption record"}},"type":"object","required":["redemption_id"],"title":"ClaimRewardRequest","description":"Request model for claiming referrer reward"},"ClaimRewardResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Whether the claim was successful"},"message":{"type":"string","title":"Message","description":"Success or error message"}},"type":"object","required":["success","message"],"title":"ClaimRewardResponse","description":"Response model for claiming referrer reward"},"CompactRequest":{"properties":{"conversation_id":{"type":"string","title":"Conversation Id"}},"type":"object","required":["conversation_id"],"title":"CompactRequest"},"CompactResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"messages_compacted":{"type":"integer","title":"Messages Compacted","default":0},"skipped":{"type":"boolean","title":"Skipped","default":false},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["success"],"title":"CompactResponse"},"ConfigResponse":{"properties":{"feature_flags":{"$ref":"#/components/schemas/FeatureFlags"},"onboard_hard_paywall_rate":{"type":"number","title":"Onboard Hard Paywall Rate"},"onboarding_treatment_allocation":{"type":"number","title":"Onboarding Treatment Allocation"},"minimum_app_version":{"type":"string","title":"Minimum App Version"},"returning_user_absent_paywall_allocation":{"type":"number","title":"Returning User Absent Paywall Allocation"},"trial_end_reminder_enabled":{"type":"boolean","title":"Trial End Reminder Enabled"},"usage_limit_warning_treatment_allocation":{"type":"number","title":"Usage Limit Warning Treatment Allocation"},"log_meta_sdk_events":{"type":"boolean","title":"Log Meta Sdk Events"},"log_tiktok_sdk_events":{"type":"boolean","title":"Log Tiktok Sdk Events"},"newcomer_banner_treatment_allocation":{"type":"number","title":"Newcomer Banner Treatment Allocation"},"tts_treatment_allocation":{"type":"number","title":"Tts Treatment Allocation"},"tts_exp_legacy_cutoff_timestamp":{"type":"integer","title":"Tts Exp Legacy Cutoff Timestamp"},"low_usage_country_codes":{"items":{"type":"string"},"type":"array","title":"Low Usage Country Codes"},"low_usage_currency_codes":{"items":{"type":"string"},"type":"array","title":"Low Usage Currency Codes"},"low_usage_language_codes":{"items":{"type":"string"},"type":"array","title":"Low Usage Language Codes"},"inapp_ads_admob_allocation":{"type":"number","title":"Inapp Ads Admob Allocation"},"inapp_ads_house_allocation":{"type":"number","title":"Inapp Ads House Allocation"},"paid_token_exp_legacy_cutoff_timestamp":{"type":"integer","title":"Paid Token Exp Legacy Cutoff Timestamp"},"paid_token_exp_treatment_allocation":{"type":"number","title":"Paid Token Exp Treatment Allocation"},"tiered_sub_exp_cutoff_timestamp":{"type":"integer","title":"Tiered Sub Exp Cutoff Timestamp"},"tiered_sub_exp_treatment_allocation":{"type":"number","title":"Tiered Sub Exp Treatment Allocation"},"compaction_interval":{"type":"integer","title":"Compaction Interval"},"chat_streaming_allocation":{"type":"number","title":"Chat Streaming Allocation"}},"type":"object","required":["feature_flags","onboard_hard_paywall_rate","onboarding_treatment_allocation","minimum_app_version","returning_user_absent_paywall_allocation","trial_end_reminder_enabled","usage_limit_warning_treatment_allocation","log_meta_sdk_events","log_tiktok_sdk_events","newcomer_banner_treatment_allocation","tts_treatment_allocation","tts_exp_legacy_cutoff_timestamp","low_usage_country_codes","low_usage_currency_codes","low_usage_language_codes","inapp_ads_admob_allocation","inapp_ads_house_allocation","paid_token_exp_legacy_cutoff_timestamp","paid_token_exp_treatment_allocation","tiered_sub_exp_cutoff_timestamp","tiered_sub_exp_treatment_allocation","compaction_interval","chat_streaming_allocation"],"title":"ConfigResponse"},"CreateAnnouncementRequest":{"properties":{"title":{"type":"string","maxLength":65,"title":"Title"},"short_description":{"type":"string","maxLength":140,"title":"Short Description"},"long_description":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Long Description"},"notify_members":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Notify Members"}},"type":"object","required":["title","short_description"],"title":"CreateAnnouncementRequest"},"CreateEventRequest":{"properties":{"title":{"type":"string","maxLength":120,"minLength":1,"title":"Title"},"date":{"type":"string","title":"Date"},"start_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Time"},"end_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Time"},"location":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Location"},"event_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Event Url"}},"type":"object","required":["title","date"],"title":"CreateEventRequest"},"CreateGiftCodeRequest":{"properties":{"rc_product":{"type":"string","minLength":1,"title":"Rc Product","description":"RevenueCat product ID"},"rc_transaction":{"type":"string","minLength":1,"title":"Rc Transaction","description":"RevenueCat transaction ID"}},"type":"object","required":["rc_product","rc_transaction"],"title":"CreateGiftCodeRequest","description":"Request model for creating a gift code"},"CreateGiftCodeResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"}},"type":"object","required":["success","code","message"],"title":"CreateGiftCodeResponse","description":"Response model for creating a gift code"},"CreateReminderRequest":{"properties":{"subtype":{"type":"string","title":"Subtype","description":"Reminder subtype: prayer, church, devotional, or custom"},"schedule_type":{"type":"string","title":"Schedule Type","description":"Schedule type: daily or weekly"},"schedule_time":{"type":"string","title":"Schedule Time","description":"Time of day in HH:MM format (e.g., '09:00')"},"schedule_day":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Schedule Day","description":"Day of week for weekly (0=Sunday, 6=Saturday)"},"custom_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Custom Text","description":"Custom reminder text (required for custom subtype)"}},"type":"object","required":["subtype","schedule_type","schedule_time"],"title":"CreateReminderRequest"},"CreateRoomRequest":{"properties":{"room_id":{"type":"string","title":"Room Id","description":"Room ID to create the LiveKit room"},"opening_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Opening Message","description":"Optional text the voice agent should speak verbatim as its first utterance."},"supports_voice_idle_check":{"type":"boolean","title":"Supports Voice Idle Check","description":"True when the client supports the voice_control idle-check flow (receives 'idle_check' and replies 'idle_active'). Older builds omit it.","default":false}},"type":"object","required":["room_id"],"title":"CreateRoomRequest"},"CreateSharedPrayersRequest":{"properties":{"prayer_text":{"type":"string","title":"Prayer Text"},"person_ids":{"items":{"type":"string"},"type":"array","title":"Person Ids"}},"type":"object","required":["prayer_text","person_ids"],"title":"CreateSharedPrayersRequest"},"CreateSharedPrayersResponse":{"properties":{"prayers":{"items":{"$ref":"#/components/schemas/SharedPrayerRef"},"type":"array","title":"Prayers"}},"type":"object","required":["prayers"],"title":"CreateSharedPrayersResponse"},"DailyDevotional":{"properties":{"id":{"type":"integer","title":"Id"},"verse_string":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Verse String"},"verse_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Verse Text"},"devotional_commentary_short":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Devotional Commentary Short"},"devotional_commentary_long":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Devotional Commentary Long"},"prayer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prayer"},"date":{"anyOf":[{},{"type":"null"}],"title":"Date"},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"}},"additionalProperties":true,"type":"object","required":["id"],"title":"DailyDevotional","description":"Model for a daily devotional entry matching the Supabase schema","example":{"date":"2024-01-15","devotional_commentary_long":"A longer, more detailed reflection on this verse and its meaning...","devotional_commentary_short":"A short reflection on this verse...","id":1,"language":"en","prayer":"Dear Lord, help us to...","verse_string":"John 3:16","verse_text":"For God so loved the world..."}},"DailyDevotionalBroadcastVarsRequest":{"properties":{"verse_string":{"type":"string","title":"Verse String","default":""},"verse_text":{"type":"string","title":"Verse Text","default":""},"reflection":{"type":"string","title":"Reflection","default":""},"prayer":{"type":"string","title":"Prayer","default":""}},"type":"object","title":"DailyDevotionalBroadcastVarsRequest","description":"Body for daily devotional preview-broadcast and send-broadcast debug endpoints."},"DailyDevotionalResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"devotionals":{"items":{"$ref":"#/components/schemas/DailyDevotional"},"type":"array","title":"Devotionals"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["success","devotionals","count"],"title":"DailyDevotionalResponse","description":"Response model for getting daily devotionals"},"DailyQuestResponse":{"properties":{"daily_prayer_completed":{"type":"boolean","title":"Daily Prayer Completed"},"daily_gratitude_completed":{"type":"boolean","title":"Daily Gratitude Completed"},"daily_verse_interacted":{"type":"boolean","title":"Daily Verse Interacted"},"daily_devotional_completed":{"type":"boolean","title":"Daily Devotional Completed"},"daily_prayer_wall_completed":{"type":"boolean","title":"Daily Prayer Wall Completed"},"daily_prompt_completed":{"type":"boolean","title":"Daily Prompt Completed"},"discord_joined":{"type":"boolean","title":"Discord Joined"},"scene_generator_completed":{"type":"boolean","title":"Scene Generator Completed"},"widget_tutorial_completed":{"type":"boolean","title":"Widget Tutorial Completed"},"prayer_reminder_completed":{"type":"boolean","title":"Prayer Reminder Completed"},"share_creed_completed":{"type":"boolean","title":"Share Creed Completed"},"customize_completed":{"type":"boolean","title":"Customize Completed"},"sponsor_completed":{"type":"boolean","title":"Sponsor Completed"},"add_church_completed":{"type":"boolean","title":"Add Church Completed","default":false},"start_friend_streak_completed":{"type":"boolean","title":"Start Friend Streak Completed","default":false},"faith_lock_completed":{"type":"boolean","title":"Faith Lock Completed","default":false},"artist_of_the_week_completed":{"type":"boolean","title":"Artist Of The Week Completed","default":false},"commit_to_mass_completed":{"type":"boolean","title":"Commit To Mass Completed","default":false},"learning_plan_started_completed":{"type":"boolean","title":"Learning Plan Started Completed","default":false},"learning_plan_completed":{"type":"boolean","title":"Learning Plan Completed","default":false},"total_quests_completed":{"type":"integer","title":"Total Quests Completed","default":0},"claimed":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Claimed"}},"type":"object","required":["daily_prayer_completed","daily_gratitude_completed","daily_verse_interacted","daily_devotional_completed","daily_prayer_wall_completed","daily_prompt_completed","discord_joined","scene_generator_completed","widget_tutorial_completed","prayer_reminder_completed","share_creed_completed","customize_completed","sponsor_completed"],"title":"DailyQuestResponse"},"DevotionalSegment":{"properties":{"type":{"type":"string","const":"devotional","title":"Type"},"title":{"type":"string","title":"Title"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"}},"type":"object","required":["type","title"],"title":"DevotionalSegment"},"EarnRewardRequest":{"properties":{"reward_key":{"type":"string","title":"Reward Key","description":"The reward key to earn tokens from (e.g., 'quest_daily_reading')"}},"type":"object","required":["reward_key"],"title":"EarnRewardRequest","description":"Request to earn tokens from a reward."},"EarnTokensRequest":{"properties":{"amount":{"type":"integer","exclusiveMinimum":0.0,"title":"Amount","description":"The number of tokens to award"},"source":{"type":"string","title":"Source","description":"The source label for this token award"}},"type":"object","required":["amount","source"],"title":"EarnTokensRequest","description":"Request to earn a custom amount of tokens directly."},"EarnTokensResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message"}},"type":"object","required":["success","message"],"title":"EarnTokensResponse","description":"Response for earning tokens."},"ErrorResponse":{"properties":{"detail":{"type":"string","title":"Detail"}},"type":"object","required":["detail"],"title":"ErrorResponse"},"FeatureFlags":{"properties":{"cpp_paywall":{"type":"boolean","title":"Cpp Paywall"}},"type":"object","required":["cpp_paywall"],"title":"FeatureFlags"},"GetSavedVersesResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"verses":{"items":{"$ref":"#/components/schemas/SavedVerse"},"type":"array","title":"Verses"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["success","verses","count"],"title":"GetSavedVersesResponse","description":"Response model for getting saved verses"},"GiftCodeRecord":{"properties":{"code":{"type":"string","title":"Code"},"buyer_id":{"type":"string","title":"Buyer Id"},"receiver_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Receiver Id"},"rc_product":{"type":"string","title":"Rc Product"},"rc_transaction":{"type":"string","title":"Rc Transaction"},"redeemed":{"type":"boolean","title":"Redeemed"},"redeemed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redeemed At"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["code","buyer_id","receiver_id","rc_product","rc_transaction","redeemed","redeemed_at","created_at"],"title":"GiftCodeRecord","description":"Model for a single gift code record"},"GoogleAutocompleteRequest":{"properties":{"input":{"type":"string","title":"Input"},"session_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Token"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"}},"type":"object","required":["input"],"title":"GoogleAutocompleteRequest"},"GoogleAutocompleteResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"suggestions":{"items":{"$ref":"#/components/schemas/GoogleAutocompleteSuggestion"},"type":"array","title":"Suggestions"}},"type":"object","required":["success","suggestions"],"title":"GoogleAutocompleteResponse"},"GoogleAutocompleteSuggestion":{"properties":{"place_id":{"type":"string","title":"Place Id"},"primary_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Primary Text"},"secondary_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secondary Text"},"full_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Full Text"},"is_church":{"type":"boolean","title":"Is Church","default":false}},"type":"object","required":["place_id"],"title":"GoogleAutocompleteSuggestion"},"GooglePreviewRequest":{"properties":{"place_id":{"type":"string","title":"Place Id"},"session_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Token"}},"type":"object","required":["place_id"],"title":"GooglePreviewRequest"},"GooglePreviewResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"place_id":{"type":"string","title":"Place Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"formatted_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Formatted Address"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"}},"type":"object","required":["success","place_id"],"title":"GooglePreviewResponse"},"GoogleSelectRequest":{"properties":{"place_id":{"type":"string","title":"Place Id"},"session_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Token"}},"type":"object","required":["place_id"],"title":"GoogleSelectRequest"},"GoogleSelectResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"duplicate":{"type":"boolean","title":"Duplicate"},"church":{"$ref":"#/components/schemas/ChurchResult"}},"type":"object","required":["success","duplicate","church"],"title":"GoogleSelectResponse"},"GratitudeJournalResponse":{"properties":{"id":{"type":"integer","title":"Id"},"gratitude_text":{"type":"string","title":"Gratitude Text"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"is_first_entry":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is First Entry"}},"type":"object","required":["id","gratitude_text","created_at"],"title":"GratitudeJournalResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"IdentityResponse":{"properties":{"mattermost_url":{"type":"string","title":"Mattermost Url"},"team_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Team Id"},"channel_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel Id"},"user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id"},"has_identity":{"type":"boolean","title":"Has Identity"}},"type":"object","required":["mattermost_url","team_id","channel_id","user_id","has_identity"],"title":"IdentityResponse"},"ImageData":{"properties":{"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"URL of the generated image"},"b64_json":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"B64 Json","description":"Base64 encoded image data"}},"type":"object","title":"ImageData","description":"Individual image data in response"},"ImageGenerationResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Whether the generation was successful"},"data":{"items":{"$ref":"#/components/schemas/ImageData"},"type":"array","title":"Data","description":"List of generated images"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error","description":"Error message if generation failed"}},"type":"object","required":["success","data"],"title":"ImageGenerationResponse","description":"Response model for image generation"},"ItemActionRequest":{"properties":{"item_key":{"type":"string","title":"Item Key","description":"The unique key of the item"}},"type":"object","required":["item_key"],"title":"ItemActionRequest","description":"Request for item actions (purchase/unlock)."},"ItemActionResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message"},"item":{"anyOf":[{"$ref":"#/components/schemas/ItemResponse"},{"type":"null"}]}},"type":"object","required":["success","message"],"title":"ItemActionResponse","description":"Item action response (purchase/unlock)."},"ItemResponse":{"properties":{"id":{"type":"string","title":"Id"},"key":{"type":"string","title":"Key"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"item_type":{"type":"string","title":"Item Type"},"unlock_type":{"$ref":"#/components/schemas/UnlockType"},"token_price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Token Price"},"available_from":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Available From"},"available_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Available Until"},"sort_order":{"type":"integer","title":"Sort Order","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","key","name","item_type","unlock_type","created_at"],"title":"ItemResponse","description":"Item response model for shop display."},"JournalBundleResponse":{"properties":{"gratitudes":{"items":{"$ref":"#/components/schemas/GratitudeJournalResponse"},"type":"array","title":"Gratitudes"},"prayers":{"items":{"$ref":"#/components/schemas/PrayerJournalResponse"},"type":"array","title":"Prayers"},"verses":{"items":{"$ref":"#/components/schemas/SavedVerse"},"type":"array","title":"Verses"},"latest_change":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Change"}},"type":"object","required":["gratitudes","prayers","verses"],"title":"JournalBundleResponse"},"LeaderboardEntry":{"properties":{"rank":{"type":"integer","title":"Rank"},"user_id":{"type":"string","title":"User Id"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"profile_picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Picture"},"streak_count":{"type":"integer","title":"Streak Count","default":0},"church_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Church Id"},"church_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Church Name"}},"type":"object","required":["rank","user_id"],"title":"LeaderboardEntry"},"LeaderboardResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"entries":{"items":{"$ref":"#/components/schemas/LeaderboardEntry"},"type":"array","title":"Entries"},"total_count":{"type":"integer","title":"Total Count"},"user_rank":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"User Rank"},"user_entry":{"anyOf":[{"$ref":"#/components/schemas/LeaderboardEntry"},{"type":"null"}]},"context_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Context Name"}},"type":"object","required":["success","entries","total_count"],"title":"LeaderboardResponse"},"LearningPlanCatalog":{"properties":{"plans":{"items":{"$ref":"#/components/schemas/Plan"},"type":"array","title":"Plans"},"starter_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Starter Count"}},"type":"object","required":["plans"],"title":"LearningPlanCatalog"},"LearningPlanInstance":{"properties":{"instance_id":{"type":"string","title":"Instance Id"},"user_id":{"type":"string","title":"User Id"},"plan_key":{"type":"string","title":"Plan Key"},"started_at":{"type":"string","title":"Started At"},"completed_segments":{"items":{"type":"string"},"type":"array","title":"Completed Segments"}},"type":"object","required":["instance_id","user_id","plan_key","started_at"],"title":"LearningPlanInstance"},"LearningPlanReflection":{"properties":{"instance_id":{"type":"string","title":"Instance Id"},"day_index":{"type":"integer","title":"Day Index"},"body":{"type":"string","title":"Body"},"quiz_answers":{"items":{"$ref":"#/components/schemas/QuizAnswer"},"type":"array","title":"Quiz Answers"},"created_at":{"type":"string","title":"Created At"},"updated_at":{"type":"string","title":"Updated At"}},"type":"object","required":["instance_id","day_index","body","created_at","updated_at"],"title":"LearningPlanReflection"},"LinkOAuthRequest":{"properties":{"identityToken":{"type":"string","title":"Identitytoken"},"userId":{"type":"string","title":"Userid"},"provider":{"type":"string","title":"Provider","default":"apple"}},"type":"object","required":["identityToken","userId"],"title":"LinkOAuthRequest"},"LiveActivityType":{"type":"string","enum":["standard","reminder","streak","call"],"title":"LiveActivityType","description":"Enum for Live Activity notification types"},"LiveStreamComment":{"properties":{"id":{"type":"integer","title":"Id"},"stream_id":{"type":"integer","title":"Stream Id"},"user_id":{"type":"string","title":"User Id"},"comment_text":{"type":"string","title":"Comment Text"},"rejection_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason"},"bot_approved":{"type":"boolean","title":"Bot Approved","default":true},"created_at":{"type":"string","format":"date-time","title":"Created At"},"user":{"anyOf":[{"$ref":"#/components/schemas/LiveStreamCommentUser"},{"type":"null"}]}},"type":"object","required":["id","stream_id","user_id","comment_text","created_at"],"title":"LiveStreamComment","description":"DB model for live_stream_comments table."},"LiveStreamCommentUser":{"properties":{"user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"profile_picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Picture"}},"type":"object","title":"LiveStreamCommentUser","description":"User info for live stream comments."},"LoginRequest":{"properties":{"username":{"type":"string","title":"Username"},"password":{"type":"string","title":"Password"}},"type":"object","required":["username","password"],"title":"LoginRequest"},"MarkSeenRequest":{"properties":{"spotlightId":{"type":"string","title":"Spotlightid"}},"type":"object","required":["spotlightId"],"title":"MarkSeenRequest"},"MarkSegmentRequest":{"properties":{"day_index":{"type":"integer","title":"Day Index"},"segment_type":{"type":"string","enum":["devotional","scripture","reflection"],"title":"Segment Type"}},"type":"object","required":["day_index","segment_type"],"title":"MarkSegmentRequest"},"MemberProfile":{"properties":{"mm_user_id":{"type":"string","title":"Mm User Id"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"profile_picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Picture"}},"type":"object","required":["mm_user_id","first_name","last_name","profile_picture"],"title":"MemberProfile"},"MembersRequest":{"properties":{"mm_user_ids":{"items":{"type":"string"},"type":"array","title":"Mm User Ids"}},"type":"object","required":["mm_user_ids"],"title":"MembersRequest"},"MembersResponse":{"properties":{"members":{"items":{"$ref":"#/components/schemas/MemberProfile"},"type":"array","title":"Members"}},"type":"object","required":["members"],"title":"MembersResponse"},"MultipleChoiceQuestion":{"properties":{"format":{"type":"string","const":"multiple_choice","title":"Format"},"prompt":{"type":"string","title":"Prompt"},"choices":{"items":{"type":"string"},"type":"array","title":"Choices"},"correct_index":{"type":"integer","title":"Correct Index"},"explanation":{"type":"string","title":"Explanation"}},"type":"object","required":["format","prompt","choices","correct_index","explanation"],"title":"MultipleChoiceQuestion"},"MyGiftCodesResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"gift_codes":{"items":{"$ref":"#/components/schemas/GiftCodeRecord"},"type":"array","title":"Gift Codes"},"total_count":{"type":"integer","title":"Total Count"},"redeemed_count":{"type":"integer","title":"Redeemed Count"},"unredeemed_count":{"type":"integer","title":"Unredeemed Count"}},"type":"object","required":["success","gift_codes","total_count","redeemed_count","unredeemed_count"],"title":"MyGiftCodesResponse","description":"Response model for getting user's gift codes"},"NudgeFriendRequest":{"properties":{"text":{"type":"string","maxLength":2000,"minLength":1,"title":"Text"},"is_custom":{"type":"boolean","title":"Is Custom","default":false}},"type":"object","required":["text"],"title":"NudgeFriendRequest"},"Plan":{"properties":{"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"author":{"type":"string","title":"Author"},"duration_days":{"type":"integer","title":"Duration Days"},"topic":{"type":"string","title":"Topic"},"description":{"type":"string","title":"Description"},"premium":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Premium"},"days":{"items":{"$ref":"#/components/schemas/PlanDay"},"type":"array","title":"Days"}},"type":"object","required":["key","title","author","duration_days","topic","description","days"],"title":"Plan"},"PlanDay":{"properties":{"day_index":{"type":"integer","title":"Day Index"},"segments":{"items":{"anyOf":[{"$ref":"#/components/schemas/DevotionalSegment"},{"$ref":"#/components/schemas/ScriptureSegment"},{"$ref":"#/components/schemas/ReflectionSegment"}]},"type":"array","title":"Segments"}},"type":"object","required":["day_index","segments"],"title":"PlanDay"},"PrayerJournalResponse":{"properties":{"id":{"type":"integer","title":"Id"},"prayer_text":{"type":"string","title":"Prayer Text"},"topic":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Topic"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","prayer_text","created_at"],"title":"PrayerJournalResponse"},"PrayerLibraryItem":{"properties":{"id":{"type":"string","title":"Id"},"topic":{"type":"string","title":"Topic"},"language":{"type":"string","title":"Language"},"voice":{"type":"string","title":"Voice"},"prayer_text":{"type":"string","title":"Prayer Text"},"audio_url":{"type":"string","title":"Audio Url"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["id","topic","language","voice","prayer_text","audio_url","created_at"],"title":"PrayerLibraryItem"},"PrayerLibraryResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"prayer":{"$ref":"#/components/schemas/PrayerLibraryItem"}},"type":"object","required":["success","prayer"],"title":"PrayerLibraryResponse"},"PrayerRequest":{"properties":{"sendAudio":{"type":"boolean","title":"Sendaudio","default":false},"topic":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Topic"},"for_names":{"anyOf":[{"items":{"type":"string","maxLength":100,"minLength":1},"type":"array"},{"type":"null"}],"title":"For Names"}},"type":"object","title":"PrayerRequest"},"PrayerResponse":{"properties":{"prayer_text":{"type":"string","title":"Prayer Text"},"audio_base64":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Audio Base64"}},"type":"object","required":["prayer_text"],"title":"PrayerResponse"},"PrayerWall":{"properties":{"id":{"type":"integer","title":"Id"},"user_input":{"type":"string","title":"User Input"},"generated_title":{"type":"string","title":"Generated Title"},"generated_prayer":{"type":"string","title":"Generated Prayer"},"rejection_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason"},"is_bot":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Bot"},"is_expired":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Expired"},"user_approved":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"User Approved"},"start_time":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Time"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"user":{"anyOf":[{"$ref":"#/components/schemas/PrayerWallUser"},{"type":"null"}]}},"type":"object","required":["id","user_input","generated_title","generated_prayer","created_at"],"title":"PrayerWall","description":"DB model for prayer_wall table."},"PrayerWallBroadcastVarsRequest":{"properties":{"name":{"type":"string","title":"Name","default":""},"prayer":{"type":"string","title":"Prayer","default":""},"prayer_request":{"type":"string","title":"Prayer Request","default":""},"title":{"type":"string","title":"Title","default":""}},"type":"object","title":"PrayerWallBroadcastVarsRequest","description":"Body for preview-broadcast and send-broadcast debug endpoints."},"PrayerWallComment":{"properties":{"id":{"type":"integer","title":"Id"},"prayer_id":{"type":"integer","title":"Prayer Id"},"user_id":{"type":"string","title":"User Id"},"comment_text":{"type":"string","title":"Comment Text"},"rejection_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rejection Reason"},"bot_approved":{"type":"boolean","title":"Bot Approved"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"user":{"anyOf":[{"$ref":"#/components/schemas/PrayerWallCommentUser"},{"type":"null"}]}},"type":"object","required":["id","prayer_id","user_id","comment_text","bot_approved","created_at"],"title":"PrayerWallComment","description":"DB model for prayer_wall_comments table."},"PrayerWallCommentUser":{"properties":{"user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"profile_picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Picture"}},"type":"object","title":"PrayerWallCommentUser","description":"User info for prayer wall comments."},"PrayerWallPaginatedResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/PrayerWall"},"type":"array","title":"Data"},"total_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Count"}},"type":"object","required":["data"],"title":"PrayerWallPaginatedResponse"},"PrayerWallUser":{"properties":{"user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"profile_picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Picture"}},"type":"object","title":"PrayerWallUser","description":"User info for prayer wall."},"PrayingCountResponse":{"properties":{"count":{"type":"integer","title":"Count"}},"type":"object","required":["count"],"title":"PrayingCountResponse"},"PricingVariant":{"type":"string","enum":["default","paid_tokens"],"title":"PricingVariant","description":"Which shop pricing to apply. Cohort bucketing for the paid_token_exp\nexperiment happens client-side (see paid_token_exp_treatment_allocation /\npaid_token_exp_legacy_cutoff_timestamp in /api/config), so the client\ntells the backend which price column applies for a given request."},"ProfileResponse":{"properties":{"admin_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Admin Name"},"church_name":{"type":"string","title":"Church Name"},"church_id":{"type":"integer","title":"Church Id"}},"type":"object","required":["church_name","church_id"],"title":"ProfileResponse"},"ProvisionResponse":{"properties":{"mattermost_url":{"type":"string","title":"Mattermost Url"},"team_id":{"type":"string","title":"Team Id"},"channel_id":{"type":"string","title":"Channel Id"},"user_id":{"type":"string","title":"User Id"},"access_token":{"type":"string","title":"Access Token"}},"type":"object","required":["mattermost_url","team_id","channel_id","user_id","access_token"],"title":"ProvisionResponse"},"QuizAnswer":{"properties":{"question_index":{"type":"integer","title":"Question Index"},"selected_index":{"type":"integer","title":"Selected Index"},"correct":{"type":"boolean","title":"Correct"}},"type":"object","required":["question_index","selected_index","correct"],"title":"QuizAnswer"},"RedeemCodeRequest":{"properties":{"token":{"type":"string","minLength":1,"title":"Token","description":"The referral code to redeem"}},"type":"object","required":["token"],"title":"RedeemCodeRequest","description":"Request model for redeeming a referral code"},"RedeemCodeResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Whether the redemption was successful"},"message":{"type":"string","title":"Message","description":"Success or error message"}},"type":"object","required":["success","message"],"title":"RedeemCodeResponse","description":"Response model for redeeming a referral code"},"RedeemGiftCodeRequest":{"properties":{"code":{"type":"string","minLength":1,"title":"Code","description":"The gift code to redeem"}},"type":"object","required":["code"],"title":"RedeemGiftCodeRequest","description":"Request model for redeeming a gift code"},"RedeemGiftCodeResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Whether the redemption was successful"},"message":{"type":"string","title":"Message","description":"Success or error message"}},"type":"object","required":["success","message"],"title":"RedeemGiftCodeResponse","description":"Response model for redeeming a gift code"},"RedeemPromoCodeRequest":{"properties":{"code":{"type":"string","minLength":1,"title":"Code","description":"The promo code to redeem"}},"type":"object","required":["code"],"title":"RedeemPromoCodeRequest","description":"Request model for redeeming a promo code"},"RedeemPromoCodeResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Whether the redemption was successful"},"message":{"type":"string","title":"Message","description":"Success or error message"}},"type":"object","required":["success","message"],"title":"RedeemPromoCodeResponse","description":"Response model for redeeming a promo code"},"RedemptionRecord":{"properties":{"id":{"type":"integer","title":"Id"},"code":{"type":"string","title":"Code"},"referrer_id":{"type":"string","title":"Referrer Id"},"referee_id":{"type":"string","title":"Referee Id"},"redeemed_at":{"type":"string","title":"Redeemed At"},"referrer_reward_claimed":{"type":"boolean","title":"Referrer Reward Claimed"},"referee_reward_claimed":{"type":"boolean","title":"Referee Reward Claimed"}},"type":"object","required":["id","code","referrer_id","referee_id","redeemed_at","referrer_reward_claimed","referee_reward_claimed"],"title":"RedemptionRecord","description":"Model for a single redemption record"},"RedemptionsResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"redemptions":{"items":{"$ref":"#/components/schemas/RedemptionRecord"},"type":"array","title":"Redemptions"},"total_count":{"type":"integer","title":"Total Count"},"unclaimed_count":{"type":"integer","title":"Unclaimed Count"}},"type":"object","required":["success","redemptions","total_count","unclaimed_count"],"title":"RedemptionsResponse","description":"Response model for getting user's redemptions"},"ReferralCodeResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"},"redemptions":{"type":"integer","title":"Redemptions"}},"type":"object","required":["success","code","message","redemptions"],"title":"ReferralCodeResponse","description":"Response model for creating a referral code"},"ReflectionSegment":{"properties":{"type":{"type":"string","const":"reflection","title":"Type"},"questions":{"items":{"anyOf":[{"$ref":"#/components/schemas/MultipleChoiceQuestion"},{"$ref":"#/components/schemas/TrueFalseQuestion"}]},"type":"array","title":"Questions"},"reflection_prompt":{"type":"string","title":"Reflection Prompt"}},"type":"object","required":["type","questions","reflection_prompt"],"title":"ReflectionSegment"},"ResendCreateContactRequest":{"properties":{"email":{"type":"string","title":"Email"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"add_to_segment":{"type":"boolean","title":"Add To Segment","default":false}},"type":"object","required":["email"],"title":"ResendCreateContactRequest","description":"Body for Resend create-contact debug endpoint."},"RewardResponse":{"properties":{"id":{"type":"string","title":"Id"},"key":{"type":"string","title":"Key"},"category":{"type":"string","title":"Category"},"amount":{"type":"integer","title":"Amount"},"is_active":{"type":"boolean","title":"Is Active"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","key","category","amount","is_active","created_at"],"title":"RewardResponse","description":"Token reward response model."},"RoomResponse":{"properties":{"room":{"additionalProperties":true,"type":"object","title":"Room"},"access_token":{"type":"string","title":"Access Token"},"url":{"type":"string","title":"Url"}},"type":"object","required":["room","access_token","url"],"title":"RoomResponse"},"SaveReflectionRequest":{"properties":{"body":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"Body"},"quiz_answers":{"anyOf":[{"items":{"$ref":"#/components/schemas/QuizAnswer"},"type":"array"},{"type":"null"}],"title":"Quiz Answers"}},"type":"object","title":"SaveReflectionRequest","description":"Both fields are optional and written independently: the quiz is saved as\nthe user taps an answer, the reflection when they finish the day. Omitting a\nfield leaves the stored value untouched."},"SaveVerseRequest":{"properties":{"version":{"type":"string","title":"Version"},"book":{"type":"string","title":"Book"},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter"},"verse":{"type":"integer","minimum":1.0,"title":"Verse"}},"type":"object","required":["version","book","chapter","verse"],"title":"SaveVerseRequest","description":"Request model for saving a verse"},"SaveVerseResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message"},"verse":{"anyOf":[{"$ref":"#/components/schemas/SavedVerse"},{"type":"null"}]}},"type":"object","required":["success","message"],"title":"SaveVerseResponse","description":"Response model for saving a verse"},"SavedVerse":{"properties":{"version":{"type":"string","title":"Version","description":"Bible version (e.g., 'KJV', 'NIV', 'ESV')"},"book":{"type":"string","title":"Book","description":"Book name (e.g., 'Genesis', 'John')"},"chapter":{"type":"integer","minimum":1.0,"title":"Chapter","description":"Chapter number"},"verse":{"type":"integer","minimum":1.0,"title":"Verse","description":"Verse number"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At","description":"ISO 8601 timestamp the verse was saved. May be null for verses saved before this field was introduced."}},"type":"object","required":["version","book","chapter","verse"],"title":"SavedVerse","description":"Model for a saved Bible verse","example":{"book":"John","chapter":3,"created_at":"2024-05-11T19:42:00+00:00","verse":16,"version":"KJV"}},"ScriptureReference":{"properties":{"book":{"type":"string","title":"Book"},"chapter":{"type":"integer","title":"Chapter"},"verses":{"type":"string","title":"Verses"}},"type":"object","required":["book","chapter","verses"],"title":"ScriptureReference"},"ScriptureSegment":{"properties":{"type":{"type":"string","const":"scripture","title":"Type"},"reference":{"$ref":"#/components/schemas/ScriptureReference"}},"type":"object","required":["type","reference"],"title":"ScriptureSegment"},"SeenEntry":{"properties":{"spotlight_id":{"type":"string","title":"Spotlight Id"},"seen_at":{"type":"string","title":"Seen At"}},"type":"object","required":["spotlight_id","seen_at"],"title":"SeenEntry"},"SeoBiblicalChatRequest":{"properties":{"question":{"type":"string","title":"Question"},"topic_question":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Topic Question"},"memory":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Memory","default":false},"system_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"System Prompt"}},"type":"object","required":["question"],"title":"SeoBiblicalChatRequest"},"SeoBiblicalChatResponse":{"properties":{"answer":{"type":"string","title":"Answer"},"bible_verses":{"items":{"type":"string"},"type":"array","title":"Bible Verses","default":[]}},"type":"object","required":["answer"],"title":"SeoBiblicalChatResponse"},"SharedPrayerAuthor":{"properties":{"id":{"type":"string","title":"Id"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"profile_picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Picture"}},"type":"object","required":["id"],"title":"SharedPrayerAuthor"},"SharedPrayerRef":{"properties":{"id":{"type":"string","title":"Id"},"person_id":{"type":"string","title":"Person Id"}},"type":"object","required":["id","person_id"],"title":"SharedPrayerRef"},"SharedPrayerResponse":{"properties":{"id":{"type":"string","title":"Id"},"prayer_text":{"type":"string","title":"Prayer Text"},"created_at":{"type":"string","title":"Created At"},"prayed_for_person_id":{"type":"string","title":"Prayed For Person Id"},"first_seen":{"type":"boolean","title":"First Seen"},"prayed_by":{"$ref":"#/components/schemas/SharedPrayerAuthor"}},"type":"object","required":["id","prayer_text","created_at","prayed_for_person_id","first_seen","prayed_by"],"title":"SharedPrayerResponse"},"SnoozeReminderRequest":{"properties":{"user_id":{"type":"string","title":"User Id","description":"User who owns the reminder (from the Live Activity)"},"task_id":{"type":"string","title":"Task Id","description":"cron_tasks id of the reminder to snooze (from the Live Activity)"},"minutes":{"type":"integer","maximum":1440.0,"minimum":1.0,"title":"Minutes","description":"Minutes to wait before re-sending the reminder"}},"type":"object","required":["user_id","task_id","minutes"],"title":"SnoozeReminderRequest"},"SocialFeedEventResponse":{"properties":{"id":{"type":"string","title":"Id"},"church_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Church Id"},"event":{"$ref":"#/components/schemas/SocialFeedEventType"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"user":{"anyOf":[{"$ref":"#/components/schemas/SocialFeedUser"},{"type":"null"}]}},"type":"object","required":["id","event","metadata","created_at"],"title":"SocialFeedEventResponse","description":"Response model for a social feed event — includes nested user, excludes user_id."},"SocialFeedEventType":{"type":"string","enum":["streak","journal","prayer","prayer_wall","achievement"],"title":"SocialFeedEventType","description":"Event types for the user social feed.\n\nNOTE: The `social_feed_event_type` enum in the database also needs to be\nupdated whenever values are added or removed here."},"SocialFeedUser":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"profile_picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Picture"}},"type":"object","title":"SocialFeedUser","description":"Embedded user info returned in social feed responses."},"Source":{"properties":{"title":{"type":"string","title":"Title"},"url":{"type":"string","title":"Url"},"snippet":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Snippet"},"favicon":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Favicon"},"domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Domain"}},"type":"object","required":["title","url"],"title":"Source"},"SponsorProfileRequest":{"properties":{"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"discord_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Discord Username"},"share_on_kindness_wall":{"type":"boolean","title":"Share On Kindness Wall","default":true}},"type":"object","title":"SponsorProfileRequest"},"StartInstanceRequest":{"properties":{"plan_key":{"type":"string","title":"Plan Key"}},"type":"object","required":["plan_key"],"title":"StartInstanceRequest"},"StartStreamRequest":{"properties":{"streamer_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Streamer Name"}},"type":"object","title":"StartStreamRequest"},"StorePushToStartTokenRequest":{"properties":{"token":{"type":"string","title":"Token"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},"type":"object","required":["token"],"title":"StorePushToStartTokenRequest"},"StorePushToStartTokenResponse":{"properties":{"success":{"type":"boolean","title":"Success"}},"type":"object","required":["success"],"title":"StorePushToStartTokenResponse"},"StreakResponse":{"properties":{"streak_count":{"type":"integer","title":"Streak Count"},"last_completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Completed At"},"today_completed":{"type":"boolean","title":"Today Completed","default":false},"streak_year_days":{"type":"integer","title":"Streak Year Days","default":0},"can_restore":{"type":"boolean","title":"Can Restore","default":false},"past_week_activity":{"items":{"type":"boolean"},"type":"array","title":"Past Week Activity","default":[]},"free_restore_count":{"type":"integer","title":"Free Restore Count","default":0},"broken_streak_count":{"type":"integer","title":"Broken Streak Count","default":0}},"type":"object","required":["streak_count"],"title":"StreakResponse"},"StreakRestoreRequest":{"properties":{"useFreeOffer":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Usefreeoffer"},"txnId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Txnid"}},"type":"object","title":"StreakRestoreRequest"},"SubmitCommentRequest":{"properties":{"comment_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment Text"},"quick_reply_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quick Reply Text"}},"type":"object","title":"SubmitCommentRequest"},"SubmitCommentResponse":{"properties":{"success":{"type":"boolean","title":"Success"}},"type":"object","required":["success"],"title":"SubmitCommentResponse"},"SubmitLiveStreamCommentRequest":{"properties":{"comment_text":{"type":"string","title":"Comment Text"}},"type":"object","required":["comment_text"],"title":"SubmitLiveStreamCommentRequest"},"SubmitLiveStreamCommentResponse":{"properties":{"success":{"type":"boolean","title":"Success"}},"type":"object","required":["success"],"title":"SubmitLiveStreamCommentResponse"},"SubmitPrayerRequest":{"properties":{"prayer_text":{"type":"string","title":"Prayer Text"},"source_lang":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Lang"}},"type":"object","required":["prayer_text"],"title":"SubmitPrayerRequest"},"SubmitTimeSpentRequest":{"properties":{"records":{"items":{"$ref":"#/components/schemas/TimeSpentRecord"},"type":"array","title":"Records","description":"Array of time spent records"}},"type":"object","required":["records"],"title":"SubmitTimeSpentRequest","description":"Request model for submitting time spent records."},"SubmitTimeSpentResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message"}},"type":"object","required":["success","message"],"title":"SubmitTimeSpentResponse","description":"Response model for submitting time spent."},"SuggestionsResponse":{"properties":{"suggestions":{"items":{"type":"string"},"type":"array","title":"Suggestions"}},"type":"object","required":["suggestions"],"title":"SuggestionsResponse"},"TTSRequest":{"properties":{"text":{"type":"string","maxLength":4000,"minLength":1,"title":"Text","description":"Text to convert to speech (max 400 words)"}},"type":"object","required":["text"],"title":"TTSRequest"},"TTSResponse":{"properties":{"audio_base64":{"type":"string","title":"Audio Base64","description":"Base64 encoded audio data"},"mime_type":{"type":"string","title":"Mime Type","description":"MIME type of the audio"},"format":{"type":"string","title":"Format","description":"Audio format"}},"type":"object","required":["audio_base64","mime_type","format"],"title":"TTSResponse"},"TestAndroidChronometerRequest":{"properties":{"streakCount":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Streakcount","description":"Streak count shown on the card (defaults to 7)"}},"type":"object","title":"TestAndroidChronometerRequest"},"TestDreamGoalRequest":{"properties":{"goal":{"type":"string","title":"Goal"}},"type":"object","required":["goal"],"title":"TestDreamGoalRequest"},"TestLiveActivityRequest":{"properties":{"notificationType":{"$ref":"#/components/schemas/LiveActivityType","description":"standard | reminder | streak","default":"reminder"},"reminderType":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Remindertype","description":"prayer | church | devotional | custom (reminder only)"},"title":{"type":"string","title":"Title","description":"Main title text (ignored for streak type)"},"body":{"type":"string","title":"Body","description":"Subtitle / body text","default":""},"deepLinkUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deeplinkurl","description":"Override the deep link. Defaults per type/subtype when omitted."},"streakCount":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Streakcount","description":"Streak count (streak type)"},"streakDays":{"anyOf":[{"items":{"type":"boolean"},"type":"array"},{"type":"null"}],"title":"Streakdays","description":"7 booleans Sun→Sat for the reminder weekly bubbles"},"includeSnooze":{"type":"boolean","title":"Includesnooze","description":"Wire snooze fields so the 'remind me later' UI works (reminder only)","default":true},"snoozeTaskId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Snoozetaskid","description":"Reminder task id used by the snooze flow. Use a real reminder id to actually re-send on snooze; defaults to a placeholder otherwise."}},"type":"object","required":["title"],"title":"TestLiveActivityRequest"},"TestNotificationRequest":{"properties":{"sendToDevice":{"type":"boolean","title":"Sendtodevice","default":false},"deliveryMethod":{"type":"string","title":"Deliverymethod","default":"push"},"notificationType":{"type":"string","title":"Notificationtype","default":"personalized"},"timeOfDay":{"type":"string","title":"Timeofday","default":"generic"},"imageUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Imageurl"},"senderName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sendername"},"interruptionLevel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Interruptionlevel"}},"type":"object","title":"TestNotificationRequest"},"TimeSpentRecord":{"properties":{"id":{"type":"string","title":"Id","description":"Record ID (UUID from frontend)"},"started_at":{"type":"string","format":"date-time","title":"Started At","description":"Session start timestamp"},"ended_at":{"type":"string","format":"date-time","title":"Ended At","description":"Session end timestamp"}},"type":"object","required":["id","started_at","ended_at"],"title":"TimeSpentRecord","description":"Single time spent record."},"TokenProductIdentifiers":{"properties":{"default":{"type":"string","title":"Default"},"ios":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ios"},"android":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Android"}},"type":"object","required":["default"],"title":"TokenProductIdentifiers","description":"Cross-platform identifiers for a token product."},"TokenProductResponse":{"properties":{"product_id":{"$ref":"#/components/schemas/TokenProductIdentifiers"},"token_amount":{"type":"integer","title":"Token Amount"},"is_default":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Default"}},"type":"object","required":["product_id","token_amount"],"title":"TokenProductResponse","description":"Token product response model for the purchasable token catalog."},"TokenProductsResponse":{"properties":{"products":{"items":{"$ref":"#/components/schemas/TokenProductResponse"},"type":"array","title":"Products"}},"type":"object","required":["products"],"title":"TokenProductsResponse","description":"Response wrapper for the token product catalog."},"TokenTransactionResponse":{"properties":{"id":{"type":"string","title":"Id"},"user_id":{"type":"string","title":"User Id"},"type":{"$ref":"#/components/schemas/TransactionType"},"amount":{"type":"integer","title":"Amount"},"reward_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reward Id"},"item_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Item Id"},"product_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Product Id"},"store_txn_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Store Txn Id"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","user_id","type","amount","created_at"],"title":"TokenTransactionResponse","description":"Token transaction response model."},"TotalTimeSpentResponse":{"properties":{"total_minutes":{"type":"integer","title":"Total Minutes","description":"Total time spent in minutes"},"total_sessions":{"type":"integer","title":"Total Sessions","description":"Total number of sessions"}},"type":"object","required":["total_minutes","total_sessions"],"title":"TotalTimeSpentResponse","description":"Response model for total time spent."},"TransactionType":{"type":"string","enum":["earned","spent","purchased","deducted"],"title":"TransactionType","description":"Transaction types."},"TrueFalseQuestion":{"properties":{"format":{"type":"string","const":"true_false","title":"Format"},"prompt":{"type":"string","title":"Prompt"},"correct":{"type":"boolean","title":"Correct"},"explanation":{"type":"string","title":"Explanation"}},"type":"object","required":["format","prompt","correct","explanation"],"title":"TrueFalseQuestion"},"UnlockAchievementRequest":{"properties":{"achievement_key":{"type":"string","title":"Achievement Key"}},"type":"object","required":["achievement_key"],"title":"UnlockAchievementRequest","description":"Request model for unlocking an achievement."},"UnlockType":{"type":"string","enum":["free","purchasable","premium","special"],"title":"UnlockType","description":"Item unlock types."},"UnlockedItemResponse":{"properties":{"id":{"type":"string","title":"Id"},"key":{"type":"string","title":"Key"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"item_type":{"type":"string","title":"Item Type"},"unlock_type":{"$ref":"#/components/schemas/UnlockType"},"token_price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Token Price"},"available_from":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Available From"},"available_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Available Until"},"sort_order":{"type":"integer","title":"Sort Order","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"},"user_id":{"type":"string","title":"User Id"},"item_id":{"type":"string","title":"Item Id"},"unlocked_at":{"type":"string","format":"date-time","title":"Unlocked At"}},"type":"object","required":["id","key","name","item_type","unlock_type","created_at","user_id","item_id","unlocked_at"],"title":"UnlockedItemResponse","description":"Enhanced unlocked item response with full item details"},"UpdateGratitudeRequest":{"properties":{"gratitude_text":{"type":"string","title":"Gratitude Text"}},"type":"object","required":["gratitude_text"],"title":"UpdateGratitudeRequest"},"UpdateReminderRequest":{"properties":{"subtype":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subtype","description":"Reminder subtype: prayer, church, devotional, or custom"},"schedule_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Schedule Type","description":"Schedule type: daily or weekly"},"schedule_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Schedule Time","description":"Time of day in HH:MM format (e.g., '09:00')"},"schedule_day":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Schedule Day","description":"Day of week for weekly (0=Sunday, 6=Saturday)"},"custom_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Custom Text","description":"Custom reminder text (for custom subtype)"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active","description":"Whether the reminder is active"}},"type":"object","title":"UpdateReminderRequest"},"UpdateUserItemPreferencesRequest":{"properties":{"preferred_background":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preferred Background"},"preferred_hat":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preferred Hat"},"preferred_bible_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preferred Bible Id"},"preferred_symbol":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preferred Symbol"},"preferred_wing":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preferred Wing"},"preferred_color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preferred Color"},"preferred_shirt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preferred Shirt"},"preferred_face":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preferred Face"}},"type":"object","title":"UpdateUserItemPreferencesRequest"},"UserAchievementResponse":{"properties":{"id":{"type":"integer","title":"Id"},"achievement_id":{"type":"string","title":"Achievement Id"},"achieved_at":{"type":"string","format":"date-time","title":"Achieved At"},"achievement":{"$ref":"#/components/schemas/AchievementResponse"}},"type":"object","required":["id","achievement_id","achieved_at","achievement"],"title":"UserAchievementResponse","description":"User achievement response with embedded achievement details."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Supabase JWT token"}}}}