{"openapi":"3.1.0","info":{"title":"Parky API (Owner Portal)","version":"0.1.0","description":"## 日本語\nParky BFF — Cloudflare Workers 上で動作する `/v1/*` API。モバイル・管理ポータル・公開 Web のすべてのクライアントがこの API のみを叩く。\n\n各 operation には想定呼出し元（portal-admin / portal-owner / app-web / app-mobile）を `x-channels` に保持し、Redoc ではバッジとしてタイトル横に表示される。ドキュメント用メタデータであり、サーバー側の振る舞いは呼出し元に依存しない。\n\n## English\nParky BFF — the `/v1/*` API running on Cloudflare Workers. Every client (mobile, admin portal, public web) hits only this API.\n\nEach operation declares its intended callers (portal-admin / portal-owner / app-web / app-mobile) via `x-channels`, rendered by Redoc as colored badges next to the operation title. This is documentation-only metadata; server behavior does not branch on the caller.\n\n> Route summaries / descriptions are primarily in Japanese. An English overlay is applied when the docs page language is switched to EN — see `docs/i18n/openapi-en-overlay.json` for current coverage."},"servers":[{"url":"https://dev-api.parky.co.jp","description":"Dev"},{"url":"https://api.parky.co.jp","description":"Production"},{"url":"http://localhost:8787","description":"Local"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Supabase Auth が発行した JWT（HS256 / SUPABASE_JWT_SECRET 署名）"}},"schemas":{"AppleAppSiteAssociation":{"type":"object","properties":{"applinks":{"type":"object","properties":{"details":{"type":"array","items":{"type":"object","properties":{"appIDs":{"type":"array","items":{"type":"string"}},"components":{"type":"array","items":{"type":"object","properties":{"/":{"type":"string"},"comment":{"type":"string"}},"required":["/"]}}},"required":["appIDs","components"]}}},"required":["details"]},"webcredentials":{"type":"object","properties":{"apps":{"type":"array","items":{"type":"string"}}},"required":["apps"]}},"required":["applinks","webcredentials"]},"AssetLinksEntry":{"type":"object","properties":{"relation":{"type":"array","items":{"type":"string"}},"target":{"type":"object","properties":{"namespace":{"type":"string"},"package_name":{"type":"string"},"sha256_cert_fingerprints":{"type":"array","items":{"type":"string"}}},"required":["namespace","package_name","sha256_cert_fingerprints"]}},"required":["relation","target"]},"AssetLinksResponse":{"type":"array","items":{"$ref":"#/components/schemas/AssetLinksEntry"}},"CodeRow":{"type":"object","properties":{"category_id":{"type":"string"},"code":{"type":"string"},"display_label":{"type":"string"},"lang":{"type":"string"},"sort_order":{"type":"integer"},"metadata":{"type":["object","null"],"additionalProperties":{}}},"required":["category_id","code","display_label","lang","sort_order","metadata"]},"CodesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/CodeRow"}},"lang":{"type":"string"}},"required":["items","lang"]},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","examples":["not_found"]},"message":{"type":"string","examples":["Not Found"]},"request_id":{"type":"string","examples":["7d4e5…-…"]}},"required":["code","message","request_id"]}},"required":["error"]},"Me":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"email":{"type":["string","null"]},"app_user":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"status":{"type":"string"},"created_at":{"type":"string"}},"required":["id","display_name","status","created_at"]},"admin":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"status":{"type":"string"}},"required":["id","name","status"]}},"required":["user_id","email","app_user","admin"]},"MeUpdate":{"type":"object","properties":{"display_name":{"type":"string","minLength":1,"maxLength":100}}},"SavedParkingLot":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"parking_lot_id":{"type":"string","format":"uuid"},"created_at":{"type":"string"}},"required":["id","user_id","parking_lot_id","created_at"]},"ParkingLotRating":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"parking_lot_id":{"type":"string","format":"uuid"},"value":{"type":"string","enum":["good","bad"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","user_id","parking_lot_id","value","created_at","updated_at"]},"UserVehicle":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"vehicle_type":{"type":"string"},"nickname":{"type":["string","null"]},"plate_number":{"type":["string","null"]},"color":{"type":["string","null"]},"is_default":{"type":"boolean"},"created_at":{"type":"string"}},"required":["id","user_id","vehicle_type","nickname","plate_number","color","is_default","created_at"]},"SearchQueryV1":{"type":"object","properties":{"v":{"type":"number","enum":[1],"description":"スキーマバージョン","examples":[1]},"center":{"type":"object","properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180},"placeName":{"type":"string","maxLength":200}},"required":["lat","lng"]},"radius_m":{"type":"integer","exclusiveMinimum":0,"maximum":50000},"price_min":{"type":["integer","null"],"minimum":0,"maximum":100000},"price_max":{"type":["integer","null"],"minimum":0,"maximum":100000},"attributes":{"type":"array","items":{"type":"string","enum":["covered","open_24h","entry_24h","ev_charging","oversized_ok","motorcycle_ok","wheelchair_accessible","barrier_free","reservable","security_camera","has_max_fee","monthly_available","coin_500_or_less","near_station","low_price","partner_facility","24h","max_fee"]},"maxItems":20},"difficulty":{"type":"array","items":{"type":"string","enum":["easy","normal","hard"]},"maxItems":3},"operator_codes":{"type":"array","items":{"type":"string","maxLength":50},"maxItems":50},"vehicle":{"type":"object","properties":{"height_m":{"type":["number","null"],"exclusiveMinimum":0,"maximum":10},"width_m":{"type":["number","null"],"exclusiveMinimum":0,"maximum":5},"length_m":{"type":["number","null"],"exclusiveMinimum":0,"maximum":20},"weight_t":{"type":["number","null"],"exclusiveMinimum":0,"maximum":50},"clearance_cm":{"type":["integer","null"],"minimum":0,"maximum":100},"tire_width_mm":{"type":["integer","null"],"exclusiveMinimum":0,"maximum":500}}},"keywords":{"type":"array","items":{"type":"string","minLength":1,"maxLength":50},"maxItems":10},"meter_ticket_included":{"type":"boolean"},"sort":{"type":"string","enum":["distance","price","recommended"]}},"additionalProperties":false},"SearchPreset":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"query_json":{"$ref":"#/components/schemas/SearchQueryV1"},"is_default":{"type":"boolean"},"sort_order":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","user_id","name","query_json","is_default","sort_order","created_at","updated_at"]},"ParkingSession":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"parking_lot_id":{"type":"string","format":"uuid"},"vehicle_type":{"type":["string","null"]},"status":{"type":"string"},"start_at":{"type":["string","null"]},"end_at":{"type":["string","null"]},"fee_amount":{"type":["integer","null"]},"memo":{"type":["string","null"]},"personal_rating":{"type":["string","null"]},"start_lat":{"type":["number","null"]},"start_lng":{"type":["number","null"]}},"required":["id","user_id","parking_lot_id","vehicle_type","status","start_at","end_at","fee_amount","memo","personal_rating","start_lat","start_lng"]},"ParkingSessionDetail":{"allOf":[{"$ref":"#/components/schemas/ParkingSession"},{"type":"object","properties":{"photos":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"phase":{"type":"string","enum":["during","after"]},"slot":{"type":"integer"},"r2_key":{"type":"string"},"content_type":{"type":["string","null"]},"size_bytes":{"type":["integer","null"]},"created_at":{"type":"string"}},"required":["id","phase","slot","r2_key","content_type","size_bytes","created_at"]}}},"required":["photos"]}]},"SessionPhoto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"phase":{"type":"string","enum":["during","after"]},"slot":{"type":"integer","minimum":1,"maximum":4},"r2_key":{"type":"string"},"content_type":{"type":["string","null"]},"size_bytes":{"type":["integer","null"]},"created_at":{"type":"string"}},"required":["id","phase","slot","r2_key","content_type","size_bytes","created_at"]},"MyReview":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"parking_lot_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"rating":{"type":"integer","minimum":1,"maximum":5},"comment":{"type":["string","null"]},"status":{"type":"string"},"created_at":{"type":"string"}},"required":["id","parking_lot_id","user_id","rating","comment","status","created_at"]},"PublicReview":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"parking_lot_id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"user_name":{"type":"string"},"rating":{"type":"integer","minimum":1,"maximum":5},"comment":{"type":["string","null"]},"status":{"type":"string"},"created_at":{"type":"string"}},"required":["id","parking_lot_id","user_id","user_name","rating","comment","status","created_at"]},"UserNotification":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"body":{"type":"string"},"type":{"type":"string"},"target":{"type":"string"},"status":{"type":"string"},"scheduled_at":{"type":["string","null"]},"sent_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","title","body","type","target","status","scheduled_at","sent_at","created_at"]},"NotifType":{"type":"object","properties":{"code":{"type":"string"},"display_label":{"type":"string"}},"required":["code","display_label"]},"NotifPrefItem":{"type":"object","properties":{"notif_type":{"type":"string"},"push_enabled":{"type":"boolean"},"in_app_enabled":{"type":"boolean"},"email_enabled":{"type":"boolean"}},"required":["notif_type","push_enabled","in_app_enabled","email_enabled"]},"UserPushToken":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"fcm_token":{"type":"string"},"device_type":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","user_id","fcm_token","device_type","created_at","updated_at"]},"MyExp":{"type":"object","properties":{"total_exp":{"type":"integer"},"level":{"type":"integer"},"next_level_exp":{"type":["integer","null"]},"exp_to_next_level":{"type":["integer","null"]}},"required":["total_exp","level","next_level_exp","exp_to_next_level"]},"MyBadge":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"badge_id":{"type":"string","format":"uuid"},"earned_at":{"type":"string"},"badge":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"icon":{"type":"string"},"category":{"type":"string"}},"required":["id","name","description","icon","category"]}},"required":["id","badge_id","earned_at","badge"]},"MyBadgeProgress":{"type":"object","properties":{"badge_id":{"type":"string","format":"uuid"},"count":{"type":"integer"},"threshold":{"type":"integer"},"percent":{"type":"number"},"badge":{"type":["object","null"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"icon":{"type":"string"},"category":{"type":"string"}},"required":["name","description","icon","category"]}},"required":["badge_id","count","threshold","percent","badge"]},"ThemeListItem":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"is_free":{"type":"boolean"},"price_yen_minor":{"type":["integer","null"]},"preview_asset_id":{"type":["string","null"],"format":"uuid"},"sort_order":{"type":"integer"}},"required":["id","name","description","is_free","price_yen_minor","preview_asset_id","sort_order"]},"MyTheme":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"theme_id":{"type":"string","format":"uuid"},"acquired_at":{"type":"string"},"acquisition_type":{"type":"string"},"theme":{"$ref":"#/components/schemas/ThemeListItem"}},"required":["id","theme_id","acquired_at","acquisition_type","theme"]},"SubscriptionPlan":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"price_minor":{"type":"integer"},"currency":{"type":"string"},"billing_period":{"type":"string"},"accent_color":{"type":["string","null"]},"features":{},"sort_order":{"type":"integer"}},"required":["id","code","name","description","price_minor","currency","billing_period","accent_color","sort_order"]},"MySubscription":{"type":"object","properties":{"id":{"type":["string","null"],"format":"uuid"},"plan_id":{"type":["string","null"],"format":"uuid"},"plan":{"$ref":"#/components/schemas/SubscriptionPlan"},"status":{"type":["string","null"]},"started_at":{"type":["string","null"]},"ended_at":{"type":["string","null"]}},"required":["id","plan_id","plan","status","started_at","ended_at"]},"VerifyIapResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"plan_id":{"type":"string","format":"uuid"},"status":{"type":"string","description":"active / expired / revoked / grace / on_hold / paused / pending / unknown"},"started_at":{"type":"string"},"ended_at":{"type":["string","null"]},"auto_renew_status":{"type":["boolean","null"],"description":"ios: autoRenewStatus (1=true)。android: SUBSCRIPTION_STATE_ACTIVE / CANCELED で導出。不明または取得不可の場合は null。"},"expires_at":{"type":["string","null"],"description":"サブスク期限の ISO 8601 文字列。ended_at と同値。"},"environment":{"type":["string","null"],"enum":["Sandbox","Production"],"description":"ios: Apple のレスポンスから取得。android: 常に Production（Play は環境を分離しない）。"},"platform":{"type":"string","enum":["ios","android"]},"external_subscription_id":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","user_id","plan_id","status","started_at","ended_at","auto_renew_status","expires_at","environment","platform","external_subscription_id","created_at","updated_at"]},"VerifyIapRequest":{"type":"object","properties":{"platform":{"type":"string","enum":["ios","android"],"description":"購入プラットフォーム。ios = App Store Server API (ES256 JWT → /inApps/v1/transactions/{id})、android = Google Play Developer API (subscriptionsV2 + OAuth2 SA JWT)"},"receipt":{"type":"string","minLength":1,"description":"ios: StoreKit2 が返す JWS (signedTransactionInfo)、またはレガシー base64 レシート。android: BillingClient が返す purchaseToken。"},"product_id":{"type":"string","minLength":1,"description":"subscription_plans.code に対応する productId / subscriptionId。"},"transaction_id":{"type":"string","description":"ios のみ。StoreKit2 がデコード済みの transactionId を渡してくれる場合に指定。未指定時は receipt の JWS ペイロードから transactionId クレームを抽出。"}},"required":["platform","receipt","product_id"]},"RefreshIapRequest":{"type":"object","properties":{"platform":{"type":"string","enum":["ios","android"],"description":"verify-iap に渡したものと同じプラットフォーム。"},"receipt":{"type":"string","minLength":1,"description":"ios: 最新の signedTransactionInfo JWS（StoreKit2 が自動更新後に返す）。android: 変わらず purchaseToken（同一トークンで最新状態を取得できる）。"},"product_id":{"type":"string","minLength":1,"description":"subscription_plans.code に対応する productId / subscriptionId。"},"transaction_id":{"type":"string","description":"ios のみ。最新の transactionId があれば指定（省略時は receipt から抽出）。"}},"required":["platform","receipt","product_id"]},"MeErrorReport":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"parking_lot_id":{"type":["string","null"],"format":"uuid"},"parking_lot_name":{"type":"string"},"report_type":{"type":"string"},"severity":{"type":["string","null"]},"status":{"type":"string"},"description":{"type":"string"},"evidence_urls":{"type":["array","null"],"items":{"type":"string"}},"created_at":{"type":"string"}},"required":["id","parking_lot_id","parking_lot_name","report_type","severity","status","description","evidence_urls","created_at"]},"ParkingLot":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"total_spaces":{"type":["integer","null"]},"status":{"type":["string","null"]},"structure":{"type":["string","null"]},"operating_hours":{"type":["string","null"]},"created_at":{"type":"string"},"max_height_m":{"type":["number","null"]},"max_width_m":{"type":["number","null"]},"max_length_m":{"type":["number","null"]},"max_weight_t":{"type":["number","null"]},"min_clearance_cm":{"type":["integer","null"]},"max_tire_width_mm":{"type":["integer","null"]},"max_parking_duration_min":{"type":["integer","null"]},"entry_method":{"type":["string","null"]},"source":{"type":["string","null"]},"shape_type":{"type":["string","null"]},"area":{},"operator_code":{"type":["string","null"]},"entry_difficulty":{"type":["string","null"]}},"required":["id","name","address","lat","lng","total_spaces","status","structure","operating_hours","created_at"]},"NearbyParkingLot":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"distance_m":{"type":"number"}},"required":["id","name","address","lat","lng","distance_m"]},"NearbyParkingLotWithRanking":{"allOf":[{"$ref":"#/components/schemas/NearbyParkingLot"},{"type":"object","properties":{"ranking_score":{"type":"number","description":"ランキングスコア 0-100（料金40%+距離40%+星評価20%）"},"ranking_rank":{"type":"integer","description":"score 降順の順位（1-based）"},"is_top3":{"type":"boolean","description":"上位3位バッジ用フラグ"}}}]},"ParkingLotWithDetail":{"allOf":[{"$ref":"#/components/schemas/ParkingLot"},{"type":"object","properties":{"pricing_rules":{"type":"array","items":{}},"images":{"type":"array","items":{}},"tags":{"type":"array","items":{}},"operator":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"color":{"type":"string"}},"required":["id","name","slug","color"]},"is_open_now":{"type":["boolean","null"],"description":"現在営業中かどうか（null = 営業時間未設定）"}}}]},"PricingRule":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"parking_lot_id":{"type":"string","format":"uuid"},"category":{"type":"string"},"rule_order":{"type":"integer"},"time_start":{"type":["string","null"]},"time_end":{"type":["string","null"]},"day_type":{"type":["string","null"]},"per_minutes":{"type":["integer","null"]},"price_minor":{"type":["integer","null"]},"cap_type":{"type":["string","null"]},"cap_duration_hours":{"type":["number","null"]},"cap_price_minor":{"type":["integer","null"]},"cap_repeat":{"type":["boolean","null"]}},"required":["id","parking_lot_id","category","rule_order","time_start","time_end","day_type","per_minutes","price_minor","cap_type","cap_duration_hours","cap_price_minor","cap_repeat"]},"NearbyStationItem":{"type":"object","properties":{"distance_m":{"type":["number","null"]},"walk_min":{"type":["number","null"]},"station":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"code":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]}},"required":["id","name","code","lat","lng"]}},"required":["distance_m","station"]},"ParkingLotImage":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"parking_lot_id":{"type":"string","format":"uuid"},"asset_id":{"type":"string","format":"uuid"},"is_main":{"type":"boolean"},"sort_order":{"type":["integer","null"]}},"required":["id","parking_lot_id","asset_id","is_main","sort_order"]},"FeeCalcResponse":{"type":"object","properties":{"total_amount_minor":{"type":"integer"},"breakdown":{"type":"array","items":{}},"note":{"type":"string"}},"required":["total_amount_minor","breakdown"]},"FeeCalcRequest":{"type":"object","properties":{"entry_at":{"type":"string","format":"date-time"},"exit_at":{"type":"string","format":"date-time"},"vehicle_type":{"type":"string","default":"sedan"}},"required":["entry_at","exit_at"]},"Review":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"parking_lot_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"rating":{"type":"integer","minimum":1,"maximum":5},"comment":{"type":["string","null"]},"status":{"type":"string"},"created_at":{"type":"string"},"owner_reply":{"type":["string","null"],"description":"オーナーからの返信テキスト（未返信時は null）"},"owner_replied_at":{"type":["string","null"],"description":"オーナー返信日時（ISO8601）"}},"required":["id","parking_lot_id","user_id","rating","comment","status","created_at","owner_reply","owner_replied_at"]},"Tag":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"color":{"type":["string","null"]},"sort_order":{"type":["integer","null"]},"slug":{"type":["string","null"]},"category":{"type":["string","null"]},"icon_name":{"type":["string","null"]}},"required":["id","name","color","sort_order"]},"ArticleListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":["string","null"]},"title":{"type":"string"},"excerpt":{"type":["string","null"]},"category":{"type":"string"},"content_format":{"type":["string","null"]},"author_name":{"type":["string","null"]},"author_slug":{"type":["string","null"]},"published_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"thumbnail_url":{"type":["string","null"]},"hero_image_url":{"type":["string","null"]},"tags":{"type":"array","items":{"type":"string"}},"related_hubs":{"type":"array","items":{}},"story_number":{"type":["integer","null"]},"view_count":{"type":["integer","null"]}},"required":["id","slug","title","excerpt","category","content_format","author_name","author_slug","published_at","updated_at","thumbnail_url","hero_image_url","tags","related_hubs","story_number","view_count"]},"Article":{"allOf":[{"$ref":"#/components/schemas/ArticleListItem"},{"type":"object","properties":{"updated_at":{"type":"string"},"view_count":{"type":"integer"},"body":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["body","created_at"]}]},"Ad":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"ad_type":{"type":"string"},"placement":{"type":"string"},"banner_url":{"type":["string","null"]},"link_url":{"type":["string","null"]},"alt_text":{"type":["string","null"]},"start_date":{"type":["string","null"]},"end_date":{"type":["string","null"]}},"required":["id","name","ad_type","placement","banner_url","link_url","alt_text","start_date","end_date"]},"SupportTicket":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"user_email":{"type":"string"},"user_name":{"type":"string"},"subject":{"type":"string"},"body":{"type":"string"},"category":{"type":"string"},"priority":{"type":"string"},"status":{"type":"string"},"created_at":{"type":"string"}},"required":["id","user_id","user_email","user_name","subject","body","category","priority","status","created_at"]},"ErrorReport":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"user_email":{"type":"string"},"user_name":{"type":"string"},"parking_lot_id":{"type":["string","null"],"format":"uuid"},"parking_lot_name":{"type":"string"},"report_type":{"type":"string"},"description":{"type":"string"},"severity":{"type":["string","null"]},"evidence_urls":{"type":["array","null"],"items":{"type":"string"}},"status":{"type":"string"},"photo_asset_id":{"type":["string","null"],"format":"uuid"},"created_at":{"type":"string"}},"required":["id","user_id","user_email","user_name","parking_lot_id","parking_lot_name","report_type","description","severity","evidence_urls","status","photo_asset_id","created_at"]},"ReviewFlagResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"review_id":{"type":"string","format":"uuid"},"reason":{"type":"string"},"status":{"type":"string"},"created_at":{"type":"string"}},"required":["id","review_id","reason","status","created_at"]},"AreaSponsor":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"category":{"type":"string"},"description":{"type":["string","null"]},"logo_url":{"type":["string","null"]},"banner_url":{"type":["string","null"]},"link_url":{"type":["string","null"]},"phone":{"type":["string","null"]},"address":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"radius_m":{"type":"integer"}},"required":["id","name","category","description","logo_url","banner_url","link_url","phone","address","lat","lng","radius_m"]},"UploadUrlResponse":{"type":"object","properties":{"asset_id":{"type":"string","format":"uuid"},"upload_url":{"type":"string","format":"uri"},"s3_key":{"type":"string"},"public_url":{"type":"string","format":"uri"},"expires_in":{"type":"integer"}},"required":["asset_id","upload_url","s3_key","public_url","expires_in"]},"Asset":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"file_name":{"type":"string"},"file_size":{"type":"integer"},"mime_type":{"type":"string"},"s3_key":{"type":"string"},"category":{"type":"string"},"entity_type":{"type":["string","null"]},"entity_id":{"type":["string","null"],"format":"uuid"},"is_public":{"type":"boolean"},"uploaded_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":"string"}},"required":["id","file_name","file_size","mime_type","s3_key","category","entity_type","entity_id","is_public","uploaded_by","created_at"]},"SearchLot":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"total_spaces":{"type":["integer","null"]},"status":{"type":["string","null"]},"structure":{"type":["string","null"]},"operating_hours":{"type":["string","null"]},"max_height_m":{"type":["number","null"]},"max_width_m":{"type":["number","null"]},"max_length_m":{"type":["number","null"]},"max_weight_t":{"type":["number","null"]},"min_clearance_cm":{"type":["integer","null"]},"max_tire_width_mm":{"type":["integer","null"]},"max_parking_duration_min":{"type":["integer","null"]},"entry_method":{"type":["string","null"]},"shape_type":{"type":["string","null"]},"area":{},"operator_code":{"type":["string","null"]},"operator_name":{"type":["string","null"]},"entry_difficulty":{"type":["string","null"]},"pricing_rules":{"type":"array","items":{}},"tags":{"type":"array","items":{}}},"required":["id","name","address","lat","lng","total_spaces","status","structure","operating_hours","max_height_m","max_width_m","max_length_m","max_weight_t","min_clearance_cm","max_tire_width_mm","max_parking_duration_min","entry_method","shape_type","operator_code","operator_name","entry_difficulty","pricing_rules","tags"]},"AiSearchQuery":{"type":"object","properties":{"keywords":{"type":"array","items":{"type":"string"}},"max_price_per_hour":{"type":"integer"},"roof":{"type":"boolean"},"open_24h":{"type":"boolean"},"vehicle_type":{"type":"string","enum":["sedan","kei","minivan","suv","truck"]}}},"AiSearchResponse":{"type":"object","properties":{"status":{"type":"string","enum":["parsed","need_info","error"]},"query":{"$ref":"#/components/schemas/AiSearchQuery"},"reply":{"type":"string"}},"required":["status","reply"]},"AiSearchRequest":{"type":"object","properties":{"message":{"type":"string","minLength":1,"maxLength":500},"session_id":{"type":"string"}},"required":["message"]},"HubStation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"name_en":{"type":["string","null"]},"lines":{"type":"array","items":{"type":"string"}},"code":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"city":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"name_en":{"type":["string","null"]},"slug":{"type":["string","null"]}},"required":["id","name","slug"]},"prefecture":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"name_en":{"type":["string","null"]},"slug":{"type":["string","null"]}},"required":["id","name","slug"]}},"required":["id","name","code","lat","lng","city","prefecture"]},"HubPublishableItem":{"type":"object","properties":{"stats":{"type":"object","properties":{"station_id":{"type":"string","format":"uuid"},"total_count":{"type":"integer"},"in_stock_count":{"type":"integer"},"out_of_stock_count":{"type":"integer"}},"required":["station_id","total_count","in_stock_count","out_of_stock_count"]},"station":{"$ref":"#/components/schemas/HubStation"}},"required":["stats","station"]},"HubParkingLot":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"total_spaces":{"type":["integer","null"]},"status":{"type":["string","null"]},"structure":{"type":["string","null"]},"operating_hours":{"type":["string","null"]},"max_height_m":{"type":["number","null"]},"max_width_m":{"type":["number","null"]},"max_length_m":{"type":["number","null"]},"max_weight_t":{"type":["number","null"]},"min_clearance_cm":{"type":["integer","null"]},"operator_code":{"type":["string","null"]},"operator_name":{"type":["string","null"]},"entry_difficulty":{"type":["string","null"]},"pricing_rules":{"type":"array","items":{}},"tags":{"type":"array","items":{}}},"required":["id","name","address","lat","lng","total_spaces","status","structure","operating_hours","max_height_m","max_width_m","max_length_m","max_weight_t","min_clearance_cm","operator_code","operator_name","entry_difficulty","pricing_rules","tags"]},"HubParkingLotItem":{"type":"object","properties":{"distance_m":{"type":["number","null"]},"walk_min":{"type":["number","null"]},"parking_lot":{"$ref":"#/components/schemas/HubParkingLot"}},"required":["distance_m","parking_lot"]},"ActivityTypeMeta":{"type":"object","properties":{"type":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["session","engagement","asset","discovery","account"]},"emitted_by":{"type":"string"},"emitted":{"type":"boolean"},"metadata_schema":{}},"required":["type","description","category","emitted_by","emitted"]},"ActivityTypesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ActivityTypeMeta"}}},"required":["items"]},"DeepLinkItem":{"type":"object","properties":{"pattern":{"type":"string","examples":["/parking-lots/:id"]},"screen":{"type":"string","examples":["ParkingLotDetail"]},"params":{"type":"array","items":{"type":"string"},"examples":[["id"]]},"requires_auth":{"type":"boolean","description":"未設定時は true 扱い（認証必須）。false のものは未ログインでも遷移できる。"}},"required":["pattern","screen","params"]},"DeepLinksResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/DeepLinkItem"}}},"required":["items"]},"AppConfig":{"type":"object","properties":{"min_app_version_ios":{"type":"string","examples":["1.0.0"]},"min_app_version_android":{"type":"string","examples":["1.0.0"]},"is_maintenance":{"type":"boolean","examples":[false]},"maintenance_message":{"type":["string","null"]},"store_url_ios":{"type":["string","null"]},"store_url_android":{"type":["string","null"]},"updated_at":{"type":"string"}},"required":["min_app_version_ios","min_app_version_android","is_maintenance","maintenance_message","store_url_ios","store_url_android","updated_at"]},"DataExport":{"type":"object","properties":{"export_date":{"type":"string"},"user_id":{"type":"string","format":"uuid"},"profile":{},"parking_sessions":{"type":"array","items":{}},"reviews":{"type":"array","items":{}},"ratings":{"type":"array","items":{}},"saved_parking_lots":{"type":"array","items":{}},"vehicles":{"type":"array","items":{}},"search_presets":{"type":"array","items":{}},"registered_device_count":{"type":"number"}},"required":["export_date","user_id","parking_sessions","reviews","ratings","saved_parking_lots","vehicles","search_presets","registered_device_count"]},"MyReferralCode":{"type":"object","properties":{"code":{"type":"string"},"usage_count":{"type":"integer"},"max_usages":{"type":["integer","null"]}},"required":["code","usage_count","max_usages"]},"ApplyReferralResponse":{"type":"object","properties":{"ok":{"type":"boolean"},"referrer_user_id":{"type":"string","format":"uuid"},"error":{"type":"string"}},"required":["ok"]},"ReferralHistoryItem":{"type":"object","properties":{"applied_at":{"type":"string"},"code":{"type":"string"},"referee_label":{"type":"string"}},"required":["applied_at","code","referee_label"]},"ReferralHistory":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ReferralHistoryItem"}}},"required":["items"]},"ConsentType":{"type":"object","properties":{"code":{"type":"string","examples":["terms_of_service"]},"current_version":{"type":"string","examples":["2026-04-01"]},"required":{"type":"boolean","examples":[true]},"display_label":{"type":"string","examples":["利用規約"]},"document_url":{"type":["string","null"],"examples":["https://parky.co.jp/terms"]},"updated_at":{"type":"string","examples":["2026-04-01T00:00:00Z"]}},"required":["code","current_version","required","display_label","document_url","updated_at"]},"ConsentItem":{"type":"object","properties":{"consent_type":{"type":"string","examples":["terms_of_service"]},"version":{"type":"string","examples":["2026-04-01"]},"granted":{"type":"boolean","examples":[true]},"granted_at":{"type":"string","examples":["2026-04-21T03:00:00Z"]},"source":{"type":["string","null"],"examples":["mobile_ios"]}},"required":["consent_type","version","granted","granted_at","source"]},"ConsentPostBody":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"consent_type":{"type":"string","minLength":1,"examples":["terms_of_service"]},"version":{"type":"string","minLength":1,"examples":["2026-04-01"]},"granted":{"type":"boolean"},"source":{"type":"string","examples":["mobile_ios"]}},"required":["consent_type","version","granted"]},"minItems":1,"maxItems":20}},"required":["items"]},"ClientEventCreated":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"created_at":{"type":"string"}},"required":["id","created_at"]},"SharePublic":{"type":"object","properties":{"parking_session_id":{"type":"string","format":"uuid"},"parking_lot_id":{"type":"string","format":"uuid"},"parking_lot_name":{"type":["string","null"]},"start_lat":{"type":["number","null"]},"start_lng":{"type":["number","null"]},"start_at":{"type":["string","null"]},"status":{"type":"string"},"access_count":{"type":"integer"},"expires_at":{"type":"string"}},"required":["parking_session_id","parking_lot_id","parking_lot_name","start_lat","start_lng","start_at","status","access_count","expires_at"]},"Admin":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"name":{"type":"string"},"email":{"type":"string"},"role_id":{"type":"string","format":"uuid"},"status":{"type":"string"},"last_login_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","user_id","name","email","role_id","status","last_login_at","created_at"]},"AdminNotificationPrefs":{"type":"object","properties":{"new_owner":{"type":"boolean","default":true},"new_parking":{"type":"boolean","default":true},"sales_daily":{"type":"boolean","default":true},"sales_monthly":{"type":"boolean","default":true},"system_alert":{"type":"boolean","default":true}}},"Role":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"color":{"type":"string"},"is_system":{"type":"boolean"},"created_at":{"type":"string"}},"required":["id","name","description","color","is_system","created_at"]},"AdminParkingLot":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"status":{"type":["string","null"]},"total_spaces":{"type":["integer","null"]},"operating_hours":{"type":["string","null"]},"operator_code":{"type":["string","null"]},"entry_difficulty":{"type":["string","null"]}},"required":["id","name","address","lat","lng","status","total_spaces","operating_hours"]},"AdminAppUser":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"auth_user_id":{"type":["string","null"],"format":"uuid"},"display_name":{"type":"string"},"email":{"type":"string"},"vehicle_type":{"type":["string","null"]},"premium":{"type":"boolean"},"status":{"type":"string"},"created_at":{"type":"string"}},"required":["id","auth_user_id","display_name","email","vehicle_type","premium","status","created_at"]},"AdminTag":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"color":{"type":"string"},"sort_order":{"type":"integer"},"created_at":{"type":"string"},"slug":{"type":["string","null"]},"category":{"type":["string","null"]},"icon_name":{"type":["string","null"]},"usage_count":{"type":"integer"}},"required":["id","name","color","sort_order","created_at","slug","category","icon_name"]},"AdminOperator":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"color":{"type":"string"},"sort_order":{"type":"integer"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"deleted_at":{"type":["string","null"]},"usage_count":{"type":"integer"}},"required":["id","name","slug","color","sort_order","created_at","updated_at","deleted_at"]},"AdminNotification":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"message":{"type":"string"},"category":{"type":"string"},"avatar":{"type":"string"},"read":{"type":"boolean"},"created_at":{"type":"string"},"deleted_at":{"type":["string","null"]}},"required":["id","title","message","category","avatar","read","created_at","deleted_at"]},"AdminUserNotification":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"body":{"type":"string"},"type":{"type":"string"},"target":{"type":"string"},"status":{"type":"string"},"scheduled_at":{"type":["string","null"]},"sent_at":{"type":["string","null"]},"total_recipients":{"type":["integer","null"]},"success_count":{"type":["integer","null"]},"failure_count":{"type":["integer","null"]},"created_at":{"type":"string"},"deleted_at":{"type":["string","null"]}},"required":["id","title","body","type","target","status","scheduled_at","sent_at","total_recipients","success_count","failure_count","created_at","deleted_at"]},"DispatchEnqueued":{"type":"object","properties":{"notification_id":{"type":"string","format":"uuid"},"enqueued":{"type":"integer"},"batches":{"type":"integer"}},"required":["notification_id","enqueued","batches"]},"AdminReview":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"parking_lot_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"rating":{"type":"integer"},"comment":{"type":["string","null"]},"status":{"type":"string"},"admin_note":{"type":["string","null"]},"created_at":{"type":"string"},"deleted_at":{"type":["string","null"]}},"required":["id","parking_lot_id","user_id","rating","comment","status","admin_note","created_at","deleted_at"]},"AdminSupportTicket":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"user_email":{"type":"string"},"user_name":{"type":"string"},"subject":{"type":"string"},"body":{"type":"string"},"category":{"type":"string"},"priority":{"type":"string"},"status":{"type":"string"},"created_at":{"type":"string"}},"required":["id","user_id","user_email","user_name","subject","body","category","priority","status","created_at"]},"AdminErrorReport":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"user_email":{"type":"string"},"user_name":{"type":"string"},"parking_lot_id":{"type":["string","null"],"format":"uuid"},"parking_lot_name":{"type":"string"},"report_type":{"type":"string"},"description":{"type":"string"},"status":{"type":"string"},"severity":{"type":["string","null"]},"evidence_urls":{"type":["array","null"],"items":{"type":"string"}},"resolved_by":{"type":["string","null"],"format":"uuid"},"admin_note":{"type":["string","null"]},"created_at":{"type":"string"},"resolved_at":{"type":["string","null"]},"user":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]}},"required":["id","display_name"]},"parking_lot":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"]}},"required":["id","user_id","user_email","user_name","parking_lot_id","parking_lot_name","report_type","description","status","severity","evidence_urls","resolved_by","admin_note","created_at","resolved_at"]},"AdminTask":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"task_kind":{"type":"string"},"ref_id":{"type":"string","format":"uuid"},"assignee_id":{"type":["string","null"],"format":"uuid"},"urgency":{"type":"string"},"due_at":{"type":["string","null"]},"memo":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","task_kind","ref_id","assignee_id","urgency","due_at","memo","created_at","updated_at"]},"AdminArticle":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":["string","null"]},"title":{"type":"string"},"body":{"type":["string","null"]},"excerpt":{"type":["string","null"]},"category":{"type":"string"},"author_name":{"type":["string","null"]},"status":{"type":"string"},"published_at":{"type":["string","null"]},"view_count":{"type":"integer"},"tags":{"type":"array","items":{"type":"string"}},"thumbnail_url":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"publish_to_web":{"type":"boolean"},"publish_to_app":{"type":"boolean"},"hero_image_url":{"type":["string","null"]},"author_slug":{"type":["string","null"]},"content_format":{"type":"string"},"related_hubs":{}},"required":["id","slug","title","body","excerpt","category","author_name","status","published_at","view_count","tags","thumbnail_url","created_at","updated_at"]},"AdminArticleTag":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"sort_order":{"type":"integer"},"created_at":{"type":"string"}},"required":["id","name","sort_order","created_at"]},"AdminAd":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"ad_type":{"type":"string"},"placement":{"type":"string"},"banner_url":{"type":["string","null"]},"link_url":{"type":["string","null"]},"alt_text":{"type":["string","null"]},"status":{"type":"string"},"start_date":{"type":["string","null"]},"end_date":{"type":["string","null"]},"impressions":{"type":"integer"},"clicks":{"type":"integer"},"memo":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","ad_type","placement","banner_url","link_url","alt_text","status","start_date","end_date","impressions","clicks","memo","created_at","updated_at"]},"AdminBoost":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"owner_id":{"type":"string","format":"uuid"},"parking_lot_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"credit_per_impression":{"type":"integer"},"daily_budget":{"type":["integer","null"]},"total_budget":{"type":["integer","null"]},"status":{"type":"string"},"started_at":{"type":"string"},"ended_at":{"type":["string","null"]},"owner":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"email":{"type":["string","null"]}},"required":["id","name","email"]},"parking_lot":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":["string","null"]}},"required":["id","name","address"]}},"required":["id","owner_id","parking_lot_id","name","credit_per_impression","daily_budget","total_budget","status","started_at","ended_at"]},"AdminSponsor":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"category":{"type":"string"},"description":{"type":["string","null"]},"logo_url":{"type":["string","null"]},"banner_url":{"type":["string","null"]},"link_url":{"type":["string","null"]}},"required":["id","name","category","description","logo_url","banner_url","link_url"]},"AdminOwner":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"owner_type":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"phone":{"type":["string","null"]},"status":{"type":"string"},"company_name":{"type":["string","null"]},"representative_name":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"parking_count":{"type":"integer"}},"required":["id","owner_type","name","email","phone","status","company_name","representative_name","created_at","updated_at"]},"AdminOwnerCredit":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"owner_id":{"type":"string","format":"uuid"},"balance":{"type":"integer"},"total_purchased":{"type":"integer"},"total_consumed":{"type":"integer"},"updated_at":{"type":["string","null"]},"owner":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"email":{"type":["string","null"]},"owner_type":{"type":["string","null"]}},"required":["id","name","email","owner_type"]}},"required":["id","owner_id","balance","total_purchased","total_consumed","owner"]},"AdminOwnerApplication":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"owner_id":{"type":["string","null"],"format":"uuid"},"owner_name":{"type":"string"},"owner_email":{"type":"string"},"company_name":{"type":["string","null"]},"parking_lot_id":{"type":"string","format":"uuid"},"proof_asset_id":{"type":["string","null"],"format":"uuid"},"additional_notes":{"type":["string","null"]},"status":{"type":"string"},"reviewed_by":{"type":["string","null"],"format":"uuid"},"reviewed_at":{"type":["string","null"]},"reject_reason":{"type":["string","null"]},"created_at":{"type":"string"},"owner":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"email":{"type":["string","null"]},"owner_type":{"type":["string","null"]}},"required":["id","name","email","owner_type"]},"parking_lot":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":["string","null"]}},"required":["id","name","address"]},"proof_asset":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"s3_key":{"type":"string"},"file_name":{"type":"string"},"mime_type":{"type":"string"},"category":{"type":["string","null"]}},"required":["id","s3_key","file_name","mime_type","category"]},"reviewer":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]}},"required":["id","name"]}},"required":["id","owner_id","owner_name","owner_email","company_name","parking_lot_id","status","reviewed_by","reviewed_at","reject_reason","created_at"]},"AdminActivityLog":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"admin_id":{"type":["string","null"],"format":"uuid"},"admin_email_snapshot":{"type":"string"},"action":{"type":"string"},"target_type":{"type":["string","null"]},"target_id":{"type":["string","null"]},"target_label":{"type":["string","null"]},"metadata":{},"ip_address":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","admin_id","admin_email_snapshot","action","target_type","target_id","target_label","ip_address","user_agent","created_at"]},"RevenueMonthlyRow":{"type":"object","properties":{"month":{"type":"string"},"channel":{"type":"string"},"amount_minor":{"type":"integer"},"count":{"type":"integer"}},"required":["month","channel","amount_minor","count"]},"RevenueTransaction":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"occurred_at":{"type":"string"},"channel":{"type":"string"},"transaction_type":{"type":"string"},"amount_minor":{"type":"integer"},"currency":{"type":"string"},"external_id":{"type":["string","null"]},"description":{"type":["string","null"]},"user_id":{"type":["string","null"],"format":"uuid"},"plan_id":{"type":["string","null"],"format":"uuid"},"created_at":{"type":"string"}},"required":["id","occurred_at","channel","transaction_type","amount_minor","currency","external_id","description","user_id","plan_id","created_at"]},"RevenueTransactionWithRelations":{"allOf":[{"$ref":"#/components/schemas/RevenueTransaction"},{"type":"object","properties":{"user":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"email":{"type":["string","null"]}},"required":["id","display_name","email"]},"plan":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"code":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","code","name"]}},"required":["user","plan"]}]},"AdminUserSubscription":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"plan_id":{"type":"string","format":"uuid"},"status":{"type":"string"},"started_at":{"type":"string"},"ended_at":{"type":["string","null"]},"external_subscription_id":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","user_id","plan_id","status","started_at","ended_at","external_subscription_id","created_at"]},"AdminSubscriptionPlan":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"price_minor":{"type":"integer"},"currency":{"type":"string"},"billing_period":{"type":"string"},"accent_color":{"type":["string","null"]},"features":{},"sort_order":{"type":"integer"},"is_active":{"type":"boolean"}},"required":["id","code","name","description","price_minor","currency","billing_period","accent_color","sort_order","is_active"]},"StoreIntegration":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"store":{"type":"string"},"display_name":{"type":"string"},"package_or_app_id":{"type":["string","null"]},"vendor_number":{"type":["string","null"]},"connection_status":{"type":"string"},"last_status_message":{"type":["string","null"]},"last_synced_at":{"type":["string","null"]},"last_sync_error":{"type":["string","null"]}},"required":["id","store","display_name","package_or_app_id","vendor_number","connection_status","last_status_message","last_synced_at","last_sync_error"]},"StoreSalesRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"store":{"type":"string"},"report_date":{"type":"string"},"product_id":{"type":"string"},"country_code":{"type":"string"},"units":{"type":"integer"},"proceeds_minor":{"type":"integer"},"gross_minor":{"type":"integer"},"currency":{"type":"string"},"fetched_at":{"type":"string"}},"required":["id","store","report_date","product_id","country_code","units","proceeds_minor","gross_minor","currency","fetched_at"]},"StoreMetricsRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"store":{"type":"string"},"metric_date":{"type":"string"},"installs":{"type":["integer","null"]},"uninstalls":{"type":["integer","null"]},"active_devices":{"type":["integer","null"]},"impressions":{"type":["integer","null"]},"product_page_views":{"type":["integer","null"]},"crash_rate":{"type":["number","null"]},"anr_rate":{"type":["number","null"]},"rating_average":{"type":["number","null"]},"rating_count":{"type":["integer","null"]}},"required":["id","store","metric_date","installs","uninstalls","active_devices","impressions","product_page_views","crash_rate","anr_rate","rating_average","rating_count"]},"StoreReview":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"store":{"type":"string"},"external_review_id":{"type":"string"},"author_name":{"type":["string","null"]},"rating":{"type":["integer","null"]},"title":{"type":["string","null"]},"body":{"type":["string","null"]},"reply_body":{"type":["string","null"]},"reply_at":{"type":["string","null"]},"posted_at":{"type":"string"}},"required":["id","store","external_review_id","author_name","rating","title","body","reply_body","reply_at","posted_at"]},"StoreSyncRun":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"store":{"type":"string"},"task":{"type":"string"},"status":{"type":"string"},"started_at":{"type":"string"},"finished_at":{"type":["string","null"]},"rows_upserted":{"type":"integer"},"message":{"type":["string","null"]},"triggered_by":{"type":"string"}},"required":["id","store","task","status","started_at","finished_at","rows_upserted","message","triggered_by"]},"BadgeDefinition":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"icon":{"type":"string"},"activity_type":{"type":"string"},"threshold":{"type":"integer"},"sort_order":{"type":"integer"},"is_active":{"type":"boolean"},"asset_id":{"type":["string","null"],"format":"uuid"},"conditions":{},"category":{"type":"string"},"created_at":{"type":"string"},"holders_count":{"type":"integer"},"asset":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"s3_key":{"type":"string"},"file_name":{"type":"string"},"mime_type":{"type":"string"},"category":{"type":["string","null"]}},"required":["id","s3_key","file_name","mime_type","category"]},"tags":{"type":"array","items":{"type":"string"}}},"required":["id","name","description","icon","activity_type","threshold","sort_order","is_active","asset_id","category","created_at"]},"ActivityExpRule":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"activity_type":{"type":"string"},"exp_amount":{"type":"integer"},"description":{"type":"string"},"is_active":{"type":"boolean"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","activity_type","exp_amount","description","is_active","created_at","updated_at"]},"LevelDefinition":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"level":{"type":"integer"},"required_exp":{"type":"integer"},"created_at":{"type":"string"}},"required":["id","level","required_exp","created_at"]},"AdminTheme":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"is_free":{"type":"boolean"},"price_yen_minor":{"type":["integer","null"]},"preview_asset_id":{"type":["string","null"],"format":"uuid"},"is_active":{"type":"boolean"},"sort_order":{"type":"integer"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"preview_asset":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"s3_key":{"type":"string"},"file_name":{"type":"string"},"mime_type":{"type":"string"},"category":{"type":["string","null"]}},"required":["id","s3_key","file_name","mime_type","category"]},"owners_count":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"theme_id":{"type":"string","format":"uuid"},"category":{"type":"string"},"part_id":{"type":"string","format":"uuid"}},"required":["id","theme_id","category","part_id"]}}},"required":["id","name","description","is_free","price_yen_minor","preview_asset_id","is_active","sort_order","created_at","updated_at"]},"AdminThemePart":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"category":{"type":"string"},"primary_color":{"type":["string","null"]},"accent_color":{"type":["string","null"]},"pin_asset_id":{"type":["string","null"],"format":"uuid"},"icon_asset_id":{"type":["string","null"],"format":"uuid"},"loading_asset_id":{"type":["string","null"],"format":"uuid"},"loading_type":{"type":["string","null"]},"is_active":{"type":"boolean"},"sort_order":{"type":"integer"},"used_in_themes_count":{"type":"integer"},"tags":{"type":"array","items":{"type":"string"}},"pin_asset":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"s3_key":{"type":"string"},"file_name":{"type":"string"},"mime_type":{"type":"string"},"category":{"type":["string","null"]}},"required":["id","s3_key","file_name","mime_type","category"]},"icon_asset":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"s3_key":{"type":"string"},"file_name":{"type":"string"},"mime_type":{"type":"string"},"category":{"type":["string","null"]}},"required":["id","s3_key","file_name","mime_type","category"]},"loading_asset":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"s3_key":{"type":"string"},"file_name":{"type":"string"},"mime_type":{"type":"string"},"category":{"type":["string","null"]}},"required":["id","s3_key","file_name","mime_type","category"]}},"required":["id","name","description","category","primary_color","accent_color","pin_asset_id","icon_asset_id","loading_asset_id","loading_type","is_active","sort_order"]},"AiProvider":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"provider_key":{"type":"string"},"display_name":{"type":"string"},"model_name":{"type":"string"},"vault_secret_id":{"type":["string","null"],"format":"uuid"},"is_enabled":{"type":"boolean"},"priority":{"type":"integer"},"config":{},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","provider_key","display_name","model_name","vault_secret_id","is_enabled","priority","created_at","updated_at"]},"AiUsageLog":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"provider_key":{"type":"string"},"user_input":{"type":"string"},"parsed_query":{},"response_status":{"type":"string"},"attempt_number":{"type":"integer"},"fallback_reason":{"type":["string","null"]},"error_code":{"type":["string","null"]},"error_message":{"type":["string","null"]},"session_id":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","provider_key","user_input","response_status","attempt_number","fallback_reason","error_code","error_message","session_id","created_at"]},"AdminCode":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"category_id":{"type":"string"},"code":{"type":"string"},"display_label":{"type":"string"},"lang":{"type":"string"},"sort_order":{"type":["integer","null"]},"is_deleted":{"type":"boolean"}},"required":["id","category_id","code","display_label","lang","sort_order","is_deleted"]},"AdminParkingSession":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"parking_lot_id":{"type":"string","format":"uuid"},"vehicle_id":{"type":["string","null"],"format":"uuid"},"started_at":{"type":["string","null"]},"ended_at":{"type":["string","null"]},"status":{"type":"string"},"total_amount_minor":{"type":["number","null"]},"memo":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","user_id","parking_lot_id","vehicle_id","started_at","ended_at","status","total_amount_minor","created_at"]},"AdminParkingSessionWithRelations":{"allOf":[{"$ref":"#/components/schemas/AdminParkingSession"},{"type":"object","properties":{"user":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"email":{"type":["string","null"]}},"required":["id","display_name","email"]},"parking_lot":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":["string","null"]}},"required":["id","name","address"]}},"required":["user","parking_lot"]}]},"IgSlideCategory":{"type":"object","properties":{"code":{"type":"string"},"label":{"type":"string"},"prefix":{"type":["string","null"]},"sort_order":{"type":"integer"},"is_deleted":{"type":"integer"}},"required":["code","label","prefix","sort_order","is_deleted"]},"IgPostCategory":{"type":"object","properties":{"code":{"type":"string"},"label":{"type":"string"},"color":{"type":["string","null"]},"sort_order":{"type":"integer"},"is_deleted":{"type":"integer"}},"required":["code","label","color","sort_order","is_deleted"]},"IgTag":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"color":{"type":["string","null"]},"usage_count":{"type":"integer"}},"required":["id","name","color","usage_count"]},"IgPostTemplate":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"slide_refs":{"type":"string"}},"required":["id","code","name","description","slide_refs"]},"IgTemplate":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"name":{"type":"string"},"slide_type":{"type":"string"},"html_body":{"type":"string"},"slot_schema":{"type":"string"},"sample_content":{"type":"string","default":"{}"},"sample_html":{"type":"string","default":""},"uses_parking_lot":{"type":"integer","default":0},"sort_order":{"type":"integer"},"is_active":{"type":"integer"}},"required":["id","code","name","slide_type","html_body","slot_schema","sort_order","is_active"]},"IgCampaign":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"title":{"type":"string"},"theme":{"type":["string","null"]},"area":{"type":["string","null"]},"status":{"type":"string"},"scheduled_at":{"type":["string","null"]},"ig_media_id":{"type":["string","null"]},"notes":{"type":["string","null"]},"source_material":{"type":["string","null"]},"post_category_code":{"type":["string","null"]},"created_by":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","code","title","theme","area","status","scheduled_at","ig_media_id","notes","source_material","post_category_code","created_by","created_at","updated_at"]},"IgSlide":{"type":"object","properties":{"id":{"type":"string"},"campaign_id":{"type":"string"},"template_id":{"type":"string"},"slide_index":{"type":"integer"},"content":{"type":"string"},"html_override":{"type":["string","null"]},"png_r2_key":{"type":["string","null"]},"png_url":{"type":["string","null"]},"revision_notes":{"type":["string","null"]},"parking_lot_id":{"type":["string","null"],"format":"uuid"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","campaign_id","template_id","slide_index","content","html_override","png_r2_key","png_url","revision_notes","created_at","updated_at"]},"IgCaption":{"type":["object","null"],"properties":{"id":{"type":"string"},"campaign_id":{"type":"string"},"body":{"type":["string","null"]},"hashtags":{"type":["string","null"]},"draft_body":{"type":["string","null"]},"generated_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","campaign_id","body","hashtags","draft_body","generated_at","created_at","updated_at"]},"IgCompetitorSnapshot":{"type":"object","properties":{"id":{"type":"string"},"campaign_id":{"type":["string","null"]},"source_url":{"type":["string","null"]},"account_handle":{"type":["string","null"]},"raw_notes":{"type":["string","null"]},"ai_ideas":{"type":["string","null"]},"created_by":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","campaign_id","source_url","account_handle","raw_notes","ai_ideas","created_by","created_at"]},"AdminAsset":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"category":{"type":"string"},"s3_key":{"type":"string"},"file_name":{"type":"string"},"mime_type":{"type":"string"},"file_size":{"type":"integer"},"width":{"type":["integer","null"]},"height":{"type":["integer","null"]},"created_at":{"type":"string"},"updated_at":{"type":["string","null"]}},"required":["id","category","s3_key","file_name","mime_type","file_size","width","height","created_at"]},"AdminUserVehicle":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"nickname":{"type":["string","null"]},"vehicle_type_code":{"type":["string","null"]},"maker_code":{"type":["string","null"]},"size_code":{"type":["string","null"]},"color_code":{"type":["string","null"]},"model_name":{"type":["string","null"]},"year":{"type":["integer","null"]},"asset_id":{"type":["string","null"],"format":"uuid"},"is_primary":{"type":"boolean"},"notes":{"type":["string","null"]},"deleted_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"user":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]}},"required":["id","display_name"]},"asset":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"s3_key":{"type":"string"},"file_name":{"type":"string"},"mime_type":{"type":"string"},"category":{"type":["string","null"]}},"required":["id","s3_key","file_name","mime_type","category"]}},"required":["id","user_id","nickname","vehicle_type_code","maker_code","size_code","color_code","model_name","year","asset_id","is_primary","notes","deleted_at","created_at","updated_at"]},"AdminUserSearchPreset":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"query_json":{"$ref":"#/components/schemas/SearchQueryV1"},"is_default":{"type":"boolean"},"sort_order":{"type":"integer"},"deleted_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"user":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]}},"required":["id","display_name"]}},"required":["id","user_id","name","query_json","is_default","sort_order","deleted_at","created_at","updated_at"]},"PlacesImportLotResult":{"type":"object","properties":{"lot_id":{"type":"string","format":"uuid"},"fetched":{"type":"integer"},"upserted":{"type":"integer"},"skipped":{"type":"integer"},"auto_on_map":{"type":"integer"},"auto_on_facility":{"type":"integer"}},"required":["lot_id","fetched","upserted","skipped","auto_on_map","auto_on_facility"]},"PlacesImportAllResult":{"type":"object","properties":{"total_lots":{"type":"integer"},"processed":{"type":"integer"},"total_upserted":{"type":"integer"},"errors":{"type":"array","items":{"type":"object","properties":{"lot_id":{"type":"string","format":"uuid"},"message":{"type":"string"}},"required":["lot_id","message"]}},"dry_run":{"type":"boolean"}},"required":["total_lots","processed","total_upserted","errors","dry_run"]},"AdminAreaPlace":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"category":{"type":"string"},"description":{"type":["string","null"]},"logo_url":{"type":["string","null"]},"banner_url":{"type":["string","null"]},"thumbnail_url":{"type":["string","null"]},"link_url":{"type":["string","null"]},"phone":{"type":["string","null"]},"address":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"radius_m":{"type":"integer"},"status":{"type":"string"},"is_sponsored":{"type":"boolean"},"source":{"type":"string"},"source_place_id":{"type":["string","null"]},"rating":{"type":["number","null"]},"user_ratings_total":{"type":["integer","null"]},"place_types":{"type":["array","null"],"items":{"type":"string"}},"show_on_map":{"type":"boolean"},"show_as_facility":{"type":"boolean"},"last_refreshed_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"deleted_at":{"type":["string","null"]}},"required":["id","name","category","lat","lng","radius_m","status","is_sponsored","source","show_on_map","show_as_facility","created_at","updated_at"]},"AdminPlaceDiscount":{"type":"object","properties":{"place_id":{"type":"string","format":"uuid"},"lot_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":["string","null"]},"terms":{"type":["string","null"]},"valid_from":{"type":["string","null"]},"valid_until":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"deleted_at":{"type":["string","null"]},"place_name":{"type":"string"},"lot_name":{"type":"string"}},"required":["place_id","lot_id","title","created_at","updated_at"]},"AdminAppConfig":{"type":"object","properties":{"min_app_version_ios":{"type":"string","examples":["1.0.0"]},"min_app_version_android":{"type":"string","examples":["1.0.0"]},"is_maintenance":{"type":"boolean","examples":[false]},"maintenance_message":{"type":["string","null"]},"store_url_ios":{"type":["string","null"]},"store_url_android":{"type":["string","null"]},"updated_at":{"type":"string"},"updated_by_admin_id":{"type":["string","null"],"format":"uuid"}},"required":["min_app_version_ios","min_app_version_android","is_maintenance","maintenance_message","store_url_ios","store_url_android","updated_at","updated_by_admin_id"]},"UpdateAppConfig":{"type":"object","properties":{"min_app_version_ios":{"type":"string","pattern":"^\\d+\\.\\d+\\.\\d+$","examples":["1.2.0"]},"min_app_version_android":{"type":"string","pattern":"^\\d+\\.\\d+\\.\\d+$","examples":["1.2.0"]},"is_maintenance":{"type":"boolean"},"maintenance_message":{"type":["string","null"],"maxLength":500},"store_url_ios":{"type":["string","null"],"format":"uri"},"store_url_android":{"type":["string","null"],"format":"uri"}}},"AdminClientEventListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"event_type":{"type":"string"},"severity":{"type":"string"},"message":{"type":["string","null"]},"app_version":{"type":["string","null"]},"platform":{"type":["string","null"]},"os_version":{"type":["string","null"]},"device_model":{"type":["string","null"]},"parking_session_id":{"type":["string","null"],"format":"uuid"},"created_at":{"type":"string"}},"required":["id","user_id","event_type","severity","message","app_version","platform","os_version","device_model","parking_session_id","created_at"]},"AdminClientEventDetail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"event_type":{"type":"string"},"severity":{"type":"string"},"message":{"type":["string","null"]},"stack_trace":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":{}},"app_version":{"type":["string","null"]},"platform":{"type":["string","null"]},"os_version":{"type":["string","null"]},"device_model":{"type":["string","null"]},"parking_session_id":{"type":["string","null"],"format":"uuid"},"created_at":{"type":"string"}},"required":["id","user_id","event_type","severity","message","stack_trace","metadata","app_version","platform","os_version","device_model","parking_session_id","created_at"]},"SnsMetricsSeriesItem":{"type":"object","properties":{"week":{"type":"string","examples":["2026-W15"]},"followers":{"type":"integer"},"engagementRate":{"type":"number"}},"required":["week","followers","engagementRate"]},"SnsMetricsPlatform":{"type":"object","properties":{"platform":{"type":"string","enum":["instagram","x"]},"followers":{"type":"integer"},"engagementRate":{"type":"number"},"weeklyDiffFollowers":{"type":"integer"},"weeklyDiffEngagementPt":{"type":"number"},"monthlyDiffFollowers":{"type":"integer"},"series":{"type":"array","items":{"$ref":"#/components/schemas/SnsMetricsSeriesItem"}}},"required":["platform","followers","engagementRate","weeklyDiffFollowers","weeklyDiffEngagementPt","monthlyDiffFollowers","series"]},"SnsMetricsResponse":{"type":"object","properties":{"platforms":{"type":"array","items":{"$ref":"#/components/schemas/SnsMetricsPlatform"}}},"required":["platforms"]},"PostCalendarDay":{"type":"object","properties":{"date":{"type":"string","examples":["2026-04-01"]},"instagram":{"type":"object","properties":{"draft":{"type":"integer"},"scheduled":{"type":"integer"},"published":{"type":"integer"}},"required":["draft","scheduled","published"]},"x":{"type":"object","properties":{"draft":{"type":"integer"},"scheduled":{"type":"integer"},"published":{"type":"integer"}},"required":["draft","scheduled","published"]}},"required":["date","instagram","x"]},"PostCalendarResponse":{"type":"object","properties":{"days":{"type":"array","items":{"$ref":"#/components/schemas/PostCalendarDay"}}},"required":["days"]},"ArticlesPvItem":{"type":"object","properties":{"id":{"anyOf":[{"type":"integer"},{"type":"string"}]},"slug":{"type":["string","null"]},"title":{"type":"string"},"pv":{"type":"integer"},"pvDiffPct":{"type":"number"}},"required":["id","slug","title","pv","pvDiffPct"]},"ArticlesPvResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ArticlesPvItem"}},"sources":{"type":"object","properties":{"direct":{"type":"integer"},"google":{"type":"integer"},"twitter":{"type":"integer"},"facebook":{"type":"integer"},"other":{"type":"integer"}},"required":["direct","google","twitter","facebook","other"]}},"required":["items","sources"]},"AdsCtrDaily":{"type":"object","properties":{"date":{"type":"string"},"clicks":{"type":"integer"}},"required":["date","clicks"]},"AdsCtrItem":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"startDate":{"type":["string","null"]},"endDate":{"type":["string","null"]},"impressions":{"type":"integer"},"clicks":{"type":"integer"},"ctr":{"type":"number"},"daysRemaining":{"type":"integer"},"daily":{"type":"array","items":{"$ref":"#/components/schemas/AdsCtrDaily"}}},"required":["id","name","startDate","endDate","impressions","clicks","ctr","daysRemaining","daily"]},"AdsCtrResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AdsCtrItem"}}},"required":["items"]},"MarketingSubscriber":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"source":{"type":["string","null"]},"lang":{"type":["string","null"]},"subscribed_at":{"type":"string"},"unsubscribed_at":{"type":["string","null"]},"meta":{},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","email","source","lang","subscribed_at","unsubscribed_at","created_at","updated_at"]},"MarketingBroadcast":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"subject":{"type":["string","null"]},"body_markdown":{"type":["string","null"]},"segment":{"type":["string","null"]},"status":{"type":"string"},"engine":{"type":["string","null"]},"scheduled_at":{"type":["string","null"]},"sent_at":{"type":["string","null"]},"delivered":{"type":"integer"},"opened":{"type":"integer"},"clicked":{"type":"integer"},"open_rate":{"type":"number"},"click_rate":{"type":"number"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","title","subject","body_markdown","segment","status","engine","scheduled_at","sent_at","delivered","opened","clicked","open_rate","click_rate","created_at","updated_at"]},"MarketingXAccount":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"handle":{"type":"string"},"display_name":{"type":["string","null"]},"tier":{"type":["string","null"]},"is_primary":{"type":"boolean"},"followers_count":{"type":"integer"},"has_token":{"type":"boolean"},"updated_at":{"type":["string","null"]},"following":{"type":"integer"},"postsTotal":{"type":"integer"},"verified":{"type":"boolean"},"bio":{"type":["string","null"]},"displayName":{"type":["string","null"]},"followers":{"type":"integer"},"updatedAt":{"type":["string","null"]}},"required":["id","handle","display_name","tier","is_primary","followers_count","has_token","updated_at","following","postsTotal","verified","bio","displayName","followers","updatedAt"]},"MarketingXPost":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"account_id":{"type":["string","null"],"format":"uuid"},"body":{"type":"string"},"thread_of":{"type":["string","null"],"format":"uuid"},"threadCount":{"type":"integer"},"status":{"type":"string"},"scheduled_at":{"type":["string","null"]},"published_at":{"type":["string","null"]},"x_tweet_id":{"type":["string","null"]},"impressions":{"type":"integer"},"likes":{"type":"integer"},"reposts":{"type":"integer"},"replies":{"type":"integer"},"error_message":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"accountId":{"type":["string","null"],"format":"uuid"},"threadOf":{"type":["string","null"],"format":"uuid"},"scheduledAt":{"type":["string","null"]},"publishedAt":{"type":["string","null"]},"xTweetId":{"type":["string","null"]},"errorMessage":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","account_id","body","thread_of","threadCount","status","scheduled_at","published_at","x_tweet_id","impressions","likes","reposts","replies","error_message","created_at","updated_at","accountId","threadOf","scheduledAt","publishedAt","xTweetId","errorMessage","createdAt","updatedAt"]},"MarketingXScheduleRule":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"dow":{"type":"array","items":{"type":"integer"}},"hour":{"type":"integer"},"minute":{"type":"integer"},"source_kind":{"type":"string"},"source_ref":{"type":["string","null"]},"category":{"type":["string","null"]},"enabled":{"type":"boolean"},"last_fired_at":{"type":["string","null"]},"created_at":{"type":"string"},"weekdays":{"type":"array","items":{"type":"integer"}},"sourceType":{"type":"string"},"sourceLabel":{"type":["string","null"]},"categoryFilter":{"type":"string"},"lastFiredAt":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","name","dow","hour","minute","source_kind","source_ref","category","enabled","last_fired_at","created_at","weekdays","sourceType","sourceLabel","categoryFilter","lastFiredAt","createdAt"]},"MarketingXListenRule":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"listen_kind":{"type":"string"},"target":{"type":"string"},"min_likes_threshold":{"type":["integer","null"]},"must_contain":{"type":["string","null"]},"must_not_contain":{"type":["string","null"]},"action_kinds":{"type":"array","items":{"type":"string"}},"reply_template":{"type":["string","null"]},"cooldown_minutes":{"type":"integer"},"enabled":{"type":"boolean"},"last_fired_at":{"type":["string","null"]},"created_at":{"type":"string"},"type":{"type":"string"},"minLikes":{"type":"integer"},"keywordContains":{"type":"string"},"actions":{"type":"array","items":{"type":"string"}},"replyTemplate":{"type":["string","null"]},"cooldownMinutes":{"type":"integer"},"lastFiredAt":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","name","listen_kind","target","min_likes_threshold","must_contain","must_not_contain","action_kinds","reply_template","cooldown_minutes","enabled","last_fired_at","created_at","type","minLikes","keywordContains","actions","replyTemplate","cooldownMinutes","lastFiredAt","createdAt"]},"MarketingXAutomationLog":{"type":"object","properties":{"id":{"type":"string"},"firedAt":{"type":"string"},"ruleName":{"type":"string"},"sourcePost":{"type":"string"},"author":{"type":"string"},"actionTaken":{"type":"string"},"rule_id":{"type":["string","null"],"format":"uuid"},"rule_kind":{"type":["string","null"]},"fired_at":{"type":"string"},"target_tweet_id":{"type":["string","null"]},"action":{"type":["string","null"]},"status":{"type":["string","null"]},"error":{"type":["string","null"]}},"required":["id","firedAt","ruleName","sourcePost","author","actionTaken","rule_id","rule_kind","fired_at","target_tweet_id","action","status","error"]},"MarketingXCompetitor":{"type":"object","properties":{"id":{"type":"string"},"handle":{"type":"string"},"display_name":{"type":["string","null"]},"memo":{"type":["string","null"]},"followers_count":{"type":"integer"},"posts_per_day":{"type":["number","null"]},"added_at":{"type":"string"},"displayName":{"type":"string"},"followers":{"type":"integer"},"postsPerWeek":{"type":"number"},"engagementRate":{"type":"number"},"topPost":{"type":"object","properties":{"body":{"type":"string"},"likes":{"type":"integer"},"postedAt":{"type":"string"}},"required":["body","likes","postedAt"]},"addedAt":{"type":"string"}},"required":["id","handle","display_name","memo","followers_count","posts_per_day","added_at","displayName","followers","postsPerWeek","engagementRate","topPost","addedAt"]},"MarketingIntegration":{"type":"object","properties":{"provider":{"type":"string","enum":["meta","x","ga4","search_console","resend","sendgrid","supabase_email"]},"status":{"type":"string"},"config":{},"updated_at":{"type":["string","null"]}},"required":["provider","status","updated_at"]},"MarketingBrand":{"type":"object","properties":{"logoUrl":{"type":["string","null"]},"primaryColor":{"type":["string","null"]},"secondaryColor":{"type":["string","null"]},"ngWords":{"type":"array","items":{"type":"string"}},"defaultHashtags":{"type":"array","items":{"type":"string"}},"defaultSignature":{"type":["string","null"]},"updatedAt":{"type":["string","null"]}},"required":["logoUrl","primaryColor","secondaryColor","ngWords","defaultHashtags","defaultSignature","updatedAt"]},"MarketingAsset":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"kind":{"type":"string","enum":["image","video","gif","logo","icon","banner"]},"mime_type":{"type":["string","null"]},"r2_key":{"type":"string"},"public_url":{"type":["string","null"]},"thumbnail_url":{"type":["string","null"]},"width":{"type":["integer","null"]},"height":{"type":["integer","null"]},"byte_size":{"type":["integer","null"]},"duration_seconds":{"type":["integer","null"]},"tags":{"type":"array","items":{"type":"string"}},"alt_text":{"type":["string","null"]},"usage_count":{"type":"integer"},"uploaded_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":"string"}},"required":["id","name","kind","mime_type","r2_key","public_url","width","height","byte_size","duration_seconds","tags","alt_text","usage_count","uploaded_by","created_at"]},"MarketingNotification":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"kind":{"type":"string","enum":["x_post_failed","newsletter_failed","campaign_start","campaign_end","automation_fired","integration_error"]},"title":{"type":"string"},"body":{"type":["string","null"]},"severity":{"type":"string","enum":["info","warning","error","success"]},"read_at":{"type":["string","null"]},"link":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","user_id","kind","title","body","severity","read_at","link","created_at"]},"MarketingActivityLog":{"type":"object","properties":{"id":{"anyOf":[{"type":"integer"},{"type":"string"}]},"user_id":{"type":["string","null"],"format":"uuid"},"action":{"type":"string"},"target_kind":{"type":["string","null"]},"target_id":{"type":["string","null"]},"detail":{},"created_at":{"type":"string"}},"required":["id","user_id","action","target_kind","target_id","created_at"]},"MarketingCampaign":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"objective":{"type":["string","null"]},"status":{"type":"string"},"start_date":{"type":"string"},"end_date":{"type":["string","null"]},"budget_minor":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"null"}]},"channels":{"type":"array","items":{"type":"string"}},"target_kpis":{},"tags":{"type":"array","items":{"type":"string"}},"created_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","description","objective","status","start_date","end_date","budget_minor","channels","tags","created_by","created_at","updated_at"]},"MarketingCampaignItem":{"type":"object","properties":{"campaign_id":{"type":"string","format":"uuid"},"item_kind":{"type":"string","enum":["instagram_post","x_post","article","ad","newsletter"]},"item_id":{"type":"string"},"linked_at":{"type":"string"}},"required":["campaign_id","item_kind","item_id","linked_at"]},"MarketingCampaignDetail":{"allOf":[{"$ref":"#/components/schemas/MarketingCampaign"},{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/MarketingCampaignItem"}}},"required":["items"]}]},"MarketingCampaignMetrics":{"type":"object","properties":{"campaign_id":{"type":"string","format":"uuid"},"totals":{"type":"object","properties":{"articles":{"type":"integer"},"ads":{"type":"integer"},"x_posts":{"type":"integer"},"instagram_posts":{"type":"integer"},"newsletters":{"type":"integer"}},"required":["articles","ads","x_posts","instagram_posts","newsletters"]},"pv":{"type":"integer"},"ad_impressions":{"type":"integer"},"ad_clicks":{"type":"integer"},"ctr":{"type":"number"},"x_impressions":{"type":"integer"},"x_likes":{"type":"integer"},"newsletters_sent":{"type":"integer"}},"required":["campaign_id","totals","pv","ad_impressions","ad_clicks","ctr","x_impressions","x_likes","newsletters_sent"]},"MarketingAnalyticsSummary":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"totalPv":{"type":"integer"},"totalImpressions":{"type":"integer"},"totalClicks":{"type":"integer"},"ctr":{"type":"number"},"newsletters_sent":{"type":"integer"},"posts_published":{"type":"integer"},"campaigns_active":{"type":"integer"}},"required":["from","to","totalPv","totalImpressions","totalClicks","ctr","newsletters_sent","posts_published","campaigns_active"]},"MarketingAnalyticsArticleRow":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":["string","null"]},"title":{"type":"string"},"category":{"type":["string","null"]},"author_name":{"type":["string","null"]},"published_at":{"type":["string","null"]},"pv":{"type":"integer"},"pv_diff_pct":{"type":"number"}},"required":["id","slug","title","category","author_name","published_at","pv","pv_diff_pct"]},"MarketingAnalyticsAdRow":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"start_date":{"type":["string","null"]},"end_date":{"type":["string","null"]},"impressions":{"type":"integer"},"clicks":{"type":"integer"},"ctr":{"type":"number"},"days_total":{"type":"integer"},"days_elapsed":{"type":"integer"},"progress":{"type":"number"},"daily":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"clicks":{"type":"integer"}},"required":["date","clicks"]}}},"required":["id","name","status","start_date","end_date","impressions","clicks","ctr","days_total","days_elapsed","progress","daily"]},"MarketingAnalyticsCrossChannelRow":{"type":"object","properties":{"channel":{"type":"string"},"posts":{"type":"integer"},"impressions":{"type":"integer"},"likes":{"type":"integer"},"clicks":{"type":"integer"},"pv":{"type":"integer"}},"required":["channel","posts","impressions","likes","clicks","pv"]},"MarketingContentPoolItem":{"type":"object","properties":{"kind":{"type":"string","enum":["article","instagram_post","x_post","ad","newsletter","asset"]},"id":{"type":"string"},"title":{"type":"string"},"status":{"type":["string","null"]},"thumbnail_url":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"meta":{"type":"object","additionalProperties":{}}},"required":["kind","id","title","status","thumbnail_url","updated_at"]},"MarketingCalendarEvent":{"type":"object","properties":{"kind":{"type":"string","enum":["x_post","article","ad","newsletter","instagram_post"]},"id":{"type":"string"},"title":{"type":"string"},"status":{"type":["string","null"]},"channel":{"type":"string","enum":["x","article","ad","newsletter","instagram"]},"at":{"type":"string"}},"required":["kind","id","title","status","channel","at"]},"MarketingCalendarDay":{"type":"object","properties":{"date":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/MarketingCalendarEvent"}}},"required":["date","items"]},"MarketingCalendarResponse":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"days":{"type":"array","items":{"$ref":"#/components/schemas/MarketingCalendarDay"}}},"required":["from","to","days"]},"MarketingArticleCategory":{"type":"object","properties":{"code":{"type":"string"},"label":{"type":"string"},"description":{"type":["string","null"]},"sort_order":{"type":"integer"},"is_deleted":{"type":"boolean"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["code","label","description","sort_order","is_deleted","created_at","updated_at"]},"OwnerParkingLot":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":["string","null"]},"status":{"type":["string","null"]},"total_spaces":{"type":["integer","null"]},"structure":{"type":["string","null"]},"created_at":{"type":["string","null"]}},"required":["id","name","address","status","total_spaces","structure","created_at"]},"OwnerSearchParkingLot":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"has_owner":{"type":"boolean"}},"required":["id","name","address","lat","lng","has_owner"]},"OwnerApplication":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"owner_id":{"type":["string","null"],"format":"uuid"},"owner_name":{"type":"string"},"owner_email":{"type":"string"},"company_name":{"type":["string","null"]},"parking_lot_id":{"type":"string","format":"uuid"},"proof_asset_id":{"type":["string","null"],"format":"uuid"},"additional_notes":{"type":["string","null"]},"status":{"type":"string"},"reviewed_at":{"type":["string","null"]},"reject_reason":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","owner_id","owner_name","owner_email","company_name","parking_lot_id","proof_asset_id","additional_notes","status","reviewed_at","reject_reason","created_at"]},"OwnerReview":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"parking_lot_id":{"type":"string","format":"uuid"},"user_name":{"type":"string"},"rating":{"type":"integer","minimum":1,"maximum":5},"comment":{"type":["string","null"]},"status":{"type":"string"},"owner_reply":{"type":["string","null"]},"owner_replied_at":{"type":["string","null"]},"owner_replied_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"parking_lot":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"]}},"required":["id","parking_lot_id","user_name","rating","comment","status","owner_reply","owner_replied_at","owner_replied_by","created_at","updated_at","parking_lot"]},"OwnerBoost":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"owner_id":{"type":"string","format":"uuid"},"parking_lot_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"credit_per_impression":{"type":["integer","null"]},"daily_budget":{"type":["integer","null"]},"total_budget":{"type":["integer","null"]},"started_at":{"type":["string","null"]},"ended_at":{"type":["string","null"]},"impressions":{"type":["integer","null"]},"clicks":{"type":["integer","null"]},"sessions":{"type":["integer","null"]},"status":{"type":["string","null"]},"created_at":{"type":["string","null"]}},"required":["id","owner_id","parking_lot_id","name","credit_per_impression","daily_budget","total_budget","started_at","ended_at","impressions","clicks","sessions","status","created_at"]},"OwnerCreditTxn":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"owner_id":{"type":"string","format":"uuid"},"type":{"type":"string"},"amount":{"type":"integer"},"balance_after":{"type":"integer"},"description":{"type":["string","null"]},"boost_id":{"type":["string","null"],"format":"uuid"},"created_at":{"type":"string"}},"required":["id","owner_id","type","amount","balance_after","description","boost_id","created_at"]}},"parameters":{}},"paths":{"/v1/owner/parking-lots/mine":{"get":{"tags":["owner","parking-lots"],"summary":"自分がオーナー権限を持つ駐車場一覧","description":"### 用途\nログイン中オーナーが `parking_lot_owners` リンクを通じて所有している駐車場の一覧を返す。\nオーナーポータルのトップ画面・サイドバーの駐車場切替ドロップダウンで利用される基幹 API。\n\n### オーナーポータルでの使用タイミング\n- ダッシュボード初回表示でオーナーが管理する物件サマリを描画するとき\n- 「自分の駐車場」一覧画面のテーブル表示・ページング操作時\n- レビュー / ブースト画面の駐車場フィルタードロップダウンを構築するとき\n\n### 認証・認可\n`requireOwner` ミドルウェアで Bearer JWT を検証し、`owners` テーブルから `status='active'` の owner 行を引き当てる。\n未設定 (`user_id IS NULL`) や `reviewing`/`suspended` の owner は 403。\n返却対象は `parking_lot_owners.owner_id = current_owner_id()` に厳密に絞られる。\n\n### 挙動・制約\n- `withOwnerContext` が `SET LOCAL ROLE authenticated` + `jwt.claims` を発行し、RLS で物理ガードする\n- アプリ層でも `WHERE plo.owner_id = ${ownerId}` を並列に効かせる二重ガード\n- 並び順は `parking_lots.created_at DESC NULLS LAST` 固定\n- ページングは `PageQuerySchema`（page / limit）\n\n### 関連\n- `GET /v1/owner/parking-lots/mine/{id}` — 1 件詳細\n- `PATCH /v1/owner/parking-lots/mine/{id}` — 編集\n- `POST /v1/owner/parking-lots/mine` — 新規申請（`status='pending'` で admin 審査待ち）\n- `GET /v1/owner/parking-lots/search` — オーナー申請対象探索","parameters":[{"schema":{"type":"string","pattern":"^\\d+$","description":"1 はじまりのページ番号","examples":["1"]},"required":false,"name":"page","in":"query"},{"schema":{"type":"string","pattern":"^\\d+$","description":"1 ページあたりの件数（最大 2000）","examples":["20"]},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"一覧","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/OwnerParkingLot"}},"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0}},"required":["items","page","limit","total"]}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]},"post":{"tags":["owner","parking-lots"],"summary":"駐車場を新規登録（status='pending' で admin 審査待ち）","description":"### 用途\nオーナーが管理対象として新規駐車場を登録する。admin の承認を経て公開される運用のため、\n本 API では `status='pending'` で作成し、同時に `parking_lot_owners` リンクを張る。\n\n### オーナーポータルでの使用タイミング\n- 「駐車場を追加」ウィザード最終ステップの送信時\n- 申請後すぐにダッシュボードへ戻り「審査中」バッジを表示するため\n\n### 認証・認可\n`requireOwner`。作成と同時にリクエスト元 owner を `parking_lot_owners` に紐付ける。\n他オーナーが既存駐車場を申請するルートは `/v1/owner/applications` 側を使う。\n\n### 挙動・制約\n- `withOwnerContext` のトランザクション内で `parking_lots` INSERT → `parking_lot_owners` INSERT を順に実行\n- どちらかが失敗すれば自動 ROLLBACK（部分作成を残さない）\n- `parking_lot_owners` は `(parking_lot_id, owner_id)` UNIQUE 競合時に DO NOTHING（冪等）\n- admin が却下した場合は `parking_lots` 削除または `status='rejected'` で運用\n\n### 関連\n- `GET /v1/owner/parking-lots/mine` — 自分の登録駐車場一覧（`status='pending'` を含む）\n- `POST /v1/owner/applications` — 既存駐車場のオーナー権利を申請する別フロー","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"address":{"type":["string","null"]}},"required":["name"]}}}},"responses":{"200":{"description":"作成済み","content":{"application/json":{"schema":{"type":"object","additionalProperties":{}}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]}},"/v1/owner/parking-lots/mine/{id}":{"get":{"tags":["owner","parking-lots"],"summary":"自分の駐車場の詳細","description":"### 用途\nオーナーが所有する単一駐車場の全カラムを返す。編集画面の初期値表示や、\nブースト作成時の物件メタ表示で使用する。\n\n### オーナーポータルでの使用タイミング\n- 駐車場詳細画面に遷移したとき\n- 「駐車場を編集」モーダルを開いたとき（最新値で再取得）\n- ブースト作成ウィザードで対象駐車場の住所・台数を確認するとき\n\n### 認証・認可\n`requireOwner`。`parking_lot_owners` を `parking_lot_id` × `owner_id` で照合し、\nリンクが無ければ `owner_not_lot_owner` を返す。RLS と並ぶ二重ガード。\n\n### 挙動・制約\n- 駐車場行が無い場合は `parking_lot_not_found`\n- レスポンスは `parking_lots` の全カラムを passthrough（`z.record(z.any())`）\n- `withOwnerContext` 内のトランザクションで権限チェックと SELECT を実行\n\n### 関連\n- `GET /v1/owner/parking-lots/mine` — 一覧\n- `PATCH /v1/owner/parking-lots/mine/{id}` — 編集","parameters":[{"schema":{"type":"string","format":"uuid","examples":["00000000-0000-0000-0000-000000000000"]},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"詳細","content":{"application/json":{"schema":{"type":"object","additionalProperties":{}}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]},"patch":{"tags":["owner","parking-lots"],"summary":"自分の駐車場を編集","description":"### 用途\nオーナー自身の駐車場の編集可能カラムを部分更新する。住所・台数・構造・営業情報など。\n業務上のステータス変更や審査関連カラムは触れない。\n\n### オーナーポータルでの使用タイミング\n- 「駐車場を編集」モーダルでフォーム送信したとき\n- マップ上のピン位置補正など個別カラム単位の更新\n\n### 認証・認可\n`requireOwner`。更新前に `parking_lot_owners` で所有権を再確認し、\n他オーナーの駐車場 ID を指定すると `owner_not_lot_owner` を返す。\n\n### 挙動・制約\n- `id` / `status` / `created_at` / `deleted_at` は禁則カラムとしてサーバー側で除外\n- 残りはすべて passthrough。バリデーションは DB 制約に委ねる\n- 空ボディの場合は更新せず現行値をそのまま返す（冪等）\n- RLS + アプリ層 WHERE による二重ガード\n\n### 関連\n- `GET /v1/owner/parking-lots/mine/{id}` — 詳細取得\n- `POST /v1/owner/parking-lots/mine` — 新規登録","parameters":[{"schema":{"type":"string","format":"uuid","examples":["00000000-0000-0000-0000-000000000000"]},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"更新後","content":{"application/json":{"schema":{"type":"object","additionalProperties":{}}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]}},"/v1/owner/parking-lots/search":{"get":{"tags":["owner","parking-lots"],"summary":"全駐車場検索（オーナー申請の対象探し用、公開情報のみ）","description":"### 用途\nParky に登録済みの全駐車場から、オーナー申請をかけたい物件を探すための検索。\n返すのは公開情報のみ（id / 名称 / 住所 / 緯度経度 / `has_owner` フラグ）。\n\n### オーナーポータルでの使用タイミング\n- 「既存の駐車場のオーナー権限を申請する」ウィザードの検索ボックス\n- 自分の物件がすでに登録されていないか名称・住所で確認するとき\n- 申請可否（`has_owner=false`）の事前判定\n\n### 認証・認可\n`requireOwner`（オーナーログインが前提）。ただし返却データは公開情報のみ。\n`has_owner` の集計を正しく行うため、このルートに限り service-role 接続 (`getSql`) で\nRLS をバイパスする（`parking_lot_owners` を全件参照する必要があるため）。\n\n### 挙動・制約\n- `q` で `name` / `address` の ILIKE 部分一致\n- `has_owner` は `EXISTS (SELECT 1 FROM parking_lot_owners ...)` で boolean を返す\n- 並び順は `name ASC` 固定\n- 機微カラム（料金体系・運用メモ・契約情報など）は返さない\n\n### 関連\n- `POST /v1/owner/applications` — ヒットした駐車場に対するオーナー申請を作成","parameters":[{"schema":{"type":"string","pattern":"^\\d+$","description":"1 はじまりのページ番号","examples":["1"]},"required":false,"name":"page","in":"query"},{"schema":{"type":"string","pattern":"^\\d+$","description":"1 ページあたりの件数（最大 2000）","examples":["20"]},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"q","in":"query"}],"responses":{"200":{"description":"一覧","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/OwnerSearchParkingLot"}},"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0}},"required":["items","page","limit","total"]}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]}},"/v1/owner/applications/mine":{"get":{"tags":["owner","applications"],"summary":"自分が出したオーナー申請の一覧","description":"### 用途\nログイン中オーナーが過去に提出した「既存駐車場へのオーナー権限申請」を一覧で返す。\nステータス（`new` / `in_progress` / `approved` / `rejected`）と却下理由を含む。\n\n### オーナーポータルでの使用タイミング\n- 「申請履歴」画面の初期表示・ページング操作\n- ダッシュボードでの「審査中の申請」件数バッジ\n- 却下された申請の `reject_reason` 確認 → 再申請判断\n\n### 認証・認可\n`requireOwner`。`owner_applications.owner_id = current_owner_id()` に厳密にスコープされる。\n他オーナーの申請は一切返さない。\n\n### 挙動・制約\n- 並び順は `created_at DESC` 固定\n- ステータスは admin 側 `/v1/admin/owner-applications/{id}/approve` で `approved` に遷移\n- 申請承認時に Supabase Auth の `inviteUserByEmail` がフックされる\n- ページングは `PageQuerySchema`\n\n### 関連\n- `POST /v1/owner/applications` — 新規申請\n- `GET /v1/owner/parking-lots/search` — 申請対象の駐車場を探す","parameters":[{"schema":{"type":"string","pattern":"^\\d+$","description":"1 はじまりのページ番号","examples":["1"]},"required":false,"name":"page","in":"query"},{"schema":{"type":"string","pattern":"^\\d+$","description":"1 ページあたりの件数（最大 2000）","examples":["20"]},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"一覧","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/OwnerApplication"}},"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0}},"required":["items","page","limit","total"]}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]}},"/v1/owner/applications":{"post":{"tags":["owner","applications"],"summary":"オーナー申請を作成（proof_asset_id 必須）","description":"### 用途\n既存駐車場に対し「自分がオーナーである」ことの審査申請を提出する。\n書面証明（登記簿・契約書スキャン等）を `proof_asset_id` で必ず添付する。\n\n### オーナーポータルでの使用タイミング\n- 「駐車場のオーナー権限を申請」ウィザード最終ステップの送信時\n- ステップ前に `/v1/storage` で書面 PDF をアップロードして asset id を取得 → このAPIに渡す\n\n### 認証・認可\n`requireOwner`。作成される `owner_applications.owner_id` はリクエスト元 owner で固定される。\n`owner_name` / `owner_email` / `company_name` は申請書面と照合するために別途入力。\n\n### 挙動・制約\n- 同じ owner × parking_lot で `status IN ('new', 'in_progress')` の申請が既にある場合は\n  `owner_application_duplicate` を返す（重複申請禁止）\n- 初期 `status='new'` で作成。admin 側で `in_progress` → `approved` / `rejected` に遷移\n- `approved` 時に admin が招待メール（`inviteUserByEmail`）を発行し、\n  オーナーは `/v1/owner/invitations/accept` で初回パスワードを設定する\n\n### 関連\n- `GET /v1/owner/applications/mine` — 自分の申請一覧\n- `POST /v1/owner/invitations/accept` — 承認後の初回セットアップ","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"parking_lot_id":{"type":"string","format":"uuid","examples":["00000000-0000-0000-0000-000000000000"]},"proof_asset_id":{"type":"string","format":"uuid","examples":["00000000-0000-0000-0000-000000000000"]},"owner_name":{"type":"string","minLength":1},"owner_email":{"type":"string","format":"email"},"company_name":{"type":["string","null"]},"additional_notes":{"type":["string","null"]}},"required":["parking_lot_id","proof_asset_id","owner_name","owner_email"]}}}},"responses":{"200":{"description":"作成済み","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OwnerApplication"}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]}},"/v1/owner/reviews/mine":{"get":{"tags":["owner","reviews"],"summary":"自分の駐車場のレビュー一覧","description":"### 用途\nオーナー所有の駐車場に投稿されたユーザーレビューを一覧表示する。\n返信状況・ステータス・対象駐車場でフィルタ可能で、未返信レビューのオーナー対応導線を担う。\n\n### オーナーポータルでの使用タイミング\n- 「レビュー管理」画面の初期表示（`reply_state=unreplied` で未対応のみ）\n- 駐車場詳細画面の「最新レビュー」ウィジェット\n- 公開／非公開ステータスでの絞り込み表示\n\n### 認証・認可\n`requireOwner`。`parking_reviews` を `parking_lot_owners` で INNER JOIN し、\n`plo.owner_id = current_owner_id()` で厳格に絞り込む。\n他オーナーの駐車場レビューは構造的に取得できない。\n\n### 挙動・制約\n- `parking_lot_id` 指定で単一物件に絞り込み（自分が所有する物件 ID のみ意味を持つ）\n- `status` でレビューの承認状態フィルタ\n- `reply_state=unreplied`: `owner_reply IS NULL` / `replied`: `owner_reply IS NOT NULL`\n- 並び順は `created_at DESC` 固定\n- レスポンスに `parking_lot.{id,name}` を埋め込む（一覧で物件名を表示するため）\n\n### 関連\n- `POST /v1/owner/reviews/{reviewId}/reply` — レビューへの返信投稿・上書き・削除","parameters":[{"schema":{"type":"string","pattern":"^\\d+$","description":"1 はじまりのページ番号","examples":["1"]},"required":false,"name":"page","in":"query"},{"schema":{"type":"string","pattern":"^\\d+$","description":"1 ページあたりの件数（最大 2000）","examples":["20"]},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid","examples":["00000000-0000-0000-0000-000000000000"]},"required":false,"name":"parking_lot_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","enum":["all","unreplied","replied"]},"required":false,"name":"reply_state","in":"query"}],"responses":{"200":{"description":"一覧","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/OwnerReview"}},"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0}},"required":["items","page","limit","total"]}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]}},"/v1/owner/reviews/{reviewId}/reply":{"post":{"tags":["owner","reviews"],"summary":"レビューに返信（上書き / null で削除）","description":"### 用途\nオーナー所有駐車場のレビューに対するオーナー返信を作成・上書き・削除する。\n1 レビュー = 1 返信モデル。`parking_reviews.owner_reply` に文字列を保存し、投稿時刻と投稿者 owner_id も合わせて記録。\n\n### オーナーポータルでの使用タイミング\n- レビュー詳細モーダルの「返信を送信」ボタン\n- 既存返信の編集（同じエンドポイントに新しい本文を投げる）\n- 返信削除（`owner_reply: null` を送信）\n\n### 認証・認可\n`requireOwner`。`parking_reviews` × `parking_lot_owners` の INNER JOIN で\n対象レビューが自オーナー所有駐車場のものか検証し、外れていれば `owner_review_not_for_your_lot`。\n\n### 挙動・制約\n- `owner_reply` が文字列: `owner_replied_at = NOW()` / `owner_replied_by = current owner_id` を同時更新\n- `owner_reply` が `null`: `owner_replied_at` / `owner_replied_by` も NULL クリア（返信削除相当）\n- `updated_at` も常に NOW() で更新\n- レビュー本体（`rating` / `comment` / `status`）は変更しない\n- 該当レビューが消えていれば `not_found`\n\n### 関連\n- `GET /v1/owner/reviews/mine` — 一覧（未返信フィルタで対応待ちを抽出）","parameters":[{"schema":{"type":"string","format":"uuid","examples":["00000000-0000-0000-0000-000000000000"]},"required":true,"name":"reviewId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"owner_reply":{"type":["string","null"]}},"required":["owner_reply"]}}}},"responses":{"200":{"description":"更新後","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OwnerReview"}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]}},"/v1/owner/boosts":{"get":{"tags":["owner","boosts"],"summary":"自分のブースト一覧","description":"### 用途\nオーナーが自分の駐車場に対して設定しているブースト（有料の検索結果上位化）の一覧を返す。\n予算・配信状況（`status`）・累計インプレッション/クリック/セッションを含む運用ダッシュボード用データ。\n\n### オーナーポータルでの使用タイミング\n- 「ブースト管理」画面の初期表示・ページング\n- 駐車場別フィルタでの配信状況確認\n- 配信中（`status='active'`）／停止中（`paused` / `ended`）の切替表示\n\n### 認証・認可\n`requireOwner`。`boosts.owner_id = current_owner_id()` に固定スコープ。\nadmin 側 `/v1/admin/boosts` は全オーナー横断だが、本ルートは自分の owner_id 配下のみ。\n\n### 挙動・制約\n- `parking_lot_id` / `status` でフィルタ\n- 並び順は `created_at DESC` 固定\n- `credit_per_impression` / `daily_budget` / `total_budget` は NULL 許可（無制限運用）\n\n### 関連\n- `POST /v1/owner/boosts` — 新規作成\n- `PATCH /v1/owner/boosts/{id}` — 編集（停止 / 予算変更）\n- `GET /v1/owner/boosts/{id}/stats` — 配信統計とクレジット消費","parameters":[{"schema":{"type":"string","pattern":"^\\d+$","description":"1 はじまりのページ番号","examples":["1"]},"required":false,"name":"page","in":"query"},{"schema":{"type":"string","pattern":"^\\d+$","description":"1 ページあたりの件数（最大 2000）","examples":["20"]},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid","examples":["00000000-0000-0000-0000-000000000000"]},"required":false,"name":"parking_lot_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"一覧","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/OwnerBoost"}},"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0}},"required":["items","page","limit","total"]}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]},"post":{"tags":["owner","boosts"],"summary":"ブーストを作成","description":"### 用途\n指定駐車場に対する新しいブーストキャンペーンを登録する。クレジットを消費して検索結果に\n優先表示するための配信枠で、予算とインプレッション単価を後から PATCH で調整できる。\n\n### オーナーポータルでの使用タイミング\n- 「ブースト作成」ウィザード最終ステップの送信時\n- 駐車場詳細画面の「上位表示する」CTA\n\n### 認証・認可\n`requireOwner`。送信された `parking_lot_id` が自オーナー所有か `parking_lot_owners` で照合し、\n外れていれば `owner_not_lot_owner`。`owner_id` はサーバー側で強制上書き（クライアント指定は無視）。\n\n### 挙動・制約\n- 配信開始時刻・予算等は body の passthrough で渡す（schema は最小限）\n- 作成時点では実際のクレジット引落しは発生しない（インプレッション発生時に `credit_transactions` で消費）\n- 残高不足ハンドリングはインプレッション発生フロー側の責務\n\n### 関連\n- `PATCH /v1/owner/boosts/{id}` — 予算・期間・状態の更新\n- `GET /v1/owner/credits/balance` — 事前残高確認","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"parking_lot_id":{"type":"string","format":"uuid","examples":["00000000-0000-0000-0000-000000000000"]},"name":{"type":"string","minLength":1}},"required":["parking_lot_id","name"]}}}},"responses":{"200":{"description":"作成済み","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OwnerBoost"}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]}},"/v1/owner/boosts/{id}":{"patch":{"tags":["owner","boosts"],"summary":"ブーストを更新","description":"### 用途\n既存ブーストの編集。配信停止（`status='paused'` / `'ended'`）・予算引き上げ・\n単価調整・配信期間変更などの運用操作を一括で受け付ける。\n\n### オーナーポータルでの使用タイミング\n- 「停止」「再開」ボタンの押下\n- 予算引き上げモーダルの送信時\n- インプレッション単価の調整スライダー操作\n\n### 認証・認可\n`requireOwner`。更新前に `boosts` テーブルで `id × owner_id` を再確認し、\n他オーナーのブーストは `owner_boost_not_found`（存在隠蔽）。\n\n### 挙動・制約\n- 禁則カラム: `id` / `owner_id` / `created_at` / `impressions` / `clicks` / `sessions`（集計値はサーバ側のみ更新）\n- 残りはすべて passthrough。バリデーションは DB 制約に委ねる\n- 空ボディは現行値を返して終わる（冪等）\n\n### 関連\n- `GET /v1/owner/boosts/{id}/stats` — 集計値の最新値取得","parameters":[{"schema":{"type":"string","format":"uuid","examples":["00000000-0000-0000-0000-000000000000"]},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"更新後","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OwnerBoost"}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]}},"/v1/owner/boosts/{id}/stats":{"get":{"tags":["owner","boosts"],"summary":"ブーストの統計（インプレッション・クリック・セッション）","description":"### 用途\n単一ブーストの累計配信実績とクレジット消費量を返す。`boosts` テーブル上のカウンタと、\n`credit_transactions` の `boost_id` 紐付け消費（負の `amount`）を SUM して算出する。\n\n### オーナーポータルでの使用タイミング\n- ブースト詳細画面のサマリカード表示\n- ダッシュボードの「配信中ブースト」カード（CTR や予算消化率の計算）\n- 配信終了後のレポート表示\n\n### 認証・認可\n`requireOwner`。`boosts.id × owner_id` 一致を必須にし、外れていれば `owner_boost_not_found`。\n他オーナーのブースト統計は構造的に取得不可。\n\n### 挙動・制約\n- `credit_consumed` は `SUM(-amount)` over `credit_transactions WHERE boost_id = ? AND amount < 0`\n- `impressions` / `clicks` / `sessions` が NULL の場合は 0 を返す（COALESCE）\n- 配信が無いブーストでも 0 埋めで返却（UI 側の null チェック不要）\n\n### 関連\n- `GET /v1/owner/credits/transactions` — クレジット消費の明細（boost_id で逆引き可）","parameters":[{"schema":{"type":"string","format":"uuid","examples":["00000000-0000-0000-0000-000000000000"]},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"統計","content":{"application/json":{"schema":{"type":"object","properties":{"boost_id":{"type":"string","format":"uuid"},"impressions":{"type":"integer"},"clicks":{"type":"integer"},"sessions":{"type":"integer"},"credit_consumed":{"type":"integer"}},"required":["boost_id","impressions","clicks","sessions","credit_consumed"]}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]}},"/v1/owner/credits/balance":{"get":{"tags":["owner","credits"],"summary":"クレジット残高","description":"### 用途\nログイン中オーナーのクレジット残高（`balance`）と累計購入額・累計消費額を返す。\nブースト課金の財布。`owner_credits` テーブル 1 行を引いて返すだけのシンプルな参照。\n\n### オーナーポータルでの使用タイミング\n- ヘッダーの残高インジケータ表示\n- ダッシュボードの「クレジット残高」カード\n- ブースト作成前の残高チェック（不足ならチャージ導線へ誘導）\n\n### 認証・認可\n`requireOwner`。`owner_credits.owner_id = current_owner_id()` に厳密スコープ。\n他オーナーの残高は一切返さない。\n\n### 挙動・制約\n- `owner_credits` 行が未生成のオーナーでも 200 を返し、すべて 0 のレスポンスを合成（UI 側の null チェック不要）\n- 残高更新は `credit_transactions` 投入時のトリガで `balance_after` から伝播する設計\n\n### 関連\n- `GET /v1/owner/credits/transactions` — 残高変動の明細\n- `POST /v1/owner/credits/checkout-session` — Stripe チャージ（Phase 2）","responses":{"200":{"description":"残高","content":{"application/json":{"schema":{"type":"object","properties":{"owner_id":{"type":"string","format":"uuid"},"balance":{"type":"integer"},"total_purchased":{"type":"integer"},"total_consumed":{"type":"integer"}},"required":["owner_id","balance","total_purchased","total_consumed"]}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]}},"/v1/owner/credits/transactions":{"get":{"tags":["owner","credits"],"summary":"クレジット取引履歴","description":"### 用途\nクレジット残高の変動明細。チャージ（正の `amount`）・ブースト消費（負の `amount`）・運営調整を\n時系列で返し、`balance_after` で各時点の残高遷移を追跡できる。\n\n### オーナーポータルでの使用タイミング\n- 「クレジット明細」画面の初期表示・ページング\n- ブースト詳細から逆引き（`boost_id` でフィルタ表示する想定）\n- 経理向け CSV エクスポート前のプレビュー\n\n### 認証・認可\n`requireOwner`。`credit_transactions.owner_id = current_owner_id()` で厳密スコープ。\n\n### 挙動・制約\n- 並び順は `created_at DESC` 固定\n- `boost_id` は消費取引のみ非 NULL\n- `type` は `purchase` / `consume` / `adjust` などのコード値\n- ページングは `PageQuerySchema`\n\n### 関連\n- `GET /v1/owner/credits/balance` — サマリ残高\n- `GET /v1/owner/boosts/{id}/stats` — 個別ブーストの消費合計","parameters":[{"schema":{"type":"string","pattern":"^\\d+$","description":"1 はじまりのページ番号","examples":["1"]},"required":false,"name":"page","in":"query"},{"schema":{"type":"string","pattern":"^\\d+$","description":"1 ページあたりの件数（最大 2000）","examples":["20"]},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"履歴","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/OwnerCreditTxn"}},"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0}},"required":["items","page","limit","total"]}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]}},"/v1/owner/credits/checkout-session":{"post":{"tags":["owner","credits"],"summary":"クレジット購入用 Stripe Checkout セッション URL（Phase 2 で実装、現状はスタブ）","description":"### 用途\nクレジット購入用の Stripe Checkout セッションを発行する想定のエンドポイント。\n**現状はスタブで、常に 503 `service_unavailable` を返す**。本実装は Phase 2 で BFF に\nStripe SDK を導入してから完成させる。\n\n### オーナーポータルでの使用タイミング\n- 「クレジットを購入」モーダルの「Stripe で支払う」ボタン押下時\n- 残高不足アラートからのチャージ導線\n\n### 認証・認可\n`requireOwner`。実装後はリクエスト元 owner で `client_reference_id` を発行し、\nwebhook 受信時に `credit_transactions` へ入金記録する設計。\n\n### 挙動・制約\n- 現状: 常に 503 `service_unavailable` を返却\n- 将来: `credits` から `price_id` × `quantity` を解決し、Stripe Checkout Session URL を返す\n- 入金確定は webhook 経由（このエンドポイントでは残高変動を起こさない）\n\n### 関連\n- `GET /v1/owner/credits/balance` — チャージ後の残高確認\n- `GET /v1/owner/credits/transactions` — チャージ反映後の明細確認","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"credits":{"type":"integer","exclusiveMinimum":0}},"required":["credits"]}}}},"responses":{"503":{"description":"Stripe 未実装","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","request_id"]}},"required":["error"]}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]}},"/v1/owner/invitations/accept":{"post":{"tags":["owner","invitations"],"summary":"招待メールから初回パスワードを設定し、オーナーを active 化する","description":"### 用途\nadmin がオーナー申請を承認した際に Supabase Auth から送られる招待メールを起点に、\nオーナー本人が初回パスワードを設定し、`owners.status` を `active` に遷移させる初回セットアップ API。\n\n### オーナーポータルでの使用タイミング\n- 招待メール内リンクから遷移した `InvitationAcceptPage` での「パスワード設定」フォーム送信\n- Supabase JS が確立したセッション（招待トークン由来）を保持した状態でこのエンドポイントを呼ぶ\n\n### 認証・認可\n**`requireOwner` は使えない**（`status='active'` を要求するため、未受諾の owner は弾かれる）。\n代わりに自前で Supabase JWT を `verifySupabaseJwt` で検証 → `auth.uid` を取得し、\n`owners.user_id = auth.uid` の 1:1 マッチングでアプリ層が認可を担保する。\n\n### 挙動・制約\n- RLS 下の `withOwnerContext` も使えない（`current_owner_id()` が未 active owner では NULL）\n- そのため `getSql`（service-role 接続）で動かす\n- 紐付き owner 行が無ければ `owner_invite_no_link`\n- Supabase Auth の password 設定が失敗した場合は `owner_invite_password_failed`\n- `owners.status` 更新は `<> 'active'` ガード付き（既に active なら何もしない＝冪等）\n- 成功後は通常のログインフロー / `requireOwner` で他のオーナー API にアクセス可能になる\n\n### 関連\n- `POST /v1/admin/owner-applications/{id}/approve` — 招待メールを発行する admin 側\n- `GET /v1/owner/parking-lots/mine` — active 化後の最初の遷移先候補","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"password":{"type":"string","minLength":8,"maxLength":128}},"required":["password"]}}}},"responses":{"200":{"description":"セットアップ完了","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"owner_id":{"type":"string","format":"uuid"}},"required":["ok","owner_id"]}}}}},"x-channels":["portal-owner"],"x-badges":[{"name":"portal-owner","color":"#22c55e"}]}}},"webhooks":{}}