{"openapi":"3.1.0","info":{"title":"flow-api","version":"0.1.0"},"paths":{"/healthz":{"get":{"tags":["meta"],"summary":"Healthz","description":"Liveness + dependency check. 200 when the service can serve requests.","operationId":"healthz_healthz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/auth/register":{"post":{"tags":["auth"],"summary":"Register","operationId":"register_v1_auth_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/login":{"post":{"tags":["auth"],"summary":"Login","operationId":"login_v1_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/refresh":{"post":{"tags":["auth"],"summary":"Refresh","operationId":"refresh_v1_auth_refresh_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/logout":{"post":{"tags":["auth"],"summary":"Logout Endpoint","operationId":"logout_endpoint_v1_auth_logout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Response Logout Endpoint V1 Auth Logout Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/me":{"get":{"tags":["auth"],"summary":"Me","operationId":"me_v1_auth_me_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["auth"],"summary":"Update Me Endpoint","operationId":"update_me_endpoint_v1_auth_me_patch","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMeIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/admin/logs":{"get":{"tags":["admin"],"summary":"List Logs","description":"Return recent log entries, newest first.","operationId":"list_logs_v1_admin_logs_get","parameters":[{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"server|client","title":"Source"},"description":"server|client"},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id"}},{"name":"request_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Request Id"}},{"name":"level","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Level"}},{"name":"since_seconds","in":"query","required":false,"schema":{"type":"integer","maximum":86400,"minimum":0,"default":3600,"title":"Since Seconds"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":200,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response List Logs V1 Admin Logs Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/admin/logs/stats":{"get":{"tags":["admin"],"summary":"Log Stats","operationId":"log_stats_v1_admin_logs_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Log Stats V1 Admin Logs Stats Get"}}}}}}},"/v1/client/logs":{"post":{"tags":["client"],"summary":"Ingest Logs","description":"Ingest a batch of client log entries. Requires auth.","operationId":"ingest_logs_v1_client_logs_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientLogBatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Ingest Logs V1 Client Logs Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/client/logs/anonymous":{"post":{"tags":["client"],"summary":"Ingest Logs Anonymous","description":"Accept logs from users who haven't managed to log in yet — useful for\ndiagnosing the very register/login problem we're chasing.\n\nTries to decode the Authorization header if present, but doesn't require\nit. The entries land with user_id=null so the user can be matched later\nby request_id or device fingerprint if needed.","operationId":"ingest_logs_anonymous_v1_client_logs_anonymous_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientLogBatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Ingest Logs Anonymous V1 Client Logs Anonymous Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/client/logs/mine":{"get":{"tags":["client"],"summary":"My Logs","description":"Return recent log entries that belong to the calling user.","operationId":"my_logs_v1_client_logs_mine_get","parameters":[{"name":"since_seconds","in":"query","required":false,"schema":{"type":"integer","default":86400,"title":"Since Seconds"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":200,"title":"Limit"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response My Logs V1 Client Logs Mine Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AuthResponse":{"properties":{"user":{"$ref":"#/components/schemas/UserOut"},"tokens":{"$ref":"#/components/schemas/TokenPair"}},"type":"object","required":["user","tokens"],"title":"AuthResponse","description":"Combined register/login/refresh response."},"ClientLogBatch":{"properties":{"entries":{"items":{"$ref":"#/components/schemas/ClientLogEntry"},"type":"array","title":"Entries"},"app_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"App Version"},"device":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device"}},"type":"object","title":"ClientLogBatch"},"ClientLogEntry":{"properties":{"ts":{"type":"number","title":"Ts"},"level":{"type":"string","title":"Level","default":"info"},"event":{"type":"string","title":"Event"},"fields":{"type":"object","title":"Fields"}},"type":"object","required":["ts","event"],"title":"ClientLogEntry"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LoginIn":{"properties":{"email_or_username":{"type":"string","maxLength":320,"minLength":3,"title":"Email Or Username"},"password":{"type":"string","maxLength":128,"minLength":1,"title":"Password"}},"type":"object","required":["email_or_username","password"],"title":"LoginIn"},"RefreshIn":{"properties":{"refresh_token":{"type":"string","minLength":20,"title":"Refresh Token"}},"type":"object","required":["refresh_token"],"title":"RefreshIn"},"RegisterIn":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"username":{"type":"string","title":"Username"},"password":{"type":"string","maxLength":128,"minLength":10,"title":"Password"}},"type":"object","required":["email","username","password"],"title":"RegisterIn"},"TokenPair":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"access_token":{"type":"string","title":"Access Token"},"access_token_expires_at":{"type":"string","format":"date-time","title":"Access Token Expires At"},"refresh_token":{"type":"string","title":"Refresh Token"},"refresh_token_expires_at":{"type":"string","format":"date-time","title":"Refresh Token Expires At"},"token_type":{"type":"string","title":"Token Type","default":"Bearer"}},"type":"object","required":["user_id","access_token","access_token_expires_at","refresh_token","refresh_token_expires_at"],"title":"TokenPair"},"UpdateMeIn":{"properties":{"username":{"anyOf":[{"type":"string","maxLength":32,"minLength":3},{"type":"null"}],"title":"Username"},"password":{"anyOf":[{"type":"string","maxLength":128,"minLength":10},{"type":"null"}],"title":"Password"}},"type":"object","title":"UpdateMeIn"},"UserOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","format":"email","title":"Email"},"username":{"type":"string","title":"Username"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","email","username","created_at"],"title":"UserOut"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}