{"openapi":"3.1.0","info":{"title":"SoulStep Catalog API","description":"REST API for the SoulStep application. Supports discovering sacred sites across religions (Islam, Christianity, Hinduism, and more), check-ins, reviews, social groups, favorites, and multi-language UI translations.\n\n## Authentication\nMost endpoints require a **Bearer token** obtained from `POST /api/v1/auth/login` or `POST /api/v1/auth/register`. Pass it as:\n```\nAuthorization: Bearer <token>\n```\nRefresh tokens are issued as `HttpOnly` cookies and rotated on every `POST /api/v1/auth/refresh` call.\n\n## Rate Limiting\nAuth endpoints are rate-limited per IP: login (5/min), register (3/min), forgot-password (2/min).\n\n## Identifiers\nAll entities use opaque string codes (e.g. `usr_abc123`, `pl_xyz456`) — never numeric IDs.","version":"1.0.0"},"paths":{"/api/v1/languages":{"get":{"tags":["v1","i18n"],"summary":"Get Languages","description":"Return list of supported languages (code, name). No auth required.","operationId":"get_languages_api_v1_languages_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/translations":{"get":{"tags":["v1","i18n"],"summary":"Get Translations","description":"Return translation key -> value for the given lang.\n\nMerges in-memory seed data with any DB overrides (UITranslation rows).\nDB overrides take precedence. Fallback to English for missing keys.\nNo auth required.","operationId":"get_translations_api_v1_translations_get","parameters":[{"name":"lang","in":"query","required":false,"schema":{"type":"string","default":"en","title":"Lang"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/register":{"post":{"tags":["v1","auth"],"summary":"Register a new user","description":"Create a new user account.\n\n- **email**: must be unique\n- **password**: minimum 8 characters with at least one uppercase letter, one lowercase letter, and one digit\n- **display_name**: optional; defaults to the email prefix\n- **visitor_code**: optional; merges anonymous visitor settings into the new account","operationId":"register_api_v1_auth_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"400":{"description":"Email already registered"},"422":{"description":"Validation error — weak password or missing fields"},"429":{"description":"Rate limit exceeded (3 requests/minute per IP)"}}}},"/api/v1/auth/login":{"post":{"tags":["v1","auth"],"summary":"Log in with email and password","description":"Authenticate and receive an access token.\n\nReturns a short-lived **access token** (Bearer) in the JSON body and a long-lived\n**refresh token** in an HTTP-only `SameSite=Strict` cookie.\n\nAfter 10 consecutive failed attempts the account is locked for 15 minutes.","operationId":"login_api_v1_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"401":{"description":"Invalid credentials"},"423":{"description":"Account locked due to too many failed login attempts"},"429":{"description":"Rate limit exceeded (5 requests/minute per IP)"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/refresh":{"post":{"tags":["v1","auth"],"summary":"Refresh Token","description":"Issue a new access token using the refresh token stored in an HTTP-only cookie.","operationId":"refresh_token_api_v1_auth_refresh_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Missing, invalid, or expired refresh token"},"429":{"description":"Rate limit exceeded (10 requests/minute per IP)"}}}},"/api/v1/auth/logout":{"post":{"tags":["v1","auth"],"summary":"Logout","description":"Revoke the refresh token and clear the cookie.","operationId":"logout_api_v1_auth_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/auth/forgot-password":{"post":{"tags":["v1","auth"],"summary":"Request a password-reset email","description":"Send a password-reset link to the given email address.\n\nAlways returns a success response — even when the email is not registered —\nto avoid leaking information about registered accounts.\nThe reset link is valid for 1 hour.","operationId":"forgot_password_api_v1_auth_forgot_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"429":{"description":"Rate limit exceeded (2 requests/minute per IP)"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/reset-password":{"post":{"tags":["v1","auth"],"summary":"Reset password using a token from email","description":"Reset a user's password.\n\nConsumes the single-use token from the password-reset email.\nThe new password must meet the same strength requirements as registration.","operationId":"reset_password_api_v1_auth_reset_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid or expired token"},"422":{"description":"Validation error — password does not meet strength requirements"}}}},"/api/v1/auth/verify-email":{"post":{"tags":["v1","auth"],"summary":"Verify email address using token from verification email","description":"Consume a single-use email verification token.\n\nOn success the user's `email_verified` field becomes `true`.","operationId":"verify_email_api_v1_auth_verify_email_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyEmailBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid, expired, or already-used verification token"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/resend-verification":{"post":{"tags":["v1","auth"],"summary":"Resend email verification link","description":"Issue a new email verification token and resend the verification email.\n\nRequires a valid Bearer token. Rate-limited to 2 requests/minute.","operationId":"resend_verification_api_v1_auth_resend_verification_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"429":{"description":"Rate limit exceeded (2 requests/minute per IP)"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/field-rules":{"get":{"tags":["v1","auth"],"summary":"Field Rules","description":"Return registration field validation rules for client-side display and hint generation.","operationId":"field_rules_api_v1_auth_field_rules_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/users/me":{"get":{"tags":["v1","users"],"summary":"Get Me","operationId":"get_me_api_v1_users_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}}},"security":[{"HTTPBearer":[]}]},"delete":{"tags":["v1","users"],"summary":"Delete own account (GDPR/CCPA self-service deletion)","description":"Permanently delete the authenticated user's account.\n\n- Anonymises all PII (email, display name, password hash)\n- Soft-deletes all check-ins and reviews\n- Revokes all active refresh tokens\n- Deactivates the account (`is_active = False`)\n\nAfter this call the user's Bearer token remains technically valid until expiry,\nbut subsequent authenticated requests will fail (user not found / inactive).","operationId":"delete_me_api_v1_users_me_delete","responses":{"204":{"description":"Account deleted successfully"}},"security":[{"HTTPBearer":[]}]},"patch":{"tags":["v1","users"],"summary":"Update Me","operationId":"update_me_api_v1_users_me_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMeBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/me/check-ins":{"get":{"tags":["v1","users"],"summary":"Get My Check Ins","operationId":"get_my_check_ins_api_v1_users_me_check_ins_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/me/check-ins/this-month":{"get":{"tags":["v1","users"],"summary":"Get My Check Ins This Month","operationId":"get_my_check_ins_this_month_api_v1_users_me_check_ins_this_month_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/me/check-ins/on-this-day":{"get":{"tags":["v1","users"],"summary":"Get My Check Ins On This Day","operationId":"get_my_check_ins_on_this_day_api_v1_users_me_check_ins_on_this_day_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/me/stats":{"get":{"tags":["v1","users"],"summary":"Get My Stats","operationId":"get_my_stats_api_v1_users_me_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/me/favorites":{"get":{"tags":["v1","users"],"summary":"Get My Favorites","operationId":"get_my_favorites_api_v1_users_me_favorites_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/me/settings":{"get":{"tags":["v1","users"],"summary":"Get My Settings","operationId":"get_my_settings_api_v1_users_me_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"tags":["v1","users"],"summary":"Update My Settings","operationId":"update_my_settings_api_v1_users_me_settings_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/places/count":{"get":{"tags":["v1","places"],"summary":"Get Places Count","description":"Return the total count of all places in the database.","operationId":"get_places_count_api_v1_places_count_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/places/recommended":{"get":{"tags":["v1","places"],"summary":"Get Recommended Places","description":"Return personalised place recommendations: nearby + matching religion preference.\n\nIf lat/lng are provided, sorts by distance. Falls back to a random sample\nif no location is given. Excludes places the user has already checked in to.","operationId":"get_recommended_places_api_v1_places_recommended_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lat"}},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lng"}},{"name":"religions","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Religions"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/places":{"get":{"tags":["v1","places"],"summary":"List Places","operationId":"list_places_api_v1_places_get","parameters":[{"name":"religion","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/Religion"}},{"type":"null"}],"description":"Filter by religion(s); repeat for multiple; omit for all","title":"Religion"},"description":"Filter by religion(s); repeat for multiple; omit for all"},{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lat"}},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lng"}},{"name":"radius","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Radius in km","title":"Radius"},"description":"Radius in km"},{"name":"place_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Type"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"sort","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"proximity or rating","title":"Sort"},"description":"proximity or rating"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Page Size"}},{"name":"jummah","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"If true, only places with Jummah / Friday prayer (Islam)","title":"Jummah"},"description":"If true, only places with Jummah / Friday prayer (Islam)"},{"name":"has_events","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"If true, only places that have events","title":"Has Events"},"description":"If true, only places that have events"},{"name":"include_rating","in":"query","required":false,"schema":{"type":"boolean","description":"Include average_rating and review_count in list items","default":true,"title":"Include Rating"},"description":"Include average_rating and review_count in list items"},{"name":"open_now","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"If true, only currently open places","title":"Open Now"},"description":"If true, only currently open places"},{"name":"has_parking","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"If true, only places with parking","title":"Has Parking"},"description":"If true, only places with parking"},{"name":"womens_area","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"If true, only places with a women's area","title":"Womens Area"},"description":"If true, only places with a women's area"},{"name":"top_rated","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"If true, only places rated 4.0 or above","title":"Top Rated"},"description":"If true, only places rated 4.0 or above"},{"name":"include_checkins","in":"query","required":false,"schema":{"type":"boolean","description":"If true, include total_checkins_count per place","default":false,"title":"Include Checkins"},"description":"If true, include total_checkins_count per place"},{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"BCP-47 language code for localized content (e.g. ar, hi, te)","title":"Lang"},"description":"BCP-47 language code for localized content (e.g. ar, hi, te)"},{"name":"min_lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"South boundary of map viewport","title":"Min Lat"},"description":"South boundary of map viewport"},{"name":"max_lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"North boundary of map viewport","title":"Max Lat"},"description":"North boundary of map viewport"},{"name":"min_lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"West boundary of map viewport","title":"Min Lng"},"description":"West boundary of map viewport"},{"name":"max_lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"East boundary of map viewport","title":"Max Lng"},"description":"East boundary of map viewport"},{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by city name (case-insensitive)","title":"City"},"description":"Filter by city name (case-insensitive)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["v1","places"],"summary":"Create Place","description":"Create a new place or update an existing one if place_code matches.","operationId":"create_place_api_v1_places_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaceCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/places/{place_code}":{"get":{"tags":["v1","places"],"summary":"Get Place","operationId":"get_place_api_v1_places__place_code__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}},{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"User latitude for distance computation","title":"Lat"},"description":"User latitude for distance computation"},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"User longitude for distance computation","title":"Lng"},"description":"User longitude for distance computation"},{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"BCP-47 language code for localized content (e.g. ar, hi, te)","title":"Lang"},"description":"BCP-47 language code for localized content (e.g. ar, hi, te)"},{"name":"include_related","in":"query","required":false,"schema":{"type":"boolean","description":"Include nearby and similar places (set false to reduce latency)","default":true,"title":"Include Related"},"description":"Include nearby and similar places (set false to reduce latency)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/places/{place_code}/reviews":{"get":{"tags":["v1","places"],"summary":"Get Place Reviews","operationId":"get_place_reviews_api_v1_places__place_code__reviews_get","parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":5,"title":"Page Size"}},{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["v1","places"],"summary":"Create Review","operationId":"create_review_api_v1_places__place_code__reviews_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewCreateBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/places/{place_code}/check-in":{"post":{"tags":["v1","places"],"summary":"Check In","operationId":"check_in_api_v1_places__place_code__check_in_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckInBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/places/{place_code}/favorite":{"post":{"tags":["v1","places"],"summary":"Add Favorite","operationId":"add_favorite_api_v1_places__place_code__favorite_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","places"],"summary":"Remove Favorite","operationId":"remove_favorite_api_v1_places__place_code__favorite_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/places/batch":{"post":{"tags":["v1","places"],"summary":"Batch Create Places","description":"Create or update multiple places in a single request (up to 500).\n\nPlaces are processed in chunks of up to 50. Each chunk uses its own\nshort-lived DB session so a connection-pool timeout or transient DB error\nonly fails that chunk's places — the remaining chunks still run.\n\nOptimisations within each chunk:\n- Existing Place rows are pre-fetched in a single SELECT per chunk.\n- Location strings are resolved once per unique (city, state, country) tuple\n  and cached for the duration of the chunk.\n- Attributes are upserted in a single round-trip instead of one commit each.\n- A failed place triggers a session rollback; already-committed places are\n  not rolled back.\n\nReturns a summary with per-place action (\"created\" | \"updated\") and errors.","operationId":"batch_create_places_api_v1_places_batch_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaceBatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/places/{place_code}/images/{image_id}":{"get":{"tags":["v1","places"],"summary":"Get Place Image","description":"Serve a blob image for a place.","operationId":"get_place_image_api_v1_places__place_code__images__image_id__get","parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}},{"name":"image_id","in":"path","required":true,"schema":{"type":"integer","title":"Image Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cities":{"get":{"tags":["v1","cities"],"summary":"List Cities","description":"List all cities with place counts, sorted by count descending.","operationId":"list_cities_api_v1_cities_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Page Size"}},{"name":"include_metrics","in":"query","required":false,"schema":{"type":"boolean","description":"Include 30-day check-in metrics and popularity label per city","default":false,"title":"Include Metrics"},"description":"Include 30-day check-in metrics and popularity label per city"},{"name":"include_images","in":"query","required":false,"schema":{"type":"boolean","description":"Include up to 3 top image URLs per city for collage display","default":false,"title":"Include Images"},"description":"Include up to 3 top image URLs per city for collage display"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cities/{city_slug}":{"get":{"tags":["v1","cities"],"summary":"List Places In City","description":"List places in a city (matched by slug).","operationId":"list_places_in_city_api_v1_cities__city_slug__get","parameters":[{"name":"city_slug","in":"path","required":true,"schema":{"type":"string","title":"City Slug"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Page Size"}},{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search places by name, address, type, or religion","title":"Q"},"description":"Search places by name, address, type, or religion"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cities/{city_slug}/{religion}":{"get":{"tags":["v1","cities"],"summary":"List Places In City By Religion","description":"List places in a city filtered by religion.","operationId":"list_places_in_city_by_religion_api_v1_cities__city_slug___religion__get","parameters":[{"name":"city_slug","in":"path","required":true,"schema":{"type":"string","title":"City Slug"}},{"name":"religion","in":"path","required":true,"schema":{"type":"string","title":"Religion"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Page Size"}},{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search places by name, address, type, or religion","title":"Q"},"description":"Search places by name, address, type, or religion"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reviews/{review_code}":{"patch":{"tags":["v1","reviews"],"summary":"Update Review","operationId":"update_review_api_v1_reviews__review_code__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"review_code","in":"path","required":true,"schema":{"type":"string","title":"Review Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewUpdateBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","reviews"],"summary":"Delete Review","operationId":"delete_review_api_v1_reviews__review_code__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"review_code","in":"path","required":true,"schema":{"type":"string","title":"Review Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reviews/upload-photo":{"post":{"tags":["v1","reviews"],"summary":"Upload Review Photo","description":"Upload a photo for use in a review.\n\nAccepts JPEG, PNG, or WebP images up to 5MB.\nImages are resized to max 1200px width and compressed to 85% JPEG quality.\nReturns image ID and URL for inclusion in review photo_urls.","operationId":"upload_review_photo_api_v1_reviews_upload_photo_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_review_photo_api_v1_reviews_upload_photo_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/reviews/images/{image_id}":{"get":{"tags":["v1","reviews"],"summary":"Get Review Image","description":"Serve a review image by ID.\nReturns the image blob with aggressive caching (1 year).","operationId":"get_review_image_api_v1_reviews_images__image_id__get","parameters":[{"name":"image_id","in":"path","required":true,"schema":{"type":"integer","title":"Image Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups":{"get":{"tags":["v1","groups"],"summary":"List Groups","operationId":"list_groups_api_v1_groups_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["v1","groups"],"summary":"Create Group","operationId":"create_group_api_v1_groups_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupCreateBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/groups/featured":{"get":{"tags":["v1","groups"],"summary":"List Featured Groups","description":"Return public featured journeys for the Popular Journeys carousel.\nNo authentication required — only is_featured=True groups are returned.","operationId":"list_featured_groups_api_v1_groups_featured_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/groups/by-invite/{invite_code}":{"get":{"tags":["v1","groups"],"summary":"Get Group By Invite","description":"Resolve group_code from invite code (for join flow).","operationId":"get_group_by_invite_api_v1_groups_by_invite__invite_code__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"invite_code","in":"path","required":true,"schema":{"type":"string","title":"Invite Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/join-by-code":{"post":{"tags":["v1","groups"],"summary":"Join By Invite Code","description":"Join a group using invite code (from /join?code=xxx).","operationId":"join_by_invite_code_api_v1_groups_join_by_code_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/groups/{group_code}":{"get":{"tags":["v1","groups"],"summary":"Get Group","operationId":"get_group_api_v1_groups__group_code__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["v1","groups"],"summary":"Update Group","operationId":"update_group_api_v1_groups__group_code__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupUpdateBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","groups"],"summary":"Delete Group","operationId":"delete_group_api_v1_groups__group_code__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_code}/join":{"post":{"tags":["v1","groups"],"summary":"Join Group","operationId":"join_group_api_v1_groups__group_code__join_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_code}/leave":{"post":{"tags":["v1","groups"],"summary":"Leave Group","operationId":"leave_group_api_v1_groups__group_code__leave_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_code}/members":{"get":{"tags":["v1","groups"],"summary":"Get Group Members","operationId":"get_group_members_api_v1_groups__group_code__members_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_code}/members/{target_user_code}":{"delete":{"tags":["v1","groups"],"summary":"Remove Member","operationId":"remove_member_api_v1_groups__group_code__members__target_user_code__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}},{"name":"target_user_code","in":"path","required":true,"schema":{"type":"string","title":"Target User Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["v1","groups"],"summary":"Update Member Role","operationId":"update_member_role_api_v1_groups__group_code__members__target_user_code__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}},{"name":"target_user_code","in":"path","required":true,"schema":{"type":"string","title":"Target User Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMemberRoleBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_code}/leaderboard":{"get":{"tags":["v1","groups"],"summary":"Get Leaderboard","operationId":"get_leaderboard_api_v1_groups__group_code__leaderboard_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_code}/activity":{"get":{"tags":["v1","groups"],"summary":"Get Activity","operationId":"get_activity_api_v1_groups__group_code__activity_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_code}/checklist":{"get":{"tags":["v1","groups"],"summary":"Get Checklist","description":"Return the shared itinerary checklist with per-place check-in status and notes.","operationId":"get_checklist_api_v1_groups__group_code__checklist_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_code}/optimize-route":{"post":{"tags":["v1","groups"],"summary":"Optimize Route","description":"Reorder path_place_codes using a nearest-neighbor greedy algorithm.\n\nStarts from the first place in the current itinerary and repeatedly picks\nthe closest unvisited place, minimising total walk distance.  Requires\nadmin membership.","operationId":"optimize_route_api_v1_groups__group_code__optimize_route_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_code}/places/{place_code}":{"post":{"tags":["v1","groups"],"summary":"Add Place To Itinerary","description":"Append a place to the group's itinerary. Any member can call this.","operationId":"add_place_to_itinerary_api_v1_groups__group_code__places__place_code__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}},{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_code}/places/{place_code}/notes":{"get":{"tags":["v1","groups"],"summary":"Get Place Notes","operationId":"get_place_notes_api_v1_groups__group_code__places__place_code__notes_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}},{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["v1","groups"],"summary":"Add Place Note","operationId":"add_place_note_api_v1_groups__group_code__places__place_code__notes_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}},{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupPlaceNoteBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_code}/notes/{note_code}":{"delete":{"tags":["v1","groups"],"summary":"Delete Place Note","operationId":"delete_place_note_api_v1_groups__group_code__notes__note_code__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}},{"name":"note_code","in":"path","required":true,"schema":{"type":"string","title":"Note Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_code}/invite":{"post":{"tags":["v1","groups"],"summary":"Create Invite","operationId":"create_invite_api_v1_groups__group_code__invite_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/upload-cover":{"post":{"tags":["v1","groups"],"summary":"Upload Group Cover","description":"Upload a cover image for a group. Returns image_code and URL.","operationId":"upload_group_cover_api_v1_groups_upload_cover_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_group_cover_api_v1_groups_upload_cover_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/groups/cover/{image_code}":{"get":{"tags":["v1","groups"],"summary":"Get Cover Image","description":"Serve a group cover image by code.","operationId":"get_cover_image_api_v1_groups_cover__image_code__get","parameters":[{"name":"image_code","in":"path","required":true,"schema":{"type":"string","title":"Image Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications":{"get":{"tags":["v1","notifications"],"summary":"List Notifications","operationId":"list_notifications_api_v1_notifications_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications/{notification_code}/read":{"patch":{"tags":["v1","notifications"],"summary":"Mark Notification Read","operationId":"mark_notification_read_api_v1_notifications__notification_code__read_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"notification_code","in":"path","required":true,"schema":{"type":"string","title":"Notification Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/visitors":{"post":{"tags":["v1","visitors"],"summary":"Create Visitor","description":"Create a new anonymous visitor identity. No auth required.","operationId":"create_visitor_api_v1_visitors_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorResponse"}}}}}}},"/api/v1/visitors/{visitor_code}/settings":{"get":{"tags":["v1","visitors"],"summary":"Get Visitor Settings","description":"Retrieve settings for an anonymous visitor. No auth required.","operationId":"get_visitor_settings_api_v1_visitors__visitor_code__settings_get","parameters":[{"name":"visitor_code","in":"path","required":true,"schema":{"type":"string","title":"Visitor Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorSettingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["v1","visitors"],"summary":"Update Visitor Settings","description":"Update settings for an anonymous visitor. No auth required.","operationId":"update_visitor_settings_api_v1_visitors__visitor_code__settings_patch","parameters":[{"name":"visitor_code","in":"path","required":true,"schema":{"type":"string","title":"Visitor Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorSettingsBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorSettingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/search/autocomplete":{"get":{"tags":["v1","search"],"summary":"Autocomplete","description":"Proxy to Google Places autocomplete. Returns suggestions list.\n\nResults are cached in-process for 10 minutes to avoid redundant API calls\nfrom keystroke-by-keystroke typing in the frontend search box.","operationId":"autocomplete_api_v1_search_autocomplete_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2,"title":"Q"}},{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lat"}},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lng"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/search/place-details":{"get":{"tags":["v1","search"],"summary":"Place Details","description":"Proxy to Google Place Details. Returns lat/lng and display info.","operationId":"place_details_api_v1_search_place_details_get","parameters":[{"name":"place_id","in":"query","required":true,"schema":{"type":"string","title":"Place Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ads/config":{"get":{"tags":["v1","ads","ads"],"summary":"Get Ad Config","description":"Return ad configuration for the web app (no auth required).","operationId":"get_ad_config_api_v1_ads_config_get","parameters":[{"name":"platform","in":"query","required":false,"schema":{"type":"string","pattern":"^web$","default":"web","title":"Platform"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdConfigResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/consent":{"post":{"tags":["v1","ads","ads"],"summary":"Record Consent","description":"Record a consent choice (ads or analytics). Works for both logged-in users and visitors.","operationId":"record_consent_api_v1_consent_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsentBody"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["v1","ads","ads"],"summary":"Get Consent Status","description":"Return the latest consent status for the current user or visitor.","operationId":"get_consent_status_api_v1_consent_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"visitor_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Visitor Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsentStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analytics/events":{"post":{"tags":["v1","analytics","analytics"],"summary":"Ingest Events","description":"Ingest a batch of analytics events (authenticated or anonymous).","operationId":"ingest_events_api_v1_analytics_events_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsIngestionBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsIngestionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/homepage":{"get":{"tags":["v1","homepage"],"summary":"Get Homepage","description":"Single composite endpoint returning all homepage data.","operationId":"get_homepage_api_v1_homepage_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lat"}},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lng"}},{"name":"religions","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Religions"}},{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blog/posts":{"get":{"tags":["v1","blog"],"summary":"List Blog Posts","description":"Return published posts ordered newest first (content excluded).\n\nSupports optional server-side search, category, and tag filters.","operationId":"list_blog_posts_api_v1_blog_posts_get","parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},{"name":"tag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tag"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Blog Posts Api V1 Blog Posts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blog/posts/{slug}":{"get":{"tags":["v1","blog"],"summary":"Get Blog Post","description":"Return a single published post by slug including full content.","operationId":"get_blog_post_api_v1_blog_posts__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Blog Post Api V1 Blog Posts  Slug  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blog/posts/{slug}/view":{"post":{"tags":["v1","blog"],"summary":"Track View","description":"Increment the view counter for a published blog post.","operationId":"track_view_api_v1_blog_posts__slug__view_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blog/posts/{slug}/link-click":{"post":{"tags":["v1","blog"],"summary":"Track Link Click","description":"Increment the link-click counter for a published blog post.","operationId":"track_link_click_api_v1_blog_posts__slug__link_click_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/scraper/data-locations":{"get":{"tags":["v1","admin","admin-scraper"],"summary":"List Data Locations","operationId":"list_data_locations_api_v1_admin_scraper_data_locations_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["v1","admin","admin-scraper"],"summary":"Create Data Location","operationId":"create_data_location_api_v1_admin_scraper_data_locations_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/scraper/data-locations/{code}":{"delete":{"tags":["v1","admin","admin-scraper"],"summary":"Delete Data Location","operationId":"delete_data_location_api_v1_admin_scraper_data_locations__code__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/scraper/runs":{"get":{"tags":["v1","admin","admin-scraper"],"summary":"List Runs","operationId":"list_runs_api_v1_admin_scraper_runs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["v1","admin","admin-scraper"],"summary":"Start Run","operationId":"start_run_api_v1_admin_scraper_runs_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/scraper/runs/{run_code}":{"get":{"tags":["v1","admin","admin-scraper"],"summary":"Get Run","operationId":"get_run_api_v1_admin_scraper_runs__run_code__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_code","in":"path","required":true,"schema":{"type":"string","title":"Run Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","admin","admin-scraper"],"summary":"Delete Run","operationId":"delete_run_api_v1_admin_scraper_runs__run_code__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_code","in":"path","required":true,"schema":{"type":"string","title":"Run Code"}},{"name":"delete_catalog_places","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Delete Catalog Places"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/scraper/runs/{run_code}/data":{"get":{"tags":["v1","admin","admin-scraper"],"summary":"Get Run Data","operationId":"get_run_data_api_v1_admin_scraper_runs__run_code__data_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_code","in":"path","required":true,"schema":{"type":"string","title":"Run Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/scraper/runs/{run_code}/raw-data":{"get":{"tags":["v1","admin","admin-scraper"],"summary":"Get Run Raw Data","operationId":"get_run_raw_data_api_v1_admin_scraper_runs__run_code__raw_data_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_code","in":"path","required":true,"schema":{"type":"string","title":"Run Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/scraper/runs/{run_code}/sync":{"post":{"tags":["v1","admin","admin-scraper"],"summary":"Sync Run","operationId":"sync_run_api_v1_admin_scraper_runs__run_code__sync_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_code","in":"path","required":true,"schema":{"type":"string","title":"Run Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/scraper/runs/{run_code}/re-enrich":{"post":{"tags":["v1","admin","admin-scraper"],"summary":"Re Enrich Run","operationId":"re_enrich_run_api_v1_admin_scraper_runs__run_code__re_enrich_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_code","in":"path","required":true,"schema":{"type":"string","title":"Run Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/scraper/runs/{run_code}/resume":{"post":{"tags":["v1","admin","admin-scraper"],"summary":"Resume Run","operationId":"resume_run_api_v1_admin_scraper_runs__run_code__resume_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_code","in":"path","required":true,"schema":{"type":"string","title":"Run Code"}},{"name":"force","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/scraper/runs/{run_code}/cancel":{"post":{"tags":["v1","admin","admin-scraper"],"summary":"Cancel Run","operationId":"cancel_run_api_v1_admin_scraper_runs__run_code__cancel_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_code","in":"path","required":true,"schema":{"type":"string","title":"Run Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/scraper/runs/{run_code}/retry-images":{"post":{"tags":["v1","admin","admin-scraper"],"summary":"Retry Images","operationId":"retry_images_api_v1_admin_scraper_runs__run_code__retry_images_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_code","in":"path","required":true,"schema":{"type":"string","title":"Run Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/scraper/runs/{run_code}/activity":{"get":{"tags":["v1","admin","admin-scraper"],"summary":"Get Run Activity","operationId":"get_run_activity_api_v1_admin_scraper_runs__run_code__activity_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_code","in":"path","required":true,"schema":{"type":"string","title":"Run Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/scraper/runs/{run_code}/cells":{"get":{"tags":["v1","admin","admin-scraper"],"summary":"Get Run Cells","operationId":"get_run_cells_api_v1_admin_scraper_runs__run_code__cells_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_code","in":"path","required":true,"schema":{"type":"string","title":"Run Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/scraper/stats":{"get":{"tags":["v1","admin","admin-scraper"],"summary":"Get Scraper Stats","operationId":"get_scraper_stats_api_v1_admin_scraper_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/scraper/collectors":{"get":{"tags":["v1","admin","admin-scraper"],"summary":"List Collectors","operationId":"list_collectors_api_v1_admin_scraper_collectors_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/scraper/quality-metrics":{"get":{"tags":["v1","admin","admin-scraper"],"summary":"Get Quality Metrics","operationId":"get_quality_metrics_api_v1_admin_scraper_quality_metrics_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/scraper/cleanup/images":{"post":{"tags":["v1","admin","admin-scraper"],"summary":"Cleanup Images","description":"Trigger the scraper's image cleanup worker.\n\nRetries image downloads for all ScrapedPlaces that have pending image_urls\nbut no image_blobs. Runs in the background on the scraper service; results\nare written to the scraper service logs.","operationId":"cleanup_images_api_v1_admin_scraper_cleanup_images_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/scraper/runs/{run_code}/places/{place_code}/quality-breakdown":{"get":{"tags":["v1","admin","admin-scraper"],"summary":"Get Place Quality Breakdown","operationId":"get_place_quality_breakdown_api_v1_admin_scraper_runs__run_code__places__place_code__quality_breakdown_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_code","in":"path","required":true,"schema":{"type":"string","title":"Run Code"}},{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/scraper/map/cells":{"get":{"tags":["v1","admin","admin-scraper"],"summary":"Get Map Cells","operationId":"get_map_cells_api_v1_admin_scraper_map_cells_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/scraper/map/places":{"get":{"tags":["v1","admin","admin-scraper"],"summary":"Get Map Places","operationId":"get_map_places_api_v1_admin_scraper_map_places_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/scraper/place-type-mappings":{"get":{"tags":["v1","admin","admin-scraper"],"summary":"List Place Type Mappings","operationId":"list_place_type_mappings_api_v1_admin_scraper_place_type_mappings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["v1","admin","admin-scraper"],"summary":"Create Place Type Mapping","operationId":"create_place_type_mapping_api_v1_admin_scraper_place_type_mappings_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/scraper/place-type-mappings/{mapping_id}":{"put":{"tags":["v1","admin","admin-scraper"],"summary":"Update Place Type Mapping","operationId":"update_place_type_mapping_api_v1_admin_scraper_place_type_mappings__mapping_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"mapping_id","in":"path","required":true,"schema":{"type":"integer","title":"Mapping Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","admin","admin-scraper"],"summary":"Delete Place Type Mapping","operationId":"delete_place_type_mapping_api_v1_admin_scraper_place_type_mappings__mapping_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"mapping_id","in":"path","required":true,"schema":{"type":"integer","title":"Mapping Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users":{"get":{"tags":["v1","admin","admin-users"],"summary":"List Users","operationId":"list_users_api_v1_admin_users_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"is_active","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"}},{"name":"is_admin","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Admin"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_code}":{"get":{"tags":["v1","admin","admin-users"],"summary":"Get User","operationId":"get_user_api_v1_admin_users__user_code__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_code","in":"path","required":true,"schema":{"type":"string","title":"User Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["v1","admin","admin-users"],"summary":"Patch User","operationId":"patch_user_api_v1_admin_users__user_code__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_code","in":"path","required":true,"schema":{"type":"string","title":"User Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchUserBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","admin","admin-users"],"summary":"Deactivate User","description":"Soft-delete: sets is_active=False.","operationId":"deactivate_user_api_v1_admin_users__user_code__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_code","in":"path","required":true,"schema":{"type":"string","title":"User Code"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_code}/check-ins":{"get":{"tags":["v1","admin","admin-users"],"summary":"List User Check Ins","operationId":"list_user_check_ins_api_v1_admin_users__user_code__check_ins_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_code","in":"path","required":true,"schema":{"type":"string","title":"User Code"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__v1__admin__users__AdminCheckInListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_code}/reviews":{"get":{"tags":["v1","admin","admin-users"],"summary":"List User Reviews","operationId":"list_user_reviews_api_v1_admin_users__user_code__reviews_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_code","in":"path","required":true,"schema":{"type":"string","title":"User Code"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__v1__admin__users__AdminReviewListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/places":{"get":{"tags":["v1","admin","admin-places"],"summary":"List Places","operationId":"list_places_api_v1_admin_places_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"religion","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Religion"}},{"name":"place_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Type"}},{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"}},{"name":"country","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPlaceListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["v1","admin","admin-places"],"summary":"Create Place","operationId":"create_place_api_v1_admin_places_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlaceBody"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPlaceDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/places/data-quality":{"get":{"tags":["v1","admin","admin-places"],"summary":"Get Data Quality","description":"List places with known data-quality issues.\n\nIssues reported:\n- ``null_coordinates`` — lat or lng is NULL (no location data)\n- ``zero_coordinates``  — lat=0.0 and lng=0.0 (sentinel from old scraper)\n- ``unknown_religion``  — religion field is 'unknown'","operationId":"get_data_quality_api_v1_admin_places_data_quality_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/DataQualityItem"},"type":"array","title":"Response Get Data Quality Api V1 Admin Places Data Quality Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/places/{place_code}":{"get":{"tags":["v1","admin","admin-places"],"summary":"Get Place","operationId":"get_place_api_v1_admin_places__place_code__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPlaceDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["v1","admin","admin-places"],"summary":"Patch Place","operationId":"patch_place_api_v1_admin_places__place_code__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchPlaceBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPlaceDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","admin","admin-places"],"summary":"Delete Place","operationId":"delete_place_api_v1_admin_places__place_code__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/places/batch":{"delete":{"tags":["v1","admin","admin-places"],"summary":"Batch Delete Places","operationId":"batch_delete_places_api_v1_admin_places_batch_delete","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchDeleteBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/places/all":{"delete":{"tags":["v1","admin","admin-places"],"summary":"Delete All Places","operationId":"delete_all_places_api_v1_admin_places_all_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/places/{place_code}/images":{"get":{"tags":["v1","admin","admin-places"],"summary":"List Place Images","operationId":"list_place_images_api_v1_admin_places__place_code__images_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AdminPlaceImageItem"},"title":"Response List Place Images Api V1 Admin Places  Place Code  Images Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/places/{place_code}/images/{image_id}":{"delete":{"tags":["v1","admin","admin-places"],"summary":"Delete Place Image","operationId":"delete_place_image_api_v1_admin_places__place_code__images__image_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}},{"name":"image_id","in":"path","required":true,"schema":{"type":"integer","title":"Image Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/reviews":{"get":{"tags":["v1","admin","admin-reviews"],"summary":"List Reviews","operationId":"list_reviews_api_v1_admin_reviews_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}},{"name":"is_flagged","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Flagged"}},{"name":"place_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Code"}},{"name":"user_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Code"}},{"name":"min_rating","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":5,"minimum":1},{"type":"null"}],"title":"Min Rating"}},{"name":"max_rating","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":5,"minimum":1},{"type":"null"}],"title":"Max Rating"}},{"name":"include_deleted","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Deleted"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__v1__admin__reviews__AdminReviewListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/reviews/{review_code}":{"get":{"tags":["v1","admin","admin-reviews"],"summary":"Get Review","operationId":"get_review_api_v1_admin_reviews__review_code__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"review_code","in":"path","required":true,"schema":{"type":"string","title":"Review Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminReviewDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["v1","admin","admin-reviews"],"summary":"Patch Review","operationId":"patch_review_api_v1_admin_reviews__review_code__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"review_code","in":"path","required":true,"schema":{"type":"string","title":"Review Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchReviewBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminReviewDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","admin","admin-reviews"],"summary":"Delete Review","operationId":"delete_review_api_v1_admin_reviews__review_code__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"review_code","in":"path","required":true,"schema":{"type":"string","title":"Review Code"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/check-ins":{"get":{"tags":["v1","admin","admin-check-ins"],"summary":"List Check Ins","operationId":"list_check_ins_api_v1_admin_check_ins_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}},{"name":"place_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Code"}},{"name":"user_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Code"}},{"name":"group_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Group Code"}},{"name":"from_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Date"}},{"name":"to_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Date"}},{"name":"include_deleted","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Deleted"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__api__v1__admin__check_ins__AdminCheckInListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/check-ins/{check_in_code}":{"delete":{"tags":["v1","admin","admin-check-ins"],"summary":"Delete Check In","operationId":"delete_check_in_api_v1_admin_check_ins__check_in_code__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"check_in_code","in":"path","required":true,"schema":{"type":"string","title":"Check In Code"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/groups":{"get":{"tags":["v1","admin","admin-groups"],"summary":"List Groups","operationId":"list_groups_api_v1_admin_groups_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminGroupListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/groups/{group_code}":{"get":{"tags":["v1","admin","admin-groups"],"summary":"Get Group","operationId":"get_group_api_v1_admin_groups__group_code__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminGroupDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["v1","admin","admin-groups"],"summary":"Patch Group","operationId":"patch_group_api_v1_admin_groups__group_code__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchGroupBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminGroupDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","admin","admin-groups"],"summary":"Delete Group","operationId":"delete_group_api_v1_admin_groups__group_code__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/groups/{group_code}/members":{"get":{"tags":["v1","admin","admin-groups"],"summary":"List Group Members","operationId":"list_group_members_api_v1_admin_groups__group_code__members_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminGroupMemberListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/groups/{group_code}/members/{user_code}":{"delete":{"tags":["v1","admin","admin-groups"],"summary":"Remove Group Member","operationId":"remove_group_member_api_v1_admin_groups__group_code__members__user_code__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_code","in":"path","required":true,"schema":{"type":"string","title":"Group Code"}},{"name":"user_code","in":"path","required":true,"schema":{"type":"string","title":"User Code"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/translations/jobs":{"get":{"tags":["v1","admin","admin-bulk-translations"],"summary":"List Translation Jobs","description":"List all bulk translation jobs, newest first.","operationId":"list_translation_jobs_api_v1_admin_translations_jobs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/translations/jobs/{job_code}":{"get":{"tags":["v1","admin","admin-bulk-translations"],"summary":"Get Translation Job","description":"Get progress details for a specific job.","operationId":"get_translation_job_api_v1_admin_translations_jobs__job_code__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_code","in":"path","required":true,"schema":{"type":"string","title":"Job Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTranslationJobOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","admin","admin-bulk-translations"],"summary":"Delete Translation Job","description":"Delete a completed or failed job. Returns 409 if the job is still running.","operationId":"delete_translation_job_api_v1_admin_translations_jobs__job_code__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_code","in":"path","required":true,"schema":{"type":"string","title":"Job Code"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/translations":{"get":{"tags":["v1","admin","admin-translations"],"summary":"List Translations","description":"List all known translation keys with per-language values.\n\nShows keys from seed data (union) any DB-only keys.\nThe supported language set is derived from the i18n store at runtime.\nThe overridden_langs field indicates which values are DB overrides.","operationId":"list_translations_api_v1_admin_translations_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TranslationEntry"},"title":"Response List Translations Api V1 Admin Translations Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["v1","admin","admin-translations"],"summary":"Create Translation","description":"Create a new translation key that does not exist in seed data.","operationId":"create_translation_api_v1_admin_translations_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTranslationBody"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationEntry"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/translations/{key}":{"get":{"tags":["v1","admin","admin-translations"],"summary":"Get Translation","description":"Get a single translation key with values for all supported languages.","operationId":"get_translation_api_v1_admin_translations__key__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationEntry"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["v1","admin","admin-translations"],"summary":"Upsert Translation","description":"Upsert DB overrides for one or more languages of a key.\n\nAccepts any subset of supported language codes in body.values.","operationId":"upsert_translation_api_v1_admin_translations__key__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertTranslationBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslationEntry"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","admin","admin-translations"],"summary":"Delete Translation","description":"Remove all DB overrides for this key (reverts all langs to seed values).","operationId":"delete_translation_api_v1_admin_translations__key__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/content-translations/stats":{"get":{"tags":["v1","admin","admin-content-translations"],"summary":"Content Translation Stats","description":"Return per-language translation coverage: translated / eligible counts.\n\n\"Eligible\" = number of distinct (entity_type, entity_code, field) triples\nthat have English source text across all entity types (place, city,\nattribute_def, review, spec_value, etc.).\n\n\"Translated\" = number of ContentTranslation rows for that language.\n\nPer-language: each triple needs a translation in each target language.","operationId":"content_translation_stats_api_v1_admin_content_translations_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentTranslationStats"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/content-translations":{"get":{"tags":["v1","admin","admin-content-translations"],"summary":"List Content Translations","operationId":"list_content_translations_api_v1_admin_content_translations_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}},{"name":"entity_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Type"}},{"name":"entity_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Code"}},{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang"}},{"name":"field","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Field"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentTranslationListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["v1","admin","admin-content-translations"],"summary":"Create Content Translation","operationId":"create_content_translation_api_v1_admin_content_translations_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContentTranslationBody"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminContentTranslation"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/content-translations/{translation_id}":{"put":{"tags":["v1","admin","admin-content-translations"],"summary":"Update Content Translation","operationId":"update_content_translation_api_v1_admin_content_translations__translation_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"translation_id","in":"path","required":true,"schema":{"type":"integer","title":"Translation Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContentTranslationBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminContentTranslation"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","admin","admin-content-translations"],"summary":"Delete Content Translation","operationId":"delete_content_translation_api_v1_admin_content_translations__translation_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"translation_id","in":"path","required":true,"schema":{"type":"integer","title":"Translation Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/content-translations/export-untranslated":{"get":{"tags":["v1","admin","admin-content-translations"],"summary":"Export Untranslated","description":"Return all (entity, field, lang) triples that are missing a ContentTranslation row.\n\nSupports entity_types=place,city,attribute_def,review (default: all four).\nThe exported JSON is the input format for translate_content_claude.py.","operationId":"export_untranslated_api_v1_admin_content_translations_export_untranslated_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"langs","in":"query","required":false,"schema":{"type":"string","description":"Comma-separated lang codes","default":"ar,hi,te,ml","title":"Langs"},"description":"Comma-separated lang codes"},{"name":"entity_types","in":"query","required":false,"schema":{"type":"string","description":"Comma-separated entity types to include","default":"place,city,attribute_def,review","title":"Entity Types"},"description":"Comma-separated entity types to include"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UntranslatedPlaceItem"},"title":"Response Export Untranslated Api V1 Admin Content Translations Export Untranslated Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/content-translations/bulk-upsert":{"post":{"tags":["v1","admin","admin-content-translations"],"summary":"Bulk Upsert Translations","description":"Upsert a flat array of translation records.\n\nOptimised: one bulk SELECT to load all existing rows for the affected\nentity_codes, then process items against an in-memory lookup dict —\nno per-item SELECT queries. Commits every _BULK_UPSERT_CHUNK rows to\nkeep transaction size bounded.","operationId":"bulk_upsert_translations_api_v1_admin_content_translations_bulk_upsert_post","requestBody":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/BulkUpsertItem"},"type":"array","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkUpsertResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/content-translations/export-txt":{"get":{"tags":["v1","admin","admin-content-translations"],"summary":"Export Untranslated Txt","description":"Export missing translations as a .txt file for use with external bulk translator sites.\n\nEach line: [type_num:entity_id:field_num] {{ english text }}\nAll components are integers — safe from accidental translation.","operationId":"export_untranslated_txt_api_v1_admin_content_translations_export_txt_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"langs","in":"query","required":false,"schema":{"type":"string","default":"ar,hi,te,ml","title":"Langs"}},{"name":"entity_types","in":"query","required":false,"schema":{"type":"string","default":"place,city,attribute_def,review","title":"Entity Types"}}],"responses":{"200":{"description":"Successful Response","content":{"text/plain":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/content-translations/import-txt":{"post":{"tags":["v1","admin","admin-content-translations"],"summary":"Import Translated Txt","description":"Import a translated .txt file (one language at a time) and create a job record.\n\nParses [type_num:entity_id:field_num] {{ translated text }} lines.\nResolves entity codes via batch DB lookups (one query per entity type).","operationId":"import_translated_txt_api_v1_admin_content_translations_import_txt_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_import_translated_txt_api_v1_admin_content_translations_import_txt_post"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/_BulkTranslationJobOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/place-attributes":{"get":{"tags":["v1","admin","admin-place-attributes"],"summary":"List Place Attribute Definitions","description":"List all PlaceAttributeDefinitions with per-definition usage counts.","operationId":"list_place_attribute_definitions_api_v1_admin_place_attributes_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/AttributeDefinitionItem"},"type":"array","title":"Response List Place Attribute Definitions Api V1 Admin Place Attributes Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/place-attributes/{place_code}":{"get":{"tags":["v1","admin","admin-place-attributes"],"summary":"List Place Attributes","description":"List all attributes set on a specific place.","operationId":"list_place_attributes_api_v1_admin_place_attributes__place_code__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PlaceAttributeItem"},"title":"Response List Place Attributes Api V1 Admin Place Attributes  Place Code  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["v1","admin","admin-place-attributes"],"summary":"Bulk Update Place Attributes","description":"Bulk upsert attributes for a place. Each entry is upserted by attribute_code.","operationId":"bulk_update_place_attributes_api_v1_admin_place_attributes__place_code__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkUpdateAttributesBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PlaceAttributeItem"},"title":"Response Bulk Update Place Attributes Api V1 Admin Place Attributes  Place Code  Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/stats/overview":{"get":{"tags":["v1","admin","admin-stats"],"summary":"Get Overview Stats","operationId":"get_overview_stats_api_v1_admin_stats_overview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OverviewStats"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/stats/user-growth":{"get":{"tags":["v1","admin","admin-stats"],"summary":"Get User Growth","operationId":"get_user_growth_api_v1_admin_stats_user_growth_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"interval","in":"query","required":false,"schema":{"type":"string","pattern":"^(day|week|month)$","default":"day","title":"Interval"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GrowthDataPoint"},"title":"Response Get User Growth Api V1 Admin Stats User Growth Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/stats/popular-places":{"get":{"tags":["v1","admin","admin-stats"],"summary":"Get Popular Places","operationId":"get_popular_places_api_v1_admin_stats_popular_places_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/PopularPlace"},"type":"array","title":"Response Get Popular Places Api V1 Admin Stats Popular Places Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/stats/religion-breakdown":{"get":{"tags":["v1","admin","admin-stats"],"summary":"Get Religion Breakdown","operationId":"get_religion_breakdown_api_v1_admin_stats_religion_breakdown_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ReligionBreakdownItem"},"type":"array","title":"Response Get Religion Breakdown Api V1 Admin Stats Religion Breakdown Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/stats/recent-activity":{"get":{"tags":["v1","admin","admin-stats"],"summary":"Get Recent Activity","operationId":"get_recent_activity_api_v1_admin_stats_recent_activity_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/RecentActivityItem"},"type":"array","title":"Response Get Recent Activity Api V1 Admin Stats Recent Activity Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/stats/review-stats":{"get":{"tags":["v1","admin","admin-stats"],"summary":"Get Review Stats","operationId":"get_review_stats_api_v1_admin_stats_review_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewStats"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/bulk/users/deactivate":{"post":{"tags":["v1","admin","admin-bulk"],"summary":"Bulk Deactivate Users","operationId":"bulk_deactivate_users_api_v1_admin_bulk_users_deactivate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkUserCodesBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/bulk/users/activate":{"post":{"tags":["v1","admin","admin-bulk"],"summary":"Bulk Activate Users","operationId":"bulk_activate_users_api_v1_admin_bulk_users_activate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkUserCodesBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/bulk/reviews/flag":{"post":{"tags":["v1","admin","admin-bulk"],"summary":"Bulk Flag Reviews","operationId":"bulk_flag_reviews_api_v1_admin_bulk_reviews_flag_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkReviewCodesBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/bulk/reviews/unflag":{"post":{"tags":["v1","admin","admin-bulk"],"summary":"Bulk Unflag Reviews","operationId":"bulk_unflag_reviews_api_v1_admin_bulk_reviews_unflag_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkReviewCodesBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/bulk/reviews/delete":{"post":{"tags":["v1","admin","admin-bulk"],"summary":"Bulk Delete Reviews","operationId":"bulk_delete_reviews_api_v1_admin_bulk_reviews_delete_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkReviewCodesBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/bulk/check-ins/delete":{"post":{"tags":["v1","admin","admin-bulk"],"summary":"Bulk Delete Check Ins","operationId":"bulk_delete_check_ins_api_v1_admin_bulk_check_ins_delete_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkCheckInCodesBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/bulk/places/delete":{"post":{"tags":["v1","admin","admin-bulk"],"summary":"Bulk Delete Places","operationId":"bulk_delete_places_api_v1_admin_bulk_places_delete_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkPlaceCodesBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/bulk/groups/delete":{"post":{"tags":["v1","admin","admin-bulk"],"summary":"Bulk Delete Groups","operationId":"bulk_delete_groups_api_v1_admin_bulk_groups_delete_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkGroupCodesBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/export/users":{"get":{"tags":["v1","admin","admin-export"],"summary":"Export Users","operationId":"export_users_api_v1_admin_export_users_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"csv","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/export/places":{"get":{"tags":["v1","admin","admin-export"],"summary":"Export Places","operationId":"export_places_api_v1_admin_export_places_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"csv","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/export/reviews":{"get":{"tags":["v1","admin","admin-export"],"summary":"Export Reviews","operationId":"export_reviews_api_v1_admin_export_reviews_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"csv","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/export/check-ins":{"get":{"tags":["v1","admin","admin-export"],"summary":"Export Check Ins","operationId":"export_check_ins_api_v1_admin_export_check_ins_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"csv","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/export/groups":{"get":{"tags":["v1","admin","admin-export"],"summary":"Export Groups","operationId":"export_groups_api_v1_admin_export_groups_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"csv","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/audit-log":{"get":{"tags":["v1","admin","admin-audit-log"],"summary":"List Audit Log","operationId":"list_audit_log_api_v1_admin_audit_log_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}},{"name":"admin_user_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Admin User Code"}},{"name":"entity_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Type"}},{"name":"action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action"}},{"name":"from_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Date"}},{"name":"to_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Date"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLogListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/audit-log/{log_code}":{"get":{"tags":["v1","admin","admin-audit-log"],"summary":"Get Audit Log Entry","operationId":"get_audit_log_entry_api_v1_admin_audit_log__log_code__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"log_code","in":"path","required":true,"schema":{"type":"string","title":"Log Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLogItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/notifications/broadcast":{"post":{"tags":["v1","admin","admin-notifications"],"summary":"Broadcast Notification","description":"Send a notification to all active users.","operationId":"broadcast_notification_api_v1_admin_notifications_broadcast_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/notifications/send":{"post":{"tags":["v1","admin","admin-notifications"],"summary":"Send Notification","description":"Send a notification to specific users.","operationId":"send_notification_api_v1_admin_notifications_send_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/notifications/history":{"get":{"tags":["v1","admin","admin-notifications"],"summary":"List Notification History","operationId":"list_notification_history_api_v1_admin_notifications_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminBroadcastListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/seo/stats":{"get":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"Get Seo Stats","description":"Return aggregated SEO health metrics including per-language coverage.","operationId":"get_seo_stats_api_v1_admin_seo_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SEOStats"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/seo/places":{"get":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"List Seo Places","description":"List all places with SEO coverage information.","operationId":"list_seo_places_api_v1_admin_seo_places_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}},{"name":"religion","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Religion"}},{"name":"missing_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Missing Only"}},{"name":"manually_edited","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Manually Edited"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SEOListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/seo/places/{place_code}":{"get":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"Get Seo Detail","description":"Return full SEO metadata for a single place.","operationId":"get_seo_detail_api_v1_admin_seo_places__place_code__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SEODetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"Patch Seo","description":"Update SEO content for a place. Sets is_manually_edited=True.","operationId":"patch_seo_api_v1_admin_seo_places__place_code__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchSEOBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SEODetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/seo/places/{place_code}/generate":{"post":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"Regenerate Single","description":"Regenerate SEO content for a single place.\n\nPass `force=true` to overwrite manually-edited content.\nPass `langs=en,ar,hi` to specify which languages to generate.","operationId":"regenerate_single_api_v1_admin_seo_places__place_code__generate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}},{"name":"force","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force"}},{"name":"langs","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Langs"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SEODetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/seo/generate":{"post":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"Bulk Generate Seo","description":"Bulk-generate SEO content for all places missing it.\n\n- force=true overwrites manually-edited records\n- limit=N processes at most N places\n- langs=[\"en\",\"ar\",\"hi\",\"te\",\"ml\"] specifies target languages","operationId":"bulk_generate_seo_api_v1_admin_seo_generate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkGenerateBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/seo/regen-slugs":{"post":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"Regen All Slugs","description":"Regenerate clean URL slugs for every place that has a PlaceSEO row.\n\nOnly the ``slug`` field is touched — all other SEO content is left intact.\nUse this once after a slugify fix to backfill clean URLs for existing records.","operationId":"regen_all_slugs_api_v1_admin_seo_regen_slugs_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegenSlugsResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/seo/regen-alt-texts":{"post":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"Regen All Alt Texts","description":"Backfill English alt text for every place image that has none.\n\nOnly images with ``alt_text IS NULL`` are touched.  Use this once after the\nimage-alt-text generation was added to backfill existing records.","operationId":"regen_all_alt_texts_api_v1_admin_seo_regen_alt_texts_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegenAltTextsResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/seo/templates":{"get":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"List Templates","description":"List all SEO content templates.","operationId":"list_templates_api_v1_admin_seo_templates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SEOTemplateItem"},"type":"array","title":"Response List Templates Api V1 Admin Seo Templates Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/seo/templates/{template_code}/{lang}":{"get":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"Get Template","description":"Get a single template by code and language.","operationId":"get_template_api_v1_admin_seo_templates__template_code___lang__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_code","in":"path","required":true,"schema":{"type":"string","title":"Template Code"}},{"name":"lang","in":"path","required":true,"schema":{"type":"string","title":"Lang"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SEOTemplateItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"Patch Template","description":"Edit a template. Auto-bumps version on any text change.","operationId":"patch_template_api_v1_admin_seo_templates__template_code___lang__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_code","in":"path","required":true,"schema":{"type":"string","title":"Template Code"}},{"name":"lang","in":"path","required":true,"schema":{"type":"string","title":"Lang"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchTemplateBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SEOTemplateItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/seo/labels":{"get":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"List Labels","description":"List all SEO labels.","operationId":"list_labels_api_v1_admin_seo_labels_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SEOLabelItem"},"type":"array","title":"Response List Labels Api V1 Admin Seo Labels Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/seo/labels/{label_type}/{label_key}/{lang}":{"patch":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"Patch Label","description":"Edit a label's text.","operationId":"patch_label_api_v1_admin_seo_labels__label_type___label_key___lang__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"label_type","in":"path","required":true,"schema":{"type":"string","title":"Label Type"}},{"name":"label_key","in":"path","required":true,"schema":{"type":"string","title":"Label Key"}},{"name":"lang","in":"path","required":true,"schema":{"type":"string","title":"Lang"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchLabelBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SEOLabelItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/seo/stale":{"get":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"List Stale Places","description":"List places where SEO content was generated with an older template version.","operationId":"list_stale_places_api_v1_admin_seo_stale_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/StaleItem"},"title":"Response List Stale Places Api V1 Admin Seo Stale Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/seo/ai-citations":{"get":{"tags":["v1","admin","admin-seo","admin-seo"],"summary":"Get Ai Citations","description":"Return AI-assistant crawler visit statistics for share pages.","operationId":"get_ai_citations_api_v1_admin_seo_ai_citations_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Days"}},{"name":"bot_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bot Name"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AICitationsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/ads/config":{"get":{"tags":["v1","admin","admin-ads","admin-ads"],"summary":"List Ad Configs","description":"List web ad config.","operationId":"list_ad_configs_api_v1_admin_ads_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAdConfigListResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/ads/config/{config_id}":{"patch":{"tags":["v1","admin","admin-ads","admin-ads"],"summary":"Patch Ad Config","description":"Update ad config for a platform.","operationId":"patch_ad_config_api_v1_admin_ads_config__config_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"integer","title":"Config Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchAdConfigBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAdConfigItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/ads/consent-stats":{"get":{"tags":["v1","admin","admin-ads","admin-ads"],"summary":"Get Consent Stats","description":"Aggregate consent grant/deny rates by type.","operationId":"get_consent_stats_api_v1_admin_ads_consent_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsentStatsResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/health/gcs":{"get":{"tags":["v1","admin","admin-health"],"summary":"Test GCS connectivity and configuration","description":"Diagnose GCS image storage configuration.\n\nChecks (in order):\n1. IMAGE_STORAGE env var value\n2. GCS_BUCKET_NAME env var value\n3. google-cloud-storage library import\n4. GCS client + bucket initialisation (uses ADC / Workload Identity on Cloud Run)\n5. A real test write → read → delete of a small object in the bucket\n\nReturns a structured report so you can identify exactly where the chain breaks.","operationId":"gcs_health_api_v1_admin_health_gcs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/analytics/overview":{"get":{"tags":["v1","admin","admin-analytics"],"summary":"Get Analytics Overview","description":"Return high-level analytics statistics.","operationId":"get_analytics_overview_api_v1_admin_analytics_overview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsOverview"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/analytics/top-places":{"get":{"tags":["v1","admin","admin-analytics"],"summary":"Get Analytics Top Places","description":"Return top places by analytics event frequency.","operationId":"get_analytics_top_places_api_v1_admin_analytics_top_places_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"period","in":"query","required":false,"schema":{"type":"string","pattern":"^(24h|7d|30d|90d)$","default":"7d","title":"Period"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AnalyticsTopPlace"},"title":"Response Get Analytics Top Places Api V1 Admin Analytics Top Places Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/analytics/trends":{"get":{"tags":["v1","admin","admin-analytics"],"summary":"Get Analytics Trends","description":"Return event count trends grouped by time interval.","operationId":"get_analytics_trends_api_v1_admin_analytics_trends_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"interval","in":"query","required":false,"schema":{"type":"string","pattern":"^(day|week|month)$","default":"day","title":"Interval"}},{"name":"event_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Type"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","pattern":"^(7d|30d|90d|365d)$","default":"30d","title":"Period"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AnalyticsTrendPoint"},"title":"Response Get Analytics Trends Api V1 Admin Analytics Trends Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/analytics/events":{"get":{"tags":["v1","admin","admin-analytics"],"summary":"Get Analytics Events","description":"Return paginated list of raw analytics events with optional filters.","operationId":"get_analytics_events_api_v1_admin_analytics_events_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}},{"name":"event_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Type"}},{"name":"platform","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform"}},{"name":"user_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Code"}},{"name":"session_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id"}},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Date To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsEventListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/sync-places/direct":{"post":{"tags":["v1","admin","admin-sync-places"],"summary":"Start Direct Sync Places","description":"Start direct DB catalog sync for a scraper run.\n\nThis endpoint is intentionally only a control plane call. The large place\npayload never flows through the HTTP request; the background job reads the\nscraper DB directly using SCRAPER_DATABASE_URL.","operationId":"start_direct_sync_places_api_v1_admin_sync_places_direct_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DirectSyncPlacesRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/blog/posts":{"get":{"tags":["v1","admin","admin-blog"],"summary":"List Blog Posts","description":"Return paginated blog posts (all statuses, including drafts).","operationId":"list_blog_posts_api_v1_admin_blog_posts_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":50,"title":"Page Size"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},{"name":"is_published","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Published"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Blog Posts Api V1 Admin Blog Posts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["v1","admin","admin-blog"],"summary":"Create Blog Post","operationId":"create_blog_post_api_v1_admin_blog_posts_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBlogPostBody"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Blog Post Api V1 Admin Blog Posts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/blog/posts/{post_code}":{"get":{"tags":["v1","admin","admin-blog"],"summary":"Get Blog Post","operationId":"get_blog_post_api_v1_admin_blog_posts__post_code__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"post_code","in":"path","required":true,"schema":{"type":"string","title":"Post Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Blog Post Api V1 Admin Blog Posts  Post Code  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["v1","admin","admin-blog"],"summary":"Update Blog Post","operationId":"update_blog_post_api_v1_admin_blog_posts__post_code__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"post_code","in":"path","required":true,"schema":{"type":"string","title":"Post Code"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchBlogPostBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Blog Post Api V1 Admin Blog Posts  Post Code  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","admin","admin-blog"],"summary":"Delete Blog Post","operationId":"delete_blog_post_api_v1_admin_blog_posts__post_code__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"post_code","in":"path","required":true,"schema":{"type":"string","title":"Post Code"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/blog/link-preview":{"post":{"tags":["v1","admin","admin-blog"],"summary":"Fetch Link Preview","description":"Fetch Open Graph / basic HTML metadata for a given URL.","operationId":"fetch_link_preview_api_v1_admin_blog_link_preview_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkPreviewBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Fetch Link Preview Api V1 Admin Blog Link Preview Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/admin/city-aliases":{"get":{"tags":["v1","admin","Admin - City Aliases"],"summary":"List Aliases","operationId":"list_aliases_api_v1_admin_city_aliases_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["v1","admin","Admin - City Aliases"],"summary":"Create Alias","operationId":"create_alias_api_v1_admin_city_aliases_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAliasRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/city-aliases/{alias_id}":{"delete":{"tags":["v1","admin","Admin - City Aliases"],"summary":"Delete Alias","operationId":"delete_alias_api_v1_admin_city_aliases__alias_id__delete","parameters":[{"name":"alias_id","in":"path","required":true,"schema":{"type":"integer","title":"Alias Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/share/places/{place_code}":{"get":{"tags":["share"],"summary":"Share Place","description":"Return a pre-rendered HTML page with full SEO metadata for a place.\n\n- Crawlers: receive a rich HTML page with visible content, JSON-LD,\n  canonical URL, OG tags, hreflang, and FAQs.\n- Human browsers: receive OG tags + JS redirect to the SPA.","operationId":"share_place_share_places__place_code__get","parameters":[{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/share/about":{"get":{"tags":["share"],"summary":"Share About","description":"Pre-rendered /about page for AI assistants and search crawlers.\n\nDescribes SoulStep's mission, features, and supported religions.\nCitable by AI assistants as context about the platform.","operationId":"share_about_share_about_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/share/how-it-works":{"get":{"tags":["share"],"summary":"Share How It Works","description":"Pre-rendered /how-it-works page for AI assistants and search crawlers.\n\nExplains the key features and user workflows in SoulStep.","operationId":"share_how_it_works_share_how_it_works_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/share/coverage":{"get":{"tags":["share"],"summary":"Share Coverage","description":"Pre-rendered /coverage page showing the scope of the SoulStep catalogue.\n\nIncludes a Dataset JSON-LD schema for AI citation about platform coverage.\nDynamically populated from the live database.","operationId":"share_coverage_share_coverage_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/share/religion/{religion}":{"get":{"tags":["share"],"summary":"Share Religion Category","description":"Pre-rendered landing page for a religion category.","operationId":"share_religion_category_share_religion__religion__get","parameters":[{"name":"religion","in":"path","required":true,"schema":{"type":"string","title":"Religion"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/share/{lang}/places/{place_code}":{"get":{"tags":["share"],"summary":"Share Place Lang","description":"Language-specific pre-rendered place page (for hreflang).","operationId":"share_place_lang_share__lang__places__place_code__get","parameters":[{"name":"lang","in":"path","required":true,"schema":{"type":"string","title":"Lang"}},{"name":"place_code","in":"path","required":true,"schema":{"type":"string","title":"Place Code"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/share/city/{city_slug}":{"get":{"tags":["share"],"summary":"Share City","description":"Pre-rendered city landing page with all sacred sites in that city.","operationId":"share_city_share_city__city_slug__get","parameters":[{"name":"city_slug","in":"path","required":true,"schema":{"type":"string","title":"City Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/share/city/{city_slug}/{religion}":{"get":{"tags":["share"],"summary":"Share City Religion","description":"Pre-rendered city+religion landing page (e.g. Mosques in Dubai).","operationId":"share_city_religion_share_city__city_slug___religion__get","parameters":[{"name":"city_slug","in":"path","required":true,"schema":{"type":"string","title":"City Slug"}},{"name":"religion","in":"path","required":true,"schema":{"type":"string","title":"Religion"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AICitationBotStats":{"properties":{"bot_name":{"type":"string","title":"Bot Name"},"visit_count":{"type":"integer","title":"Visit Count"}},"type":"object","required":["bot_name","visit_count"],"title":"AICitationBotStats"},"AICitationTopPlace":{"properties":{"place_code":{"type":"string","title":"Place Code"},"visit_count":{"type":"integer","title":"Visit Count"}},"type":"object","required":["place_code","visit_count"],"title":"AICitationTopPlace"},"AICitationsResponse":{"properties":{"total_visits":{"type":"integer","title":"Total Visits"},"period_days":{"type":"integer","title":"Period Days"},"by_bot":{"items":{"$ref":"#/components/schemas/AICitationBotStats"},"type":"array","title":"By Bot"},"top_places":{"items":{"$ref":"#/components/schemas/AICitationTopPlace"},"type":"array","title":"Top Places"},"recent_logs":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Recent Logs"}},"type":"object","required":["total_visits","period_days","by_bot","top_places","recent_logs"],"title":"AICitationsResponse"},"AdConfigResponse":{"properties":{"platform":{"type":"string","title":"Platform"},"ads_enabled":{"type":"boolean","title":"Ads Enabled"},"ad_server":{"type":"string","enum":["adsense","adsterra"],"title":"Ad Server"},"adsense_publisher_id":{"type":"string","title":"Adsense Publisher Id"},"ad_slots":{"additionalProperties":true,"type":"object","title":"Ad Slots"}},"type":"object","required":["platform","ads_enabled","ad_server","adsense_publisher_id","ad_slots"],"title":"AdConfigResponse"},"AdminAdConfigItem":{"properties":{"id":{"type":"integer","title":"Id"},"platform":{"type":"string","title":"Platform"},"ads_enabled":{"type":"boolean","title":"Ads Enabled"},"ad_server":{"type":"string","enum":["adsense","adsterra"],"title":"Ad Server"},"adsense_publisher_id":{"type":"string","title":"Adsense Publisher Id"},"ad_slots":{"additionalProperties":true,"type":"object","title":"Ad Slots"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","platform","ads_enabled","ad_server","adsense_publisher_id","ad_slots","updated_at"],"title":"AdminAdConfigItem"},"AdminAdConfigListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminAdConfigItem"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"AdminAdConfigListResponse"},"AdminBroadcastItem":{"properties":{"broadcast_code":{"type":"string","title":"Broadcast Code"},"admin_user_code":{"type":"string","title":"Admin User Code"},"admin_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Admin Display Name"},"type":{"type":"string","title":"Type"},"payload":{"additionalProperties":true,"type":"object","title":"Payload"},"recipient_type":{"type":"string","title":"Recipient Type"},"recipient_count":{"type":"integer","title":"Recipient Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["broadcast_code","admin_user_code","admin_display_name","type","payload","recipient_type","recipient_count","created_at"],"title":"AdminBroadcastItem"},"AdminBroadcastListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminBroadcastItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"AdminBroadcastListResponse"},"AdminCheckInItem":{"properties":{"check_in_code":{"type":"string","title":"Check In Code"},"place_code":{"type":"string","title":"Place Code"},"place_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Name"},"group_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Group Code"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"checked_in_at":{"type":"string","format":"date-time","title":"Checked In At"}},"type":"object","required":["check_in_code","place_code","place_name","group_code","note","checked_in_at"],"title":"AdminCheckInItem"},"AdminCheckInListItem":{"properties":{"check_in_code":{"type":"string","title":"Check In Code"},"user_code":{"type":"string","title":"User Code"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name"},"place_code":{"type":"string","title":"Place Code"},"place_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Name"},"group_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Group Code"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"checked_in_at":{"type":"string","format":"date-time","title":"Checked In At"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Deleted At"}},"type":"object","required":["check_in_code","user_code","user_display_name","place_code","place_name","group_code","note","checked_in_at"],"title":"AdminCheckInListItem"},"AdminContentTranslation":{"properties":{"id":{"type":"integer","title":"Id"},"entity_type":{"type":"string","title":"Entity Type"},"entity_code":{"type":"string","title":"Entity Code"},"field":{"type":"string","title":"Field"},"lang":{"type":"string","title":"Lang"},"translated_text":{"type":"string","title":"Translated Text"},"source":{"type":"string","title":"Source"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"place_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Name"}},"type":"object","required":["id","entity_type","entity_code","field","lang","translated_text","source","created_at","updated_at"],"title":"AdminContentTranslation"},"AdminGroupDetail":{"properties":{"group_code":{"type":"string","title":"Group Code"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"is_private":{"type":"boolean","title":"Is Private"},"member_count":{"type":"integer","title":"Member Count"},"place_count":{"type":"integer","title":"Place Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"created_by_user_code":{"type":"string","title":"Created By User Code"},"invite_code":{"type":"string","title":"Invite Code"},"path_place_codes":{"items":{"type":"string"},"type":"array","title":"Path Place Codes"},"cover_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Image Url"},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date"}},"type":"object","required":["group_code","name","description","is_private","member_count","place_count","created_at","updated_at","created_by_user_code","invite_code","path_place_codes","cover_image_url","start_date","end_date"],"title":"AdminGroupDetail"},"AdminGroupListItem":{"properties":{"group_code":{"type":"string","title":"Group Code"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"is_private":{"type":"boolean","title":"Is Private"},"member_count":{"type":"integer","title":"Member Count"},"place_count":{"type":"integer","title":"Place Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["group_code","name","description","is_private","member_count","place_count","created_at","updated_at"],"title":"AdminGroupListItem"},"AdminGroupListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminGroupListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"AdminGroupListResponse"},"AdminGroupMemberItem":{"properties":{"user_code":{"type":"string","title":"User Code"},"display_name":{"type":"string","title":"Display Name"},"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role"},"joined_at":{"type":"string","format":"date-time","title":"Joined At"}},"type":"object","required":["user_code","display_name","email","role","joined_at"],"title":"AdminGroupMemberItem"},"AdminGroupMemberListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminGroupMemberItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["items","total"],"title":"AdminGroupMemberListResponse"},"AdminPlaceDetail":{"properties":{"place_code":{"type":"string","title":"Place Code"},"name":{"type":"string","title":"Name"},"religion":{"type":"string","title":"Religion"},"place_type":{"type":"string","title":"Place Type"},"lat":{"type":"number","title":"Lat"},"lng":{"type":"number","title":"Lng"},"address":{"type":"string","title":"Address"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"review_count":{"type":"integer","title":"Review Count"},"check_in_count":{"type":"integer","title":"Check In Count"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"website_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Url"},"opening_hours":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Opening Hours"},"utc_offset_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Utc Offset Minutes"}},"type":"object","required":["place_code","name","religion","place_type","lat","lng","address","city","state","country","source","created_at","review_count","check_in_count","description","website_url","opening_hours","utc_offset_minutes"],"title":"AdminPlaceDetail"},"AdminPlaceImageItem":{"properties":{"id":{"type":"integer","title":"Id"},"image_type":{"type":"string","title":"Image Type"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"display_order":{"type":"integer","title":"Display Order"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","image_type","url","display_order","created_at"],"title":"AdminPlaceImageItem"},"AdminPlaceListItem":{"properties":{"place_code":{"type":"string","title":"Place Code"},"name":{"type":"string","title":"Name"},"religion":{"type":"string","title":"Religion"},"place_type":{"type":"string","title":"Place Type"},"lat":{"type":"number","title":"Lat"},"lng":{"type":"number","title":"Lng"},"address":{"type":"string","title":"Address"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"review_count":{"type":"integer","title":"Review Count"},"check_in_count":{"type":"integer","title":"Check In Count"}},"type":"object","required":["place_code","name","religion","place_type","lat","lng","address","city","state","country","source","created_at","review_count","check_in_count"],"title":"AdminPlaceListItem"},"AdminPlaceListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminPlaceListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"AdminPlaceListResponse"},"AdminReviewDetail":{"properties":{"review_code":{"type":"string","title":"Review Code"},"place_code":{"type":"string","title":"Place Code"},"place_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Name"},"user_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Code"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name"},"rating":{"type":"integer","title":"Rating"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"is_flagged":{"type":"boolean","title":"Is Flagged"},"source":{"type":"string","title":"Source"},"review_time":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Review Time"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Deleted At"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"},"is_anonymous":{"type":"boolean","title":"Is Anonymous"},"author_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Author Name"}},"type":"object","required":["review_code","place_code","place_name","user_code","user_display_name","rating","title","is_flagged","source","review_time","created_at","body","is_anonymous","author_name"],"title":"AdminReviewDetail"},"AdminReviewItem":{"properties":{"review_code":{"type":"string","title":"Review Code"},"place_code":{"type":"string","title":"Place Code"},"place_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Name"},"rating":{"type":"integer","title":"Rating"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"},"is_flagged":{"type":"boolean","title":"Is Flagged"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["review_code","place_code","place_name","rating","title","body","is_flagged","created_at"],"title":"AdminReviewItem"},"AdminReviewListItem":{"properties":{"review_code":{"type":"string","title":"Review Code"},"place_code":{"type":"string","title":"Place Code"},"place_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Name"},"user_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Code"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name"},"rating":{"type":"integer","title":"Rating"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"is_flagged":{"type":"boolean","title":"Is Flagged"},"source":{"type":"string","title":"Source"},"review_time":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Review Time"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Deleted At"}},"type":"object","required":["review_code","place_code","place_name","user_code","user_display_name","rating","title","is_flagged","source","review_time","created_at"],"title":"AdminReviewListItem"},"AdminUserDetail":{"properties":{"user_code":{"type":"string","title":"User Code"},"email":{"type":"string","title":"Email"},"display_name":{"type":"string","title":"Display Name"},"is_active":{"type":"boolean","title":"Is Active"},"is_admin":{"type":"boolean","title":"Is Admin"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"check_in_count":{"type":"integer","title":"Check In Count"},"review_count":{"type":"integer","title":"Review Count"}},"type":"object","required":["user_code","email","display_name","is_active","is_admin","created_at","updated_at","check_in_count","review_count"],"title":"AdminUserDetail"},"AdminUserListItem":{"properties":{"user_code":{"type":"string","title":"User Code"},"email":{"type":"string","title":"Email"},"display_name":{"type":"string","title":"Display Name"},"is_active":{"type":"boolean","title":"Is Active"},"is_admin":{"type":"boolean","title":"Is Admin"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["user_code","email","display_name","is_active","is_admin","created_at","updated_at"],"title":"AdminUserListItem"},"AdminUserListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminUserListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"AdminUserListResponse"},"AnalyticsEventListItem":{"properties":{"event_code":{"type":"string","title":"Event Code"},"event_type":{"type":"string","title":"Event Type"},"user_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Code"},"visitor_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Visitor Code"},"session_id":{"type":"string","title":"Session Id"},"properties":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Properties"},"platform":{"type":"string","title":"Platform"},"device_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Type"},"app_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"App Version"},"client_timestamp":{"type":"string","format":"date-time","title":"Client Timestamp"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["event_code","event_type","user_code","visitor_code","session_id","properties","platform","device_type","app_version","client_timestamp","created_at"],"title":"AnalyticsEventListItem"},"AnalyticsEventListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AnalyticsEventListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"AnalyticsEventListResponse"},"AnalyticsIngestionBody":{"properties":{"events":{"items":{"$ref":"#/components/schemas/EventItem"},"type":"array","title":"Events"},"platform":{"type":"string","title":"Platform"},"device_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Type"},"app_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"App Version"},"visitor_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Visitor Code"}},"type":"object","required":["events","platform"],"title":"AnalyticsIngestionBody"},"AnalyticsIngestionResponse":{"properties":{"accepted":{"type":"integer","title":"Accepted"}},"type":"object","required":["accepted"],"title":"AnalyticsIngestionResponse"},"AnalyticsOverview":{"properties":{"total_events":{"type":"integer","title":"Total Events"},"total_events_24h":{"type":"integer","title":"Total Events 24H"},"total_events_7d":{"type":"integer","title":"Total Events 7D"},"unique_users":{"type":"integer","title":"Unique Users"},"unique_visitors":{"type":"integer","title":"Unique Visitors"},"unique_sessions":{"type":"integer","title":"Unique Sessions"},"top_event_types":{"items":{"$ref":"#/components/schemas/EventTypeCount"},"type":"array","title":"Top Event Types"},"platform_breakdown":{"items":{"$ref":"#/components/schemas/PlatformCount"},"type":"array","title":"Platform Breakdown"}},"type":"object","required":["total_events","total_events_24h","total_events_7d","unique_users","unique_visitors","unique_sessions","top_event_types","platform_breakdown"],"title":"AnalyticsOverview"},"AnalyticsTopPlace":{"properties":{"place_code":{"type":"string","title":"Place Code"},"place_name":{"type":"string","title":"Place Name"},"religion":{"type":"string","title":"Religion"},"view_count":{"type":"integer","title":"View Count"},"interaction_count":{"type":"integer","title":"Interaction Count"}},"type":"object","required":["place_code","place_name","religion","view_count","interaction_count"],"title":"AnalyticsTopPlace"},"AnalyticsTrendPoint":{"properties":{"period":{"type":"string","title":"Period"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["period","count"],"title":"AnalyticsTrendPoint"},"ArticleSection":{"properties":{"heading":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Heading"},"paragraphs":{"items":{"type":"string"},"type":"array","title":"Paragraphs","default":[]}},"type":"object","title":"ArticleSection"},"AttributeDefinitionItem":{"properties":{"attribute_code":{"type":"string","title":"Attribute Code"},"name":{"type":"string","title":"Name"},"data_type":{"type":"string","title":"Data Type"},"icon":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Icon"},"label_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label Key"},"is_filterable":{"type":"boolean","title":"Is Filterable"},"is_specification":{"type":"boolean","title":"Is Specification"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"religion":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Religion"},"display_order":{"type":"integer","title":"Display Order"},"usage_count":{"type":"integer","title":"Usage Count"}},"type":"object","required":["attribute_code","name","data_type","icon","label_key","is_filterable","is_specification","category","religion","display_order","usage_count"],"title":"AttributeDefinitionItem"},"AuditLogItem":{"properties":{"log_code":{"type":"string","title":"Log Code"},"admin_user_code":{"type":"string","title":"Admin User Code"},"admin_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Admin Display Name"},"action":{"type":"string","title":"Action"},"entity_type":{"type":"string","title":"Entity Type"},"entity_code":{"type":"string","title":"Entity Code"},"changes":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Changes"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["log_code","admin_user_code","admin_display_name","action","entity_type","entity_code","changes","created_at"],"title":"AuditLogItem"},"AuditLogListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AuditLogItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"AuditLogListResponse"},"AuthResponse":{"properties":{"user":{"$ref":"#/components/schemas/UserResponse"},"token":{"type":"string","title":"Token","description":"Short-lived JWT access token (Bearer)"},"refresh_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refresh Token","description":"Deprecated — refresh token is set as an HTTP-only cookie"}},"type":"object","required":["user","token"],"title":"AuthResponse","example":{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...","user":{"created_at":"2024-01-15T10:30:00Z","display_name":"Ahmed","email":"user@example.com","religions":["islam"],"updated_at":"2024-01-15T10:30:00Z","user_code":"usr_abc123de"}}},"BatchDeleteBody":{"properties":{"place_codes":{"items":{"type":"string"},"type":"array","title":"Place Codes"}},"type":"object","required":["place_codes"],"title":"BatchDeleteBody"},"Body_import_translated_txt_api_v1_admin_content_translations_import_txt_post":{"properties":{"lang":{"type":"string","title":"Lang"},"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["lang","file"],"title":"Body_import_translated_txt_api_v1_admin_content_translations_import_txt_post"},"Body_upload_group_cover_api_v1_groups_upload_cover_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_group_cover_api_v1_groups_upload_cover_post"},"Body_upload_review_photo_api_v1_reviews_upload_photo_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_review_photo_api_v1_reviews_upload_photo_post"},"BroadcastBody":{"properties":{"type":{"type":"string","title":"Type"},"payload":{"additionalProperties":true,"type":"object","title":"Payload","default":{}}},"type":"object","required":["type"],"title":"BroadcastBody"},"BroadcastResult":{"properties":{"broadcast_code":{"type":"string","title":"Broadcast Code"},"recipient_count":{"type":"integer","title":"Recipient Count"}},"type":"object","required":["broadcast_code","recipient_count"],"title":"BroadcastResult"},"BulkAttributeEntry":{"properties":{"attribute_code":{"type":"string","title":"Attribute Code"},"value_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value Text"},"value_json":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Value Json"}},"type":"object","required":["attribute_code"],"title":"BulkAttributeEntry"},"BulkCheckInCodesBody":{"properties":{"check_in_codes":{"items":{"type":"string"},"type":"array","title":"Check In Codes"}},"type":"object","required":["check_in_codes"],"title":"BulkCheckInCodesBody"},"BulkGenerateBody":{"properties":{"force":{"type":"boolean","title":"Force","default":false},"limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Limit"},"langs":{"items":{"type":"string"},"type":"array","title":"Langs","default":["en"]}},"type":"object","title":"BulkGenerateBody"},"BulkGroupCodesBody":{"properties":{"group_codes":{"items":{"type":"string"},"type":"array","title":"Group Codes"}},"type":"object","required":["group_codes"],"title":"BulkGroupCodesBody"},"BulkPlaceCodesBody":{"properties":{"place_codes":{"items":{"type":"string"},"type":"array","title":"Place Codes"}},"type":"object","required":["place_codes"],"title":"BulkPlaceCodesBody"},"BulkResult":{"properties":{"affected":{"type":"integer","title":"Affected"}},"type":"object","required":["affected"],"title":"BulkResult"},"BulkReviewCodesBody":{"properties":{"review_codes":{"items":{"type":"string"},"type":"array","title":"Review Codes"}},"type":"object","required":["review_codes"],"title":"BulkReviewCodesBody"},"BulkTranslationJobOut":{"properties":{"job_code":{"type":"string","title":"Job Code"},"status":{"type":"string","title":"Status"},"job_type":{"type":"string","title":"Job Type"},"target_langs":{"items":{"type":"string"},"type":"array","title":"Target Langs"},"entity_types":{"items":{"type":"string"},"type":"array","title":"Entity Types"},"source_lang":{"type":"string","title":"Source Lang"},"total_items":{"type":"integer","title":"Total Items"},"completed_items":{"type":"integer","title":"Completed Items"},"failed_items":{"type":"integer","title":"Failed Items"},"skipped_items":{"type":"integer","title":"Skipped Items"},"progress_pct":{"type":"number","title":"Progress Pct"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Started At"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["job_code","status","job_type","target_langs","entity_types","source_lang","total_items","completed_items","failed_items","skipped_items","progress_pct","error_message","started_at","completed_at","created_at"],"title":"BulkTranslationJobOut"},"BulkUpdateAttributesBody":{"properties":{"attributes":{"items":{"$ref":"#/components/schemas/BulkAttributeEntry"},"type":"array","title":"Attributes"}},"type":"object","required":["attributes"],"title":"BulkUpdateAttributesBody"},"BulkUpsertItem":{"properties":{"entity_type":{"type":"string","title":"Entity Type"},"entity_code":{"type":"string","title":"Entity Code"},"field":{"type":"string","title":"Field"},"lang":{"type":"string","title":"Lang"},"translated_text":{"type":"string","title":"Translated Text"},"source":{"type":"string","title":"Source","default":"claude_ai"}},"type":"object","required":["entity_type","entity_code","field","lang","translated_text"],"title":"BulkUpsertItem"},"BulkUpsertResult":{"properties":{"created":{"type":"integer","title":"Created"},"updated":{"type":"integer","title":"Updated"},"errors":{"items":{"type":"string"},"type":"array","title":"Errors"}},"type":"object","required":["created","updated","errors"],"title":"BulkUpsertResult"},"BulkUserCodesBody":{"properties":{"user_codes":{"items":{"type":"string"},"type":"array","title":"User Codes"}},"type":"object","required":["user_codes"],"title":"BulkUserCodesBody"},"CheckInBody":{"properties":{"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"photo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Photo Url"},"group_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Group Code"}},"type":"object","title":"CheckInBody"},"ConsentBody":{"properties":{"consent_type":{"type":"string","title":"Consent Type"},"granted":{"type":"boolean","title":"Granted"},"visitor_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Visitor Code"}},"type":"object","required":["consent_type","granted"],"title":"ConsentBody"},"ConsentStatsItem":{"properties":{"consent_type":{"type":"string","title":"Consent Type"},"total":{"type":"integer","title":"Total"},"granted":{"type":"integer","title":"Granted"},"denied":{"type":"integer","title":"Denied"},"grant_rate":{"type":"number","title":"Grant Rate"}},"type":"object","required":["consent_type","total","granted","denied","grant_rate"],"title":"ConsentStatsItem"},"ConsentStatsResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ConsentStatsItem"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"ConsentStatsResponse"},"ConsentStatusResponse":{"properties":{"ads":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ads"},"analytics":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Analytics"}},"type":"object","title":"ConsentStatusResponse"},"ContentTranslationListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminContentTranslation"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"ContentTranslationListResponse"},"ContentTranslationStats":{"properties":{"langs":{"items":{"$ref":"#/components/schemas/_LangStat"},"type":"array","title":"Langs"}},"type":"object","required":["langs"],"title":"ContentTranslationStats"},"CreateAliasRequest":{"properties":{"alias_name":{"type":"string","title":"Alias Name"},"canonical_city_code":{"type":"string","title":"Canonical City Code"},"country_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Code"}},"type":"object","required":["alias_name","canonical_city_code"],"title":"CreateAliasRequest"},"CreateBlogPostBody":{"properties":{"slug":{"type":"string","title":"Slug"},"title":{"type":"string","title":"Title"},"description":{"type":"string","title":"Description"},"category":{"type":"string","title":"Category"},"reading_time":{"type":"integer","title":"Reading Time","default":5},"cover_gradient":{"type":"string","title":"Cover Gradient","default":"from-emerald-500 to-teal-600"},"cover_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Image Url"},"author_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Author Name"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags","default":[]},"content":{"items":{"$ref":"#/components/schemas/ArticleSection"},"type":"array","title":"Content","default":[]},"faq_json":{"anyOf":[{"items":{"$ref":"#/components/schemas/FAQItem"},"type":"array"},{"type":"null"}],"title":"Faq Json"},"is_published":{"type":"boolean","title":"Is Published","default":true},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"}},"type":"object","required":["slug","title","description","category"],"title":"CreateBlogPostBody"},"CreateContentTranslationBody":{"properties":{"entity_type":{"type":"string","title":"Entity Type"},"entity_code":{"type":"string","title":"Entity Code"},"field":{"type":"string","title":"Field"},"lang":{"type":"string","title":"Lang"},"translated_text":{"type":"string","title":"Translated Text"},"source":{"type":"string","title":"Source","default":"manual"}},"type":"object","required":["entity_type","entity_code","field","lang","translated_text"],"title":"CreateContentTranslationBody"},"CreatePlaceBody":{"properties":{"name":{"type":"string","title":"Name"},"religion":{"type":"string","title":"Religion"},"place_type":{"type":"string","title":"Place Type"},"lat":{"type":"number","title":"Lat"},"lng":{"type":"number","title":"Lng"},"address":{"type":"string","title":"Address"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"website_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Url"},"opening_hours":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Opening Hours"},"utc_offset_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Utc Offset Minutes"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source","default":"manual"}},"type":"object","required":["name","religion","place_type","lat","lng","address"],"title":"CreatePlaceBody"},"CreateTranslationBody":{"properties":{"key":{"type":"string","title":"Key"},"values":{"additionalProperties":{"type":"string"},"type":"object","title":"Values"}},"type":"object","required":["key","values"],"title":"CreateTranslationBody"},"DataQualityItem":{"properties":{"place_code":{"type":"string","title":"Place Code"},"name":{"type":"string","title":"Name"},"place_type":{"type":"string","title":"Place Type"},"religion":{"type":"string","title":"Religion"},"lat":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lat"},"lng":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lng"},"issue":{"type":"string","title":"Issue"}},"type":"object","required":["place_code","name","place_type","religion","lat","lng","issue"],"title":"DataQualityItem"},"DirectSyncPlacesRequest":{"properties":{"run_code":{"type":"string","title":"Run Code"},"failed_only":{"type":"boolean","title":"Failed Only","default":false},"dry_run":{"type":"boolean","title":"Dry Run","default":false}},"type":"object","required":["run_code"],"title":"DirectSyncPlacesRequest"},"EventItem":{"properties":{"event_type":{"type":"string","title":"Event Type"},"properties":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Properties"},"client_timestamp":{"type":"string","format":"date-time","title":"Client Timestamp"},"session_id":{"type":"string","title":"Session Id"}},"type":"object","required":["event_type","client_timestamp","session_id"],"title":"EventItem"},"EventTypeCount":{"properties":{"event_type":{"type":"string","title":"Event Type"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["event_type","count"],"title":"EventTypeCount"},"ExternalReviewInput":{"properties":{"author_name":{"type":"string","title":"Author Name"},"rating":{"type":"integer","title":"Rating"},"text":{"type":"string","title":"Text"},"time":{"type":"integer","title":"Time"},"language":{"type":"string","title":"Language","default":"en"},"photo_urls":{"items":{"type":"string"},"type":"array","title":"Photo Urls","default":[]}},"type":"object","required":["author_name","rating","text","time"],"title":"ExternalReviewInput","description":"Typed schema for external (e.g. Google) reviews imported during sync."},"FAQItem":{"properties":{"question":{"type":"string","title":"Question"},"answer":{"type":"string","title":"Answer"}},"type":"object","required":["question","answer"],"title":"FAQItem"},"ForgotPasswordBody":{"properties":{"email":{"type":"string","title":"Email"}},"type":"object","required":["email"],"title":"ForgotPasswordBody"},"GenerateResponse":{"properties":{"generated":{"type":"integer","title":"Generated"},"skipped":{"type":"integer","title":"Skipped"},"errors":{"type":"integer","title":"Errors"},"lang_generated":{"additionalProperties":{"type":"integer"},"type":"object","title":"Lang Generated"},"lang_errors":{"additionalProperties":{"type":"integer"},"type":"object","title":"Lang Errors"}},"type":"object","required":["generated","skipped","errors","lang_generated","lang_errors"],"title":"GenerateResponse"},"GroupCreateBody":{"properties":{"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"is_private":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Private","default":false},"path_place_codes":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Path Place Codes"},"cover_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Image Url"},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date"}},"type":"object","required":["name"],"title":"GroupCreateBody"},"GroupPlaceNoteBody":{"properties":{"text":{"type":"string","title":"Text"}},"type":"object","required":["text"],"title":"GroupPlaceNoteBody"},"GroupUpdateBody":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"is_private":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Private"},"path_place_codes":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Path Place Codes"},"cover_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Image Url"},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date"}},"type":"object","title":"GroupUpdateBody"},"GrowthDataPoint":{"properties":{"period":{"type":"string","title":"Period"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["period","count"],"title":"GrowthDataPoint"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"JobListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/BulkTranslationJobOut"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"JobListResponse"},"LinkPreviewBody":{"properties":{"url":{"type":"string","title":"Url"}},"type":"object","required":["url"],"title":"LinkPreviewBody"},"LoginBody":{"properties":{"email":{"type":"string","title":"Email","description":"Registered email address"},"password":{"type":"string","title":"Password","description":"Account password"},"visitor_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Visitor Code","description":"Anonymous visitor code to merge settings on login"}},"type":"object","required":["email","password"],"title":"LoginBody","example":{"email":"user@example.com","password":"SecurePass1"}},"OverviewStats":{"properties":{"total_users":{"type":"integer","title":"Total Users"},"total_places":{"type":"integer","title":"Total Places"},"total_reviews":{"type":"integer","title":"Total Reviews"},"total_check_ins":{"type":"integer","title":"Total Check Ins"},"total_groups":{"type":"integer","title":"Total Groups"},"active_users_30d":{"type":"integer","title":"Active Users 30D"}},"type":"object","required":["total_users","total_places","total_reviews","total_check_ins","total_groups","active_users_30d"],"title":"OverviewStats"},"PatchAdConfigBody":{"properties":{"ads_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ads Enabled"},"ad_server":{"anyOf":[{"type":"string","enum":["adsense","adsterra"]},{"type":"null"}],"title":"Ad Server"},"adsense_publisher_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Adsense Publisher Id"},"ad_slots":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Ad Slots"}},"type":"object","title":"PatchAdConfigBody"},"PatchBlogPostBody":{"properties":{"slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"reading_time":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Reading Time"},"cover_gradient":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Gradient"},"cover_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Image Url"},"author_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Author Name"},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags"},"content":{"anyOf":[{"items":{"$ref":"#/components/schemas/ArticleSection"},"type":"array"},{"type":"null"}],"title":"Content"},"faq_json":{"anyOf":[{"items":{"$ref":"#/components/schemas/FAQItem"},"type":"array"},{"type":"null"}],"title":"Faq Json"},"is_published":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Published"}},"type":"object","title":"PatchBlogPostBody"},"PatchGroupBody":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"is_private":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Private"}},"type":"object","title":"PatchGroupBody"},"PatchLabelBody":{"properties":{"label_text":{"type":"string","title":"Label Text"}},"type":"object","required":["label_text"],"title":"PatchLabelBody"},"PatchPlaceBody":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"religion":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Religion"},"place_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Type"},"lat":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lat"},"lng":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lng"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"website_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Url"},"opening_hours":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Opening Hours"},"utc_offset_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Utc Offset Minutes"}},"type":"object","title":"PatchPlaceBody"},"PatchReviewBody":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"},"is_flagged":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Flagged"}},"type":"object","title":"PatchReviewBody"},"PatchSEOBody":{"properties":{"slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"},"seo_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Seo Title"},"meta_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meta Description"},"rich_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rich Description"},"faq_json":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Faq Json"},"og_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Og Image Url"},"is_manually_edited":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Manually Edited"}},"type":"object","title":"PatchSEOBody"},"PatchTemplateBody":{"properties":{"template_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template Text"},"fallback_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fallback Text"},"static_phrases":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Static Phrases"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"}},"type":"object","title":"PatchTemplateBody"},"PatchUserBody":{"properties":{"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"is_admin":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Admin"}},"type":"object","title":"PatchUserBody"},"PlaceAttributeInput":{"properties":{"attribute_code":{"type":"string","title":"Attribute Code"},"value":{"anyOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"},{"items":{"type":"string"},"type":"array"}],"title":"Value"}},"type":"object","required":["attribute_code","value"],"title":"PlaceAttributeInput"},"PlaceAttributeItem":{"properties":{"id":{"type":"integer","title":"Id"},"attribute_code":{"type":"string","title":"Attribute Code"},"attribute_name":{"type":"string","title":"Attribute Name"},"data_type":{"type":"string","title":"Data Type"},"value_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value Text"},"value_json":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Value Json"}},"type":"object","required":["id","attribute_code","attribute_name","data_type","value_text","value_json"],"title":"PlaceAttributeItem"},"PlaceBatch":{"properties":{"places":{"items":{"$ref":"#/components/schemas/PlaceCreate"},"type":"array","maxItems":500,"title":"Places"}},"type":"object","required":["places"],"title":"PlaceBatch","description":"Wraps a list of places for the batch create/update endpoint.\n\nAt most 500 places per request. Duplicate place_codes are deduplicated\n(last entry wins) before processing."},"PlaceCreate":{"properties":{"place_code":{"type":"string","title":"Place Code"},"name":{"type":"string","title":"Name"},"religion":{"type":"string","enum":["islam","hinduism","christianity","all"],"title":"Religion"},"place_type":{"type":"string","title":"Place Type"},"lat":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lat"},"lng":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lng"},"address":{"type":"string","title":"Address"},"opening_hours":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Opening Hours"},"utc_offset_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Utc Offset Minutes"},"image_urls":{"items":{"type":"string"},"type":"array","title":"Image Urls","default":[]},"image_blobs":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Image Blobs"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"website_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website Url"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"attributes":{"anyOf":[{"items":{"$ref":"#/components/schemas/PlaceAttributeInput"},"type":"array"},{"type":"null"}],"title":"Attributes"},"external_reviews":{"anyOf":[{"items":{"$ref":"#/components/schemas/ExternalReviewInput"},"type":"array"},{"type":"null"}],"title":"External Reviews"},"translations":{"anyOf":[{"$ref":"#/components/schemas/PlaceTranslationInput"},{"type":"null"}]}},"type":"object","required":["place_code","name","religion","place_type","address"],"title":"PlaceCreate"},"PlaceTranslationInput":{"properties":{"name":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Description"},"address":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Address"}},"type":"object","title":"PlaceTranslationInput","description":"Per-field non-English translations provided at ingest time by the scraper."},"PlatformCount":{"properties":{"platform":{"type":"string","title":"Platform"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["platform","count"],"title":"PlatformCount"},"PopularPlace":{"properties":{"place_code":{"type":"string","title":"Place Code"},"name":{"type":"string","title":"Name"},"religion":{"type":"string","title":"Religion"},"check_in_count":{"type":"integer","title":"Check In Count"},"review_count":{"type":"integer","title":"Review Count"},"avg_rating":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Rating"}},"type":"object","required":["place_code","name","religion","check_in_count","review_count","avg_rating"],"title":"PopularPlace"},"RecentActivityItem":{"properties":{"type":{"type":"string","title":"Type"},"user_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Code"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name"},"place_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Code"},"place_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Name"},"group_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Group Code"},"group_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Group Name"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"}},"type":"object","required":["type","user_code","user_display_name","place_code","place_name","group_code","group_name","timestamp"],"title":"RecentActivityItem"},"RegenAltTextsResponse":{"properties":{"images_updated":{"type":"integer","title":"Images Updated"},"places_processed":{"type":"integer","title":"Places Processed"},"errors":{"type":"integer","title":"Errors"}},"type":"object","required":["images_updated","places_processed","errors"],"title":"RegenAltTextsResponse"},"RegenSlugsResponse":{"properties":{"updated":{"type":"integer","title":"Updated"},"unchanged":{"type":"integer","title":"Unchanged"},"errors":{"type":"integer","title":"Errors"}},"type":"object","required":["updated","unchanged","errors"],"title":"RegenSlugsResponse"},"RegisterBody":{"properties":{"email":{"type":"string","title":"Email","description":"Unique email address for the account"},"password":{"type":"string","title":"Password","description":"Must be at least 8 characters and contain at least one uppercase letter, one lowercase letter, and one digit."},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name","description":"Optional display name; defaults to the email prefix"},"visitor_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Visitor Code","description":"Anonymous visitor code to merge settings on account creation"}},"type":"object","required":["email","password"],"title":"RegisterBody","example":{"display_name":"Ahmed Al-Rashid","email":"user@example.com","password":"SecurePass1"}},"Religion":{"type":"string","enum":["islam","hinduism","christianity","all"],"title":"Religion"},"ReligionBreakdownItem":{"properties":{"religion":{"type":"string","title":"Religion"},"place_count":{"type":"integer","title":"Place Count"},"check_in_count":{"type":"integer","title":"Check In Count"}},"type":"object","required":["religion","place_count","check_in_count"],"title":"ReligionBreakdownItem"},"ResetPasswordBody":{"properties":{"token":{"type":"string","title":"Token"},"newPassword":{"type":"string","title":"Newpassword"}},"type":"object","required":["token","newPassword"],"title":"ResetPasswordBody"},"ReviewCreateBody":{"properties":{"rating":{"type":"integer","title":"Rating"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"},"is_anonymous":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Anonymous"},"photo_urls":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Photo Urls"}},"type":"object","required":["rating"],"title":"ReviewCreateBody"},"ReviewStats":{"properties":{"rating_histogram":{"additionalProperties":{"type":"integer"},"type":"object","title":"Rating Histogram"},"flagged_count":{"type":"integer","title":"Flagged Count"},"avg_rating":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Rating"},"total_reviews":{"type":"integer","title":"Total Reviews"}},"type":"object","required":["rating_histogram","flagged_count","avg_rating","total_reviews"],"title":"ReviewStats"},"ReviewUpdateBody":{"properties":{"rating":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rating"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"}},"type":"object","title":"ReviewUpdateBody"},"SEODetail":{"properties":{"place_code":{"type":"string","title":"Place Code"},"name":{"type":"string","title":"Name"},"religion":{"type":"string","title":"Religion"},"place_type":{"type":"string","title":"Place Type"},"address":{"type":"string","title":"Address"},"slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"},"seo_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Seo Title"},"meta_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meta Description"},"rich_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rich Description"},"faq_json":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Faq Json"},"og_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Og Image Url"},"is_manually_edited":{"type":"boolean","title":"Is Manually Edited"},"template_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Template Version"},"generated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Generated At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"translations":{"additionalProperties":{"$ref":"#/components/schemas/SEOLangDetail"},"type":"object","title":"Translations"}},"type":"object","required":["place_code","name","religion","place_type","address","slug","seo_title","meta_description","rich_description","faq_json","og_image_url","is_manually_edited","template_version","generated_at","updated_at","translations"],"title":"SEODetail"},"SEOLabelItem":{"properties":{"id":{"type":"integer","title":"Id"},"label_type":{"type":"string","title":"Label Type"},"label_key":{"type":"string","title":"Label Key"},"lang":{"type":"string","title":"Lang"},"label_text":{"type":"string","title":"Label Text"}},"type":"object","required":["id","label_type","label_key","lang","label_text"],"title":"SEOLabelItem"},"SEOLangDetail":{"properties":{"seo_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Seo Title"},"meta_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meta Description"},"rich_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rich Description"},"faq_json":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Faq Json"},"template_version":{"type":"integer","title":"Template Version"},"is_manually_edited":{"type":"boolean","title":"Is Manually Edited"},"generated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Generated At"}},"type":"object","required":["seo_title","meta_description","rich_description","faq_json","template_version","is_manually_edited","generated_at"],"title":"SEOLangDetail"},"SEOListItem":{"properties":{"place_code":{"type":"string","title":"Place Code"},"name":{"type":"string","title":"Name"},"religion":{"type":"string","title":"Religion"},"place_type":{"type":"string","title":"Place Type"},"has_seo":{"type":"boolean","title":"Has Seo"},"slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"},"seo_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Seo Title"},"meta_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meta Description"},"is_manually_edited":{"type":"boolean","title":"Is Manually Edited"},"generated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Generated At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["place_code","name","religion","place_type","has_seo","slug","seo_title","meta_description","is_manually_edited","generated_at","updated_at"],"title":"SEOListItem"},"SEOListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/SEOListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"SEOListResponse"},"SEOStats":{"properties":{"total_places":{"type":"integer","title":"Total Places"},"places_with_seo":{"type":"integer","title":"Places With Seo"},"places_missing_seo":{"type":"integer","title":"Places Missing Seo"},"places_manually_edited":{"type":"integer","title":"Places Manually Edited"},"coverage_pct":{"type":"number","title":"Coverage Pct"},"lang_coverage":{"additionalProperties":{"type":"integer"},"type":"object","title":"Lang Coverage"},"stale_count":{"type":"integer","title":"Stale Count"}},"type":"object","required":["total_places","places_with_seo","places_missing_seo","places_manually_edited","coverage_pct","lang_coverage","stale_count"],"title":"SEOStats"},"SEOTemplateItem":{"properties":{"id":{"type":"integer","title":"Id"},"template_code":{"type":"string","title":"Template Code"},"lang":{"type":"string","title":"Lang"},"template_text":{"type":"string","title":"Template Text"},"fallback_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fallback Text"},"static_phrases":{"additionalProperties":{"type":"string"},"type":"object","title":"Static Phrases"},"version":{"type":"integer","title":"Version"},"is_active":{"type":"boolean","title":"Is Active"}},"type":"object","required":["id","template_code","lang","template_text","fallback_text","static_phrases","version","is_active"],"title":"SEOTemplateItem"},"SendBody":{"properties":{"user_codes":{"items":{"type":"string"},"type":"array","title":"User Codes"},"type":{"type":"string","title":"Type"},"payload":{"additionalProperties":true,"type":"object","title":"Payload","default":{}}},"type":"object","required":["user_codes","type"],"title":"SendBody"},"SettingsBody":{"properties":{"notifications_on":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Notifications On"},"theme":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Theme"},"units":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Units"},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"},"religions":{"anyOf":[{"items":{"type":"string","enum":["islam","hinduism","christianity","all"]},"type":"array"},{"type":"null"}],"title":"Religions"}},"type":"object","title":"SettingsBody"},"StaleItem":{"properties":{"place_code":{"type":"string","title":"Place Code"},"name":{"type":"string","title":"Name"},"current_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Current Version"},"max_version":{"type":"integer","title":"Max Version"}},"type":"object","required":["place_code","name","current_version","max_version"],"title":"StaleItem"},"TranslationEntry":{"properties":{"key":{"type":"string","title":"Key"},"values":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object","title":"Values"},"overridden_langs":{"items":{"type":"string"},"type":"array","title":"Overridden Langs"}},"type":"object","required":["key","values","overridden_langs"],"title":"TranslationEntry"},"UntranslatedPlaceItem":{"properties":{"entity_type":{"type":"string","title":"Entity Type"},"entity_code":{"type":"string","title":"Entity Code"},"place_name":{"type":"string","title":"Place Name"},"fields":{"additionalProperties":{"type":"string"},"type":"object","title":"Fields"},"missing_langs":{"items":{"type":"string"},"type":"array","title":"Missing Langs"}},"type":"object","required":["entity_type","entity_code","place_name","fields","missing_langs"],"title":"UntranslatedPlaceItem"},"UpdateContentTranslationBody":{"properties":{"translated_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Translated Text"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},"type":"object","title":"UpdateContentTranslationBody"},"UpdateMeBody":{"properties":{"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"}},"type":"object","title":"UpdateMeBody"},"UpdateMemberRoleBody":{"properties":{"role":{"type":"string","title":"Role"}},"type":"object","required":["role"],"title":"UpdateMemberRoleBody"},"UpsertTranslationBody":{"properties":{"values":{"additionalProperties":{"type":"string"},"type":"object","title":"Values"}},"type":"object","required":["values"],"title":"UpsertTranslationBody"},"UserResponse":{"properties":{"user_code":{"type":"string","title":"User Code","description":"Unique opaque user identifier, e.g. usr_abc123"},"email":{"type":"string","title":"Email"},"display_name":{"type":"string","title":"Display Name"},"is_admin":{"type":"boolean","title":"Is Admin","description":"Whether the user has admin privileges","default":false},"email_verified":{"type":"boolean","title":"Email Verified","description":"Whether the email address has been verified","default":false},"religions":{"items":{"type":"string","enum":["islam","hinduism","christianity","all"]},"type":"array","title":"Religions","description":"User's religion filter preferences","default":[]},"created_at":{"type":"string","title":"Created At","description":"ISO 8601 UTC timestamp"},"updated_at":{"type":"string","title":"Updated At","description":"ISO 8601 UTC timestamp"}},"type":"object","required":["user_code","email","display_name","created_at","updated_at"],"title":"UserResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VerifyEmailBody":{"properties":{"token":{"type":"string","title":"Token"}},"type":"object","required":["token"],"title":"VerifyEmailBody"},"VisitorResponse":{"properties":{"visitor_code":{"type":"string","title":"Visitor Code"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["visitor_code","created_at"],"title":"VisitorResponse"},"VisitorSettingsBody":{"properties":{"theme":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Theme"},"units":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Units"},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"},"religions":{"anyOf":[{"items":{"type":"string","enum":["islam","hinduism","christianity","all"]},"type":"array"},{"type":"null"}],"title":"Religions"}},"type":"object","title":"VisitorSettingsBody"},"VisitorSettingsResponse":{"properties":{"theme":{"type":"string","title":"Theme"},"units":{"type":"string","title":"Units"},"language":{"type":"string","title":"Language"},"religions":{"items":{"type":"string","enum":["islam","hinduism","christianity","all"]},"type":"array","title":"Religions"}},"type":"object","required":["theme","units","language","religions"],"title":"VisitorSettingsResponse"},"_BulkTranslationJobOut":{"properties":{"job_code":{"type":"string","title":"Job Code"},"status":{"type":"string","title":"Status"},"job_type":{"type":"string","title":"Job Type"},"target_langs":{"items":{"type":"string"},"type":"array","title":"Target Langs"},"entity_types":{"items":{"type":"string"},"type":"array","title":"Entity Types"},"source_lang":{"type":"string","title":"Source Lang"},"total_items":{"type":"integer","title":"Total Items"},"completed_items":{"type":"integer","title":"Completed Items"},"failed_items":{"type":"integer","title":"Failed Items"},"skipped_items":{"type":"integer","title":"Skipped Items"},"progress_pct":{"type":"number","title":"Progress Pct"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Started At"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["job_code","status","job_type","target_langs","entity_types","source_lang","total_items","completed_items","failed_items","skipped_items","progress_pct","error_message","started_at","completed_at","created_at"],"title":"_BulkTranslationJobOut","description":"Minimal job output schema for import endpoint (avoids circular import)."},"_LangStat":{"properties":{"lang":{"type":"string","title":"Lang"},"translated":{"type":"integer","title":"Translated"},"eligible":{"type":"integer","title":"Eligible"},"pct":{"type":"number","title":"Pct"}},"type":"object","required":["lang","translated","eligible","pct"],"title":"_LangStat"},"app__api__v1__admin__check_ins__AdminCheckInListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminCheckInListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"AdminCheckInListResponse"},"app__api__v1__admin__reviews__AdminReviewListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminReviewListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"AdminReviewListResponse"},"app__api__v1__admin__users__AdminCheckInListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminCheckInItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"AdminCheckInListResponse"},"app__api__v1__admin__users__AdminReviewListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminReviewItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"}},"type":"object","required":["items","total","page","page_size"],"title":"AdminReviewListResponse"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}},"tags":[{"name":"auth","description":"Authentication: register, login, refresh, logout, and password reset."},{"name":"users","description":"Current-user profile, settings, stats, and check-in history."},{"name":"places","description":"Sacred site discovery, search, filtering, check-ins, favorites, reviews, and image management."},{"name":"reviews","description":"User reviews and ratings for sacred sites."},{"name":"groups","description":"Social groups: create, join via invite link, leaderboard, and activity."},{"name":"notifications","description":"In-app notification listing and mark-as-read."},{"name":"i18n","description":"Available languages and UI translation key-value pairs."},{"name":"visitors","description":"Anonymous visitor session management and visitor settings."}]}