{"components":{"responses":{"BadRequest":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Bad request"},"NotFound":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource not found"},"Unauthorized":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Authentication required or invalid credentials"},"UserCreated":{"content":{"application/json":{"schema":{"properties":{"email":{"format":"email","type":"string"},"message":{"type":"string"},"user_id":{"format":"uuid","type":"string"}},"type":"object"}}},"description":"User created successfully"},"ValidationError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Validation error"}},"schemas":{"ApiEndpoint":{"properties":{"action":{"example":"show","type":"string"},"controller":{"example":"ExampleApp.UserController","type":"string"},"deprecated":{"default":false,"type":"boolean"},"description":{"nullable":true,"type":"string"},"discovered_at":{"format":"date-time","type":"string"},"http_method":{"enum":["GET","POST","PUT","DELETE","PATCH"],"type":"string"},"id":{"format":"uuid","type":"string"},"last_updated":{"format":"date-time","type":"string"},"path":{"example":"/api/v1/users/:id","type":"string"},"tags":{"items":{"type":"string"},"type":"array"}},"required":["id","path","http_method","controller","action","discovered_at","last_updated"],"type":"object"},"ApiTestResult":{"properties":{"api_endpoint_id":{"format":"uuid","type":"string"},"api_token_id":{"format":"uuid","type":"string"},"error_message":{"nullable":true,"type":"string"},"executed_at":{"format":"date-time","type":"string"},"id":{"format":"uuid","type":"string"},"request_headers":{"nullable":true,"type":"object"},"request_params":{"nullable":true,"type":"object"},"request_payload":{"nullable":true,"type":"object"},"response_body":{"nullable":true,"type":"object"},"response_headers":{"nullable":true,"type":"object"},"response_status":{"maximum":599,"minimum":100,"type":"integer"},"response_time_ms":{"minimum":0,"type":"integer"},"success":{"type":"boolean"}},"required":["id","api_endpoint_id","api_token_id","response_status","response_time_ms","executed_at","success"],"type":"object"},"ApiToken":{"properties":{"active":{"default":true,"type":"boolean"},"created_at":{"format":"date-time","type":"string"},"expires_at":{"format":"date-time","nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"last_used_at":{"format":"date-time","nullable":true,"type":"string"},"name":{"example":"My API Token","type":"string"},"permissions":{"example":["/api/v1/*","/api/v2/users"],"items":{"type":"string"},"type":"array"},"usage_count":{"default":0,"type":"integer"}},"required":["id","name","permissions","created_at","active"],"type":"object"},"CommunityDetail":{"description":"Detailed community information","properties":{"created_at":{"description":"Community creation timestamp","format":"date-time","type":"string"},"description":{"description":"Community description","nullable":true,"type":"string"},"id":{"description":"Community UUID","format":"uuid","type":"string"},"is_manager":{"description":"Whether current user is a manager","type":"boolean"},"is_member":{"description":"Whether current user is a member","type":"boolean"},"joined_at":{"description":"When user joined","format":"date-time","nullable":true,"type":"string"},"managers":{"description":"List of community managers","items":{"properties":{"id":{"format":"uuid","type":"string"},"name":{"type":"string"}},"type":"object"},"type":"array"},"member_count":{"description":"Number of members","type":"integer"},"name":{"description":"Community name","type":"string"},"tags":{"description":"Community tags","items":{"type":"string"},"type":"array"},"updated_at":{"description":"Last update timestamp","format":"date-time","type":"string"},"user_role":{"description":"User's role if member","enum":["member","manager"],"nullable":true,"type":"string"}},"required":["id","name","member_count","managers","is_member","is_manager","created_at","updated_at"],"type":"object"},"CommunityJoinResponse":{"properties":{"data":{"properties":{"joined_at":{"description":"Join timestamp","format":"date-time","type":"string"},"member_count":{"description":"Updated member count","type":"integer"},"role":{"description":"User's role","example":"member","type":"string"}},"required":["member_count","role","joined_at"],"type":"object"},"success":{"example":true,"type":"boolean"}},"required":["success","data"],"type":"object"},"CommunityLeaveResponse":{"properties":{"data":{"properties":{"member_count":{"description":"Updated member count","type":"integer"}},"required":["member_count"],"type":"object"},"success":{"example":true,"type":"boolean"}},"required":["success","data"],"type":"object"},"CommunityListItem":{"description":"Community item in list view (index/search results)","properties":{"created_at":{"description":"Community creation timestamp","format":"date-time","type":"string"},"description":{"description":"Community description","nullable":true,"type":"string"},"id":{"description":"Community UUID","format":"uuid","type":"string"},"is_manager":{"description":"Whether current user is a manager (search results)","type":"boolean"},"is_member":{"description":"Whether current user is a member (search results)","type":"boolean"},"joined_at":{"description":"When user joined (user's communities list)","format":"date-time","nullable":true,"type":"string"},"member_count":{"description":"Number of members","type":"integer"},"name":{"description":"Community name","type":"string"},"role":{"description":"User's role in community (user's communities list)","enum":["member","manager"],"nullable":true,"type":"string"},"tags":{"description":"Community tags","items":{"type":"string"},"type":"array"},"updated_at":{"description":"Last update timestamp","format":"date-time","type":"string"}},"required":["id","name","member_count","created_at","updated_at"],"type":"object"},"CommunityMember":{"description":"Community member information","properties":{"id":{"description":"Member node UUID","format":"uuid","type":"string"},"joined_at":{"description":"When member joined","format":"date-time","type":"string"},"name":{"description":"Member name","nullable":true,"type":"string"},"role":{"description":"Member's role","enum":["member","manager"],"type":"string"}},"required":["id","role","joined_at"],"type":"object"},"Error":{"properties":{"details":{"nullable":true,"type":"object"},"error":{"type":"string"},"message":{"type":"string"}},"required":["error","message"],"type":"object"},"Event":{"properties":{"__sync_meta":{"description":"Phoenix.Sync metadata for mobile clients","nullable":true,"properties":{"operation":{"enum":["insert","update","delete"],"type":"string"},"table":{"example":"event","type":"string"},"timestamp":{"format":"date-time","type":"string"}},"type":"object"},"can_sync":{"description":"Whether event supports external platform sync (managers only)","nullable":true,"type":"boolean"},"community_node_id":{"description":"Community hosting the event","format":"uuid","type":"string"},"date":{"description":"Event start date/time (ISO 8601)","format":"date-time","type":"string"},"deeplink_path":{"description":"Deeplink path: /l/event/{shortlink}","type":"string"},"deeplink_url":{"description":"Full deeplink URL for web/mobile routing","format":"uri","type":"string"},"description":{"description":"Event description","nullable":true,"type":"string"},"end_time":{"description":"Event end date/time (ISO 8601)","format":"date-time","nullable":true,"type":"string"},"event_url":{"description":"External event page URL","nullable":true,"type":"string"},"eventbrite_url":{"description":"Eventbrite event URL if synced","format":"uri","nullable":true,"type":"string"},"external_platforms":{"description":"List of synced platforms (managers only)","items":{"type":"string"},"nullable":true,"type":"array"},"id":{"description":"Event UUID","format":"uuid","type":"string"},"image_path":{"description":"Event image URL","nullable":true,"type":"string"},"location":{"description":"Event location name","nullable":true,"type":"string"},"luma_url":{"description":"Luma event URL if synced","format":"uri","nullable":true,"type":"string"},"meetup_url":{"description":"Meetup event URL if synced","format":"uri","nullable":true,"type":"string"},"node_id":{"description":"Event node ID","format":"uuid","nullable":true,"type":"string"},"public_full_url":{"description":"Full public event page URL","format":"uri","type":"string"},"public_url":{"description":"Public event page path: /e/{shortlink}","type":"string"},"shortlink":{"description":"8-character event shortlink code","type":"string"},"title":{"description":"Event title","type":"string"}},"required":["id","title","date","community_node_id","shortlink","deeplink_path","deeplink_url","public_url","public_full_url"],"type":"object"},"Hat":{"properties":{"created_at":{"format":"date-time","type":"string"},"description":{"nullable":true,"type":"string"},"hat_type":{"type":"string"},"id":{"format":"uuid","type":"string"},"is_primary":{"default":false,"type":"boolean"},"name":{"type":"string"}},"required":["id","name","hat_type"],"type":"object"},"HatInput":{"properties":{"description":{"nullable":true,"type":"string"},"hat_type":{"type":"string"},"name":{"type":"string"}},"required":["name","hat_type"],"type":"object"},"LiveTestRequest":{"properties":{"body":{"nullable":true,"type":"object"},"endpoint_id":{"format":"uuid","type":"string"},"headers":{"nullable":true,"type":"object"},"method":{"enum":["GET","POST","PUT","DELETE","PATCH"],"type":"string"},"params":{"nullable":true,"type":"object"},"path":{"type":"string"}},"required":["endpoint_id","method","path"],"type":"object"},"LiveTestResponse":{"properties":{"body":{"nullable":true,"type":"object"},"error_message":{"nullable":true,"type":"string"},"headers":{"nullable":true,"type":"object"},"response_time_ms":{"type":"integer"},"status":{"type":"integer"},"success":{"type":"boolean"},"test_result_id":{"format":"uuid","type":"string"}},"required":["test_result_id","status","response_time_ms","success"],"type":"object"},"Pagination":{"properties":{"page":{"description":"Current page number","type":"integer"},"page_size":{"description":"Items per page","type":"integer"},"total_count":{"description":"Total number of items","type":"integer"},"total_pages":{"description":"Total number of pages","type":"integer"}},"required":["total_count","page","page_size","total_pages"],"type":"object"},"UserProfile":{"properties":{"created_at":{"format":"date-time","type":"string"},"email":{"format":"email","type":"string"},"id":{"format":"uuid","type":"string"},"is_premium":{"type":"boolean"},"max_hats":{"minimum":0,"type":"integer"},"name":{"type":"string"},"node_id":{"format":"uuid","nullable":true,"type":"string"},"subscription_type":{"enum":["basic","premium"],"type":"string"},"updated_at":{"format":"date-time","type":"string"}},"required":["id","email","name","is_premium","subscription_type","max_hats"],"type":"object"}},"securitySchemes":{"bearerAuth":{"bearerFormat":"JWT","scheme":"bearer","type":"http"}}},"info":{"contact":{"email":"api@local.foundation","name":"Local Foundation API Team"},"description":"Interactive API documentation with live testing capabilities using Phoenix.Sync and ElectricSQL","title":"Local Foundation API Documentation","version":"1.0.0"},"openapi":"3.0.3","paths":{"/api/v1/platform/events/{event_node_id}/checkins":{"post":{"description":"Checks in a user to an event. User must exist. Reuses the existing check-in system. Idempotent.","parameters":[{"description":"Event node UUID","in":"path","name":"event_node_id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"email":{"description":"Attendee email address","format":"email","type":"string"}},"required":["email"],"type":"object"}}},"required":true},"responses":{"200":{"description":"Already checked in (idempotent)"},"201":{"content":{"application/json":{"schema":{"properties":{"data":{"properties":{"already_checked_in":{"type":"boolean"},"checked_in_at":{"format":"date-time","type":"string"},"checkin_id":{"format":"uuid","type":"string"}},"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Check-in created"},"403":{"description":"Not authorized"},"404":{"description":"Event or user not found"},"422":{"description":"Validation error"}},"summary":"Check in attendee to event","tags":["Platform Integration"]}},"/api/mobile/tasks":{"get":{"description":"Get all tasks for the authenticated user with optional status filtering and pagination","parameters":[{"description":"Filter tasks by status","in":"query","name":"status","required":false,"schema":{"enum":["pending","in_progress","completed"],"type":"string"}},{"description":"Page number for pagination","in":"query","name":"page","required":false,"schema":{"minimum":1,"type":"integer"}},{"description":"Number of tasks per page","in":"query","name":"limit","required":false,"schema":{"maximum":100,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"success":{"type":"boolean"},"tasks":{"items":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"meta":{"description":"Task metadata including status, title, description, etc.","type":"object"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"},"type":"array"}},"type":"object"}}},"description":"List of tasks"},"422":{"$ref":"#/components/responses/ValidationError"}},"summary":"List all tasks","tags":["Tasks"]},"post":{"description":"Create a new task for the authenticated user. All attributes are stored in the meta field.","requestBody":{"content":{"application/json":{"schema":{"example":{"deal_context":{"company":"TechCorp","deal_value":50000},"description":"Schedule demo call","status":"pending","title":"Follow up with TechCorp"},"properties":{"deal_context":{"properties":{"company":{"example":"TechCorp","type":"string"},"deal_value":{"example":50000,"type":"number"}},"type":"object"},"description":{"example":"Schedule demo call","type":"string"},"status":{"default":"pending","enum":["pending","in_progress","completed"],"type":"string"},"title":{"example":"Follow up with TechCorp","type":"string"}},"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"success":{"type":"boolean"},"task":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"meta":{"type":"object"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Task created successfully"},"422":{"$ref":"#/components/responses/ValidationError"}},"summary":"Create new task","tags":["Tasks"]}},"/api/auth/verify":{"post":{"description":"Verify the validity of an access token","requestBody":{"content":{"application/json":{"schema":{"properties":{"token":{"type":"string"}},"required":["token"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"user_id":{"format":"uuid","type":"string"},"valid":{"type":"boolean"}},"type":"object"}}},"description":"Token is valid"},"401":{"$ref":"#/components/responses/Unauthorized"}},"summary":"Verify access token","tags":["Authentication"]}},"/api/mobile/tasks/{id}/complete_and_link":{"post":{"description":"Complete the current task and create a new linked task in one operation. The new task is automatically linked via task_transition event.","parameters":[{"description":"Current task ID to complete","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"next_task":{"description":"Attributes for the next task","example":{"description":"Check if they have questions","status":"pending","title":"Follow up on demo"},"properties":{"description":{"type":"string"},"status":{"default":"pending","enum":["pending","in_progress"],"type":"string"},"title":{"type":"string"}},"type":"object"}},"required":["next_task"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"completed_task":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"meta":{"type":"object"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"},"next_task":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"meta":{"type":"object"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Task completed and next task created successfully"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Invalid status transition - task is already completed","type":"string"}},"type":"object"}}},"description":"Invalid status transition or validation error"}},"summary":"Complete task and create next task","tags":["Tasks"]}},"/api/mobile/deals/{id}/start_task":{"post":{"description":"Start the current task for a deal","parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"deal":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"meta":{"type":"object"}},"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Task started successfully"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Start current task","tags":["Deals"]}},"/api/mobile/communities/{id}/leave":{"post":{"description":"Remove the authenticated user from the community membership","parameters":[{"description":"Community UUID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityLeaveResponse"}}},"description":"Successfully left community"},"400":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Not a member of this community","type":"string"},"success":{"example":false,"type":"boolean"}},"type":"object"}}},"description":"Bad request - not a member or user has no node"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Community not found","type":"string"},"success":{"example":false,"type":"boolean"}},"type":"object"}}},"description":"Community not found"}},"summary":"Leave a community","tags":["Communities"]}},"/api/mobile/tasks/{id}/next":{"get":{"description":"Get the immediately next task in the chain (if any)","parameters":[{"description":"Current task ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"next_task":{"oneOf":[{"type":"null"},{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"meta":{"type":"object"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"}]},"success":{"type":"boolean"}},"type":"object"}}},"description":"Next task retrieved successfully (may be null if no next task)"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Get next task","tags":["Tasks"]}},"/api/mobile/connections/recent":{"get":{"description":"Get recently created connections","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"connections":{"items":{"type":"object"},"type":"array"},"success":{"type":"boolean"}},"type":"object"}}},"description":"List of recent connections"}},"summary":"Get recent connections","tags":["Connections"]}},"/api/docs/test":{"post":{"description":"Execute a live API call for testing purposes","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LiveTestRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LiveTestResponse"}}},"description":"Test executed successfully"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid test request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Authentication required"}},"summary":"Execute live API test"}},"/api/auth/login":{"post":{"description":"Authenticate user and get access token","requestBody":{"content":{"application/json":{"schema":{"properties":{"email":{"format":"email","type":"string"},"password":{"type":"string"}},"required":["email","password"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"access_token":{"type":"string"},"expires_in":{"type":"integer"},"refresh_token":{"type":"string"}},"type":"object"}}},"description":"Login successful"},"401":{"$ref":"#/components/responses/Unauthorized"}},"security":[],"summary":"User login","tags":["Authentication"]}},"/api/v1/platform/events":{"post":{"description":"Creates an event in a community with full venue details. Idempotent — if an event with the same external_platform + external_id already exists, returns the existing event.","requestBody":{"content":{"application/json":{"schema":{"properties":{"community_id":{"description":"Community node UUID","format":"uuid","type":"string"},"date":{"description":"Event start time (ISO 8601)","format":"date-time","type":"string"},"description":{"type":"string"},"end_time":{"description":"Event end time (ISO 8601)","format":"date-time","type":"string"},"external_id":{"description":"Event ID on the external platform","type":"string"},"external_platform":{"description":"External platform name","enum":["eventbrite","meetup","luma","tito"],"type":"string"},"external_url":{"description":"URL to event on external platform","type":"string"},"image_url":{"type":"string"},"title":{"type":"string"},"venue":{"properties":{"address":{"type":"string"},"latitude":{"format":"float","type":"number"},"longitude":{"format":"float","type":"number"},"name":{"type":"string"}},"type":"object"}},"required":["community_id","external_platform","external_id","title","description","date"],"type":"object"}}},"required":true},"responses":{"200":{"description":"Event already exists (idempotent)"},"201":{"content":{"application/json":{"schema":{"properties":{"data":{"properties":{"created":{"type":"boolean"},"event_id":{"format":"uuid","type":"string"},"event_node_id":{"format":"uuid","type":"string"},"title":{"type":"string"},"venue":{"nullable":true,"properties":{"location_id":{"type":"integer"},"name":{"type":"string"},"venue_node_id":{"format":"uuid","type":"string"}},"type":"object"}},"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Event created"},"403":{"description":"Not authorized to manage this community"},"422":{"description":"Validation error"}},"summary":"Create event from external platform","tags":["Platform Integration"]}},"/api/mobile/tasks/by_company":{"get":{"description":"Get all tasks grouped by company name from deal_context metadata","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"companies":{"items":{"properties":{"active_task":{"oneOf":[{"type":"null"},{"description":"Current pending or in_progress task","type":"object"}]},"all_tasks":{"items":{"type":"object"},"type":"array"},"company_name":{"type":"string"},"completed_tasks":{"items":{"type":"object"},"type":"array"},"deal_value":{"type":"number"},"task_count":{"type":"integer"}},"type":"object"},"type":"array"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Tasks grouped by company"},"422":{"$ref":"#/components/responses/ValidationError"}},"summary":"Group tasks by company","tags":["Tasks"]}},"/api/mobile/tasks/{id}/start":{"post":{"description":"Mark a task as in_progress. Task must be in pending status.","parameters":[{"description":"Task ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"success":{"type":"boolean"},"task":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"meta":{"description":"Meta object with status set to 'in_progress'","type":"object"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Task started successfully"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Invalid status transition - task must be pending to start","type":"string"}},"type":"object"}}},"description":"Invalid status transition"}},"summary":"Start task","tags":["Tasks"]}},"/api/mobile/hats":{"get":{"description":"Get all hats for the authenticated user","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Hat"},"type":"array"},"success":{"type":"boolean"}},"type":"object"}}},"description":"List of user hats"}},"summary":"List user hats","tags":["Hats"]},"post":{"description":"Create a new hat for the authenticated user","requestBody":{"content":{"application/json":{"schema":{"properties":{"hat":{"$ref":"#/components/schemas/HatInput"}},"required":["hat"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Hat"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Hat created successfully"},"422":{"$ref":"#/components/responses/ValidationError"}},"summary":"Create new hat","tags":["Hats"]}},"/api/mobile/venues/{venue_id}/checkin":{"post":{"description":"Intelligent venue check-in endpoint that detects concurrent events and routes accordingly.\n\n**Routing Logic:**\n- **No concurrent events** (0): Checks in to venue directly → Returns 201 with venue check-in data\n- **Single concurrent event** (1): Auto-checks in to that event → Returns 201 with event check-in data\n- **Multiple concurrent events** (2+): Returns event list for user selection → Returns 200 with events array\n\n**Concurrent Event Detection:**\n- Events are considered concurrent if they're within a 2-hour window (before or after current time)\n- Accounts for early arrivals and late departures\n- Query uses: `event.date - 2 hours <= now <= event.end_time + 2 hours`\n\n**Use Cases:**\n- Venue QR code scanning\n- Mobile app venue check-in\n- Smart routing for multi-event venues\n","parameters":[{"description":"The venue's node ID","in":"path","name":"venue_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"hat_id":{"description":"UUID of the hat/persona being worn","format":"uuid","type":"string"},"visibility":{"default":"anonymous","description":"Visibility level: anonymous (only hat type visible) or public (full details visible)","enum":["anonymous","public"],"type":"string"}},"required":["hat_id"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"event_count":{"example":3,"type":"integer"},"events":{"items":{"properties":{"date":{"format":"date-time","type":"string"},"description":{"type":"string"},"end_time":{"format":"date-time","type":"string"},"id":{"format":"uuid","type":"string"},"image_path":{"type":"string"},"node_id":{"type":"string"},"title":{"type":"string"}},"type":"object"},"type":"array"},"message":{"example":"Multiple events found. Please select one.","type":"string"},"success":{"example":true,"type":"boolean"},"type":{"example":"event_selection","type":"string"}},"type":"object"}}},"description":"Multiple events found - user must select one"},"201":{"content":{"application/json":{"schema":{"properties":{"checkin":{"description":"Check-in details (format varies by type)","type":"object"},"success":{"type":"boolean"},"type":{"description":"Type of check-in performed","enum":["venue","event"],"type":"string"}},"type":"object"}}},"description":"Successfully checked in (to venue or single event)"},"422":{"$ref":"#/components/responses/ValidationError"}},"summary":"Smart venue check-in with event detection","tags":["Venues","Checkin"]}},"/api/docs/endpoints":{"get":{"description":"Returns a list of all discoverable API endpoints","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ApiEndpoint"},"type":"array"}}},"description":"List of API endpoints"}},"security":[],"summary":"List all API endpoints","tags":["Documentation"]}},"/api/mobile/connections/{id}":{"get":{"description":"Retrieve a specific connection by its ID","parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"connection":{"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Connection details"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Get connection by ID","tags":["Connections"]},"patch":{"description":"Update an existing connection","parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"notes":{"type":"string"},"strength":{"enum":["weak","medium","strong"],"type":"string"},"tags":{"items":{"type":"string"},"type":"array"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"connection":{"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Connection updated successfully"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Update connection","tags":["Connections"]}},"/api/community/{community_id}":{"get":{"description":"Retrieve information about a specific community","parameters":[{"in":"path","name":"community_id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Community"}}},"description":"Community information"},"404":{"$ref":"#/components/responses/NotFound"}},"security":[],"summary":"Get community information","tags":["Community"]}},"/api/auth/register":{"post":{"description":"Register a new user account","requestBody":{"content":{"application/json":{"schema":{"properties":{"email":{"format":"email","type":"string"},"password":{"minLength":8,"type":"string"}},"required":["email","password"],"type":"object"}}},"required":true},"responses":{"201":{"$ref":"#/components/responses/UserCreated"},"400":{"$ref":"#/components/responses/BadRequest"}},"security":[],"summary":"Register new user","tags":["Authentication"]}},"/api/docs":{"get":{"description":"Returns the interactive API documentation interface","responses":{"200":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Documentation interface HTML"}},"security":[],"summary":"Get API documentation interface","tags":["Documentation"]}},"/api/mobile/events/{id}":{"get":{"description":"Retrieve a specific event by its ID","parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}},"description":"Event details"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Get event by ID","tags":["Events"]}},"/api/mobile/communities/{id}/join":{"post":{"description":"Add the authenticated user as a member of the specified community","parameters":[{"description":"Community UUID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityJoinResponse"}}},"description":"Successfully joined community"},"400":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Already a member of this community","type":"string"},"success":{"example":false,"type":"boolean"}},"type":"object"}}},"description":"Bad request - already a member or user has no node"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Community not found","type":"string"},"success":{"example":false,"type":"boolean"}},"type":"object"}}},"description":"Community not found"}},"summary":"Join a community","tags":["Communities"]}},"/l/checkin/event/{event_node_id}":{"get":{"description":"Web-accessible deep link for event check-in. This endpoint:\n- Detects user's platform (mobile app vs web browser)\n- Redirects to mobile app if available (localfoundation://checkin/event/{id})\n- Falls back to web check-in form if no app installed\n- Requires user authentication\n\nUsed for QR codes and shareable check-in links.\n","parameters":[{"description":"The event's node ID","in":"path","name":"event_node_id","required":true,"schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to check-in form (app or web)","headers":{"Location":{"description":"URL to redirect to (app deep link or web page)","schema":{"type":"string"}}}},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Event not found"}},"security":[],"summary":"Event check-in deep link","tags":["Deep Links","Checkin"]}},"/api/mobile/hat_types":{"get":{"description":"Retrieve available hat types metadata","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"type":"object"},"type":"array"},"success":{"type":"boolean"}},"type":"object"}}},"description":"List of hat types"}},"summary":"Get hat types","tags":["Hats"]}},"/api/mobile/profile":{"get":{"description":"Retrieve the authenticated user's profile information including subscription status and limits","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/UserProfile"},"success":{"type":"boolean"}},"type":"object"}}},"description":"User profile"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"type":"string"},"success":{"type":"boolean"}},"type":"object"}}},"description":"User profile not found (missing PII record)"}},"summary":"Get user profile","tags":["User"]}},"/api/mobile/connections":{"get":{"description":"Get all connections for the authenticated user","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"connections":{"items":{"type":"object"},"type":"array"},"success":{"type":"boolean"}},"type":"object"}}},"description":"List of connections"}},"summary":"List user connections","tags":["Connections"]},"post":{"description":"Create a new connection with another user","requestBody":{"content":{"application/json":{"schema":{"properties":{"connection_type":{"enum":["in_event","post_event","async"],"type":"string"},"event_id":{"format":"uuid","type":"string"},"my_hat_id":{"format":"uuid","type":"string"},"notes":{"type":"string"},"strength":{"enum":["weak","medium","strong"],"type":"string"},"tags":{"items":{"type":"string"},"type":"array"},"target_node_id":{"format":"uuid","type":"string"},"their_hat_id":{"format":"uuid","type":"string"}},"required":["target_node_id"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"connection":{"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Connection created successfully"},"422":{"$ref":"#/components/responses/ValidationError"}},"summary":"Create connection","tags":["Connections"]}},"/api/mobile/checkins":{"get":{"description":"Returns all events and venues the authenticated user is currently checked into (hasn't checked out).\nIncludes event status (ongoing/past/upcoming) and identifies the current ongoing event check-in.\n\nThis endpoint is optimized for performance with caching and eliminates N+1 query problems\nwhen checking multiple locations.\n\nCheck-ins can be for events or venues:\n- Event check-ins include event_status and can be used for connections\n- Venue check-ins are standalone and don't have status\n- Only ongoing event check-ins are returned in current_ongoing_checkin\n","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"checkins":{"description":"Mixed array of event and venue check-ins","items":{"oneOf":[{"description":"Event check-in","properties":{"checked_in_at":{"format":"date-time","type":"string"},"event_date":{"format":"date-time","type":"string"},"event_end_time":{"format":"date-time","nullable":true,"type":"string"},"event_id":{"format":"uuid","type":"string"},"event_status":{"enum":["ongoing","past","upcoming"],"type":"string"},"event_title":{"type":"string"},"hat_id":{"format":"uuid","type":"string"},"type":{"enum":["event"],"type":"string"},"visibility":{"enum":["public","anonymous"],"type":"string"}},"required":["type","event_id","event_title","event_status","checked_in_at"],"type":"object"},{"description":"Venue check-in","properties":{"checked_in_at":{"format":"date-time","type":"string"},"hat_id":{"format":"uuid","type":"string"},"type":{"enum":["venue"],"type":"string"},"venue_id":{"format":"uuid","type":"string"},"venue_name":{"type":"string"},"visibility":{"enum":["public","anonymous"],"type":"string"}},"required":["type","venue_id","venue_name","checked_in_at"],"type":"object"}]},"type":"array"},"current_ongoing_checkin":{"description":"Most recent ongoing EVENT check-in (used for connections), or null. Venue check-ins are not included here.","nullable":true,"properties":{"event_id":{"format":"uuid","type":"string"},"event_status":{"enum":["ongoing"],"type":"string"},"event_title":{"type":"string"},"type":{"enum":["event"],"type":"string"}},"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"List of user's current check-ins (events and venues)"},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"User node not found"}},"summary":"Get current user's check-ins","tags":["Checkin","User"]}},"/api/mobile/tasks/{id}/chain":{"get":{"description":"Get the task chain starting from a given task. Can traverse forward (to next tasks) or backward (to previous tasks) with configurable depth.","parameters":[{"description":"Starting task ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}},{"description":"Direction to traverse the chain","in":"query","name":"direction","required":false,"schema":{"default":"forward","enum":["forward","backward"],"type":"string"}},{"description":"Maximum depth to traverse","in":"query","name":"depth","required":false,"schema":{"default":50,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"chain":{"description":"Array of tasks in the chain","items":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"meta":{"type":"object"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"},"type":"array"},"depth":{"type":"integer"},"direction":{"type":"string"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Task chain retrieved successfully"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Get task chain","tags":["Tasks"]}},"/api/docs/openapi.json":{"get":{"description":"Returns the complete OpenAPI specification for all endpoints","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"OpenAPI specification"}},"security":[],"summary":"Get OpenAPI specification","tags":["Documentation"]}},"/api/mobile/events/upcoming":{"get":{"description":"Retrieve a list of upcoming events for mobile clients","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Event"},"type":"array"}}},"description":"List of upcoming events"},"401":{"$ref":"#/components/responses/Unauthorized"}},"summary":"Get upcoming events","tags":["Events"]}},"/api/auth/signup":{"post":{"description":"Create a new user account for mobile applications","requestBody":{"content":{"application/json":{"schema":{"properties":{"email":{"format":"email","type":"string"},"password":{"minLength":8,"type":"string"}},"required":["email","password"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"email":{"format":"email","type":"string"},"user_id":{"format":"uuid","type":"string"}},"type":"object"}}},"description":"User created successfully"},"400":{"$ref":"#/components/responses/BadRequest"},"422":{"$ref":"#/components/responses/ValidationError"}},"security":[],"summary":"Mobile user signup","tags":["Authentication"]}},"/api/mobile/communities":{"get":{"description":"Get all communities the authenticated user is a member of, with enriched metadata including role and join date","parameters":[{"description":"Maximum number of results to return","in":"query","name":"limit","required":false,"schema":{"default":50,"maximum":100,"minimum":1,"type":"integer"}},{"description":"Pagination offset","in":"query","name":"offset","required":false,"schema":{"default":0,"minimum":0,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CommunityListItem"},"type":"array"},"pagination":{"$ref":"#/components/schemas/Pagination"},"success":{"example":true,"type":"boolean"}},"required":["success","data","pagination"],"type":"object"}}},"description":"List of communities"},"401":{"$ref":"#/components/responses/Unauthorized"}},"summary":"List user's communities","tags":["Communities"]}},"/api/mobile/events/upcoming/stream":{"get":{"description":"Get a streaming connection for upcoming events updates","responses":{"200":{"content":{"text/event-stream":{"schema":{"type":"string"}}},"description":"Event stream"}},"summary":"Stream upcoming events","tags":["Events"]}},"/api/mobile/tasks/{id}/complete":{"post":{"description":"Mark a task as completed. Task must not already be completed.","parameters":[{"description":"Task ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"success":{"type":"boolean"},"task":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"meta":{"description":"Meta object with status set to 'completed'","type":"object"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Task completed successfully"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Invalid status transition - task is already completed","type":"string"}},"type":"object"}}},"description":"Invalid status transition"}},"summary":"Complete task","tags":["Tasks"]}},"/api/docs/tokens":{"get":{"description":"Returns a list of API tokens for the authenticated user","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"tokens":{"items":{"$ref":"#/components/schemas/ApiToken"},"type":"array"}},"type":"object"}}},"description":"List of API tokens"}},"summary":"List user's API tokens"},"post":{"description":"Creates a new API token for testing","requestBody":{"content":{"application/json":{"schema":{"properties":{"expires_at":{"format":"date-time","nullable":true,"type":"string"},"name":{"type":"string"},"permissions":{"items":{"type":"string"},"type":"array"}},"required":["name","permissions"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"token":{"$ref":"#/components/schemas/ApiToken"},"token_value":{"description":"The actual token value (only returned once)","type":"string"}},"type":"object"}}},"description":"Token created successfully"}},"summary":"Create new API token"}},"/api/mobile/tasks/{id}/link":{"post":{"description":"Create a link between two tasks via a task_transition event. This establishes a sequential relationship.","parameters":[{"description":"Origin task ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"example":{"destination_task_id":"123e4567-e89b-12d3-a456-426614174000","transition_meta":{"notes":"Scheduled for next week","reason":"Follow-up task"}},"properties":{"destination_task_id":{"description":"The task to link to","format":"uuid","type":"string"},"transition_meta":{"description":"Optional metadata about the transition","type":"object"}},"required":["destination_task_id"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"link":{"properties":{"destination_task_id":{"format":"uuid","type":"string"},"event":{"properties":{"created_by":{"format":"uuid","type":"string"},"destination_id":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"meta":{"type":"object"},"origin_id":{"format":"uuid","type":"string"},"type":{"type":"string"}},"type":"object"},"origin_task_id":{"format":"uuid","type":"string"}},"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Tasks linked successfully"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Cannot link tasks - circular dependency detected","type":"string"}},"type":"object"}}},"description":"Validation error or circular dependency"}},"summary":"Link two tasks","tags":["Tasks"]}},"/api/v1/forms":{"post":{"description":"Submit form data for processing","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"message":{"type":"string"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Form submitted successfully"},"400":{"$ref":"#/components/responses/ValidationError"}},"security":[],"summary":"Submit form data","tags":["Forms"]}},"/api/mobile/events/{event_id}/checkin":{"delete":{"description":"Remove a check-in from an event","parameters":[{"in":"path","name":"event_id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"message":{"type":"string"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Check-in deleted successfully"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Delete check-in","tags":["Events","Checkin"]},"post":{"description":"Check in to an event with QR code","parameters":[{"in":"path","name":"event_id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"hat_id":{"format":"uuid","type":"string"},"location_id":{"format":"uuid","type":"string"},"visibility":{"enum":["anonymous","public"],"type":"string"}},"type":"object"}}},"required":false},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"checkin":{"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Successfully checked in"},"422":{"$ref":"#/components/responses/ValidationError"}},"summary":"Check in to event","tags":["Events","Checkin"]}},"/api/mobile/communities/{id}":{"get":{"description":"Retrieve detailed information about a specific community including managers, membership status, and user role","parameters":[{"description":"Community UUID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/CommunityDetail"},"success":{"example":true,"type":"boolean"}},"required":["success","data"],"type":"object"}}},"description":"Community details"},"400":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Invalid community ID","type":"string"},"success":{"example":false,"type":"boolean"}},"type":"object"}}},"description":"Invalid community ID format"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Community not found","type":"string"},"success":{"example":false,"type":"boolean"}},"type":"object"}}},"description":"Community not found"}},"summary":"Get community details","tags":["Communities"]}},"/api/mobile/tasks/search":{"get":{"description":"Search for tasks by company name (case-insensitive partial match)","parameters":[{"description":"Company name to search for","example":"TechCorp","in":"query","name":"company","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"search_query":{"type":"string"},"success":{"type":"boolean"},"tasks":{"items":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"meta":{"type":"object"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"},"type":"array"}},"type":"object"}}},"description":"Search results"},"422":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Company name is required","type":"string"}},"type":"object"}}},"description":"Validation error - company name required"}},"summary":"Search tasks by company","tags":["Tasks"]}},"/api/mobile/communities/{id}/members":{"get":{"description":"Get a paginated list of all members in a community with their roles and join dates","parameters":[{"description":"Community UUID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}},{"description":"Maximum number of members to return","in":"query","name":"limit","required":false,"schema":{"default":50,"maximum":100,"minimum":1,"type":"integer"}},{"description":"Pagination offset","in":"query","name":"offset","required":false,"schema":{"default":0,"minimum":0,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CommunityMember"},"type":"array"},"pagination":{"$ref":"#/components/schemas/Pagination"},"success":{"example":true,"type":"boolean"}},"required":["success","data","pagination"],"type":"object"}}},"description":"List of community members"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Community not found","type":"string"},"success":{"example":false,"type":"boolean"}},"type":"object"}}},"description":"Community not found"}},"summary":"List community members","tags":["Communities"]}},"/api/v1/platform/events/{event_node_id}/attendees":{"post":{"description":"Registers a user as an event attendee. Creates the user if they don't exist. Joins them to the event's community. Idempotent.","parameters":[{"description":"Event node UUID","in":"path","name":"event_node_id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"email":{"format":"email","type":"string"},"name":{"description":"Defaults to email prefix","type":"string"}},"required":["email"],"type":"object"}}},"required":true},"responses":{"200":{"description":"User already registered (idempotent)"},"201":{"content":{"application/json":{"schema":{"properties":{"data":{"properties":{"community_joined":{"type":"boolean"},"email":{"type":"string"},"user_created":{"type":"boolean"},"user_id":{"format":"uuid","type":"string"}},"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Attendee registered (user created)"},"403":{"description":"Not authorized"},"404":{"description":"Event not found"},"422":{"description":"Validation error"}},"summary":"Register attendee for event","tags":["Platform Integration"]}},"/api/mobile/deals/{id}/complete_task":{"post":{"description":"Complete the current task and optionally set a new next action","parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"new_next_action":{"example":"Follow up call","type":"string"}},"type":"object"}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"deal":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"meta":{"type":"object"}},"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Task completed successfully"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Complete current task","tags":["Deals"]}},"/api/mobile/events/{event_id}/connections":{"get":{"description":"List connections made at a specific event","parameters":[{"in":"path","name":"event_id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"connections":{"items":{"type":"object"},"type":"array"},"success":{"type":"boolean"}},"type":"object"}}},"description":"List of connections from event"}},"summary":"List event connections","tags":["Connections","Events"]}},"/api/mobile/communities/search":{"get":{"description":"Search for communities by name with enriched metadata showing membership status","parameters":[{"description":"Search query string","in":"query","name":"q","required":true,"schema":{"minLength":1,"type":"string"}},{"description":"Maximum number of results to return","in":"query","name":"limit","required":false,"schema":{"default":50,"maximum":100,"minimum":1,"type":"integer"}},{"description":"Pagination offset","in":"query","name":"offset","required":false,"schema":{"default":0,"minimum":0,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CommunityListItem"},"type":"array"},"pagination":{"$ref":"#/components/schemas/Pagination"},"success":{"example":true,"type":"boolean"}},"required":["success","data","pagination"],"type":"object"}}},"description":"Search results"},"400":{"content":{"application/json":{"schema":{"properties":{"error":{"example":"Search query 'q' parameter is required","type":"string"},"success":{"example":false,"type":"boolean"}},"type":"object"}}},"description":"Bad request - missing or invalid search query"},"401":{"$ref":"#/components/responses/Unauthorized"}},"summary":"Search communities","tags":["Communities"]}},"/l/checkin/venue/{venue_node_id}":{"get":{"description":"Web-accessible deep link for venue check-in with intelligent event detection.\nThis endpoint queries for events currently happening at the venue (with 2-hour buffer)\nand provides smart routing:\n\n**Single Event (auto-redirect):**\n- Automatically redirects to event check-in\n- Returns 302 redirect to /l/checkin/event/{event_node_id}\n\n**Multiple Events (selection UI):**\n- Shows event selection interface\n- User chooses which event they're attending\n- Returns 200 with event selection HTML page\n\n**No Events (error):**\n- Shows error message\n- Returns 404 with helpful message\n\nTime Window: Events are considered \"concurrent\" if they're within 2 hours\nbefore or after the current time (accounts for early arrivals and late departures).\n\nUsed for venue QR codes and shareable venue check-in links.\n","parameters":[{"description":"The venue's node ID","in":"path","name":"venue_node_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"text/html":{"example":"HTML page with event selection interface","schema":{"type":"string"}}},"description":"Event selection page (multiple concurrent events)"},"302":{"description":"Redirect to single event check-in","headers":{"Location":{"description":"URL to event check-in: /l/checkin/event/{event_node_id}","example":"/l/checkin/event/evt_abc123","schema":{"type":"string"}}}},"404":{"content":{"text/html":{"example":"HTML error page with message","schema":{"type":"string"}}},"description":"Venue not found or no concurrent events"}},"security":[],"summary":"Venue check-in deep link with smart routing","tags":["Deep Links","Checkin"]}},"/api/mobile/tasks/{id}":{"delete":{"description":"Delete a task. Only the creator of the task can delete it.","parameters":[{"description":"Task ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"204":{"description":"Task deleted successfully"},"403":{"content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Forbidden - You can only delete your own tasks"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Delete task","tags":["Tasks"]},"get":{"description":"Retrieve a specific task by its ID","parameters":[{"description":"Task ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"success":{"type":"boolean"},"task":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"meta":{"type":"object"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Task details"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Get task by ID","tags":["Tasks"]},"patch":{"description":"Update an existing task's metadata. Fields are merged into the existing meta object. For status changes, use /start or /complete endpoints instead.","parameters":[{"description":"Task ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"example":{"deal_context":{"company":"TechCorp Inc","deal_value":75000},"description":"Updated description","title":"Updated task title"},"properties":{"deal_context":{"properties":{"company":{"type":"string"},"deal_value":{"type":"number"}},"type":"object"},"description":{"type":"string"},"title":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"success":{"type":"boolean"},"task":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"meta":{"type":"object"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"}},"type":"object"}}},"description":"Task updated successfully"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/ValidationError"}},"summary":"Update task metadata","tags":["Tasks"]}},"/api/mobile/tasks/{id}/previous":{"get":{"description":"Get the immediately previous task in the chain (if any)","parameters":[{"description":"Current task ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"previous_task":{"oneOf":[{"type":"null"},{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"meta":{"type":"object"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"}]},"success":{"type":"boolean"}},"type":"object"}}},"description":"Previous task retrieved successfully (may be null if no previous task)"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Get previous task","tags":["Tasks"]}},"/api/mobile/hats/{id}":{"delete":{"description":"Delete a hat by ID","parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"message":{"type":"string"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Hat deleted successfully"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Delete hat","tags":["Hats"]},"get":{"description":"Retrieve a specific hat by its ID","parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Hat"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Hat details"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Get hat by ID","tags":["Hats"]},"patch":{"description":"Update an existing hat","parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"hat":{"$ref":"#/components/schemas/HatInput"}},"required":["hat"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Hat"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Hat updated successfully"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Update hat","tags":["Hats"]}},"/api/mobile/deals":{"get":{"description":"Get all deals for the authenticated user","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"deals":{"items":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"meta":{"type":"object"}},"type":"object"},"type":"array"},"success":{"type":"boolean"}},"type":"object"}}},"description":"List of deals"},"422":{"$ref":"#/components/responses/ValidationError"}},"summary":"List all deals","tags":["Deals"]},"post":{"description":"Create a new deal for the authenticated user","requestBody":{"content":{"application/json":{"schema":{"properties":{"deal_notes":{"type":"string"},"deal_stage":{"example":"discovery","type":"string"},"deal_value":{"example":50000,"type":"number"},"name":{"example":"TechCorp Deal","type":"string"},"next_action":{"example":"Schedule demo call","type":"string"},"next_action_date":{"format":"date","type":"string"},"receiver_node_id":{"format":"uuid","type":"string"}},"required":["name","receiver_node_id"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"deal":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"meta":{"type":"object"}},"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Deal created successfully"},"422":{"$ref":"#/components/responses/ValidationError"}},"summary":"Create new deal","tags":["Deals"]}},"/api/mobile/events/{event_id}/checkins":{"get":{"description":"List all check-ins for an event","parameters":[{"in":"path","name":"event_id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"checkins":{"items":{"type":"object"},"type":"array"},"success":{"type":"boolean"}},"type":"object"}}},"description":"List of check-ins"}},"summary":"List event check-ins","tags":["Events","Checkin"]}},"/api/mobile/deals/{id}/move_to_tomorrow":{"post":{"description":"Move the current task's next action date to tomorrow","parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"deal":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"meta":{"type":"object"}},"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Task moved to tomorrow successfully"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Move task to tomorrow","tags":["Deals"]}},"/api/mobile/hats/{id}/set_primary":{"put":{"description":"Set a hat as the user's primary hat","parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Hat"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Hat set as primary successfully"}},"summary":"Set primary hat","tags":["Hats"]}},"/api/mobile/deals/{id}":{"get":{"description":"Retrieve a specific deal by its ID","parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"deal":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"meta":{"type":"object"}},"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Deal details"},"404":{"$ref":"#/components/responses/NotFound"}},"summary":"Get deal by ID","tags":["Deals"]},"patch":{"description":"Update an existing deal","parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"deal_stage":{"example":"proposal","type":"string"},"deal_value":{"example":75000,"type":"number"},"next_action":{"example":"Send proposal document","type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"deal":{"properties":{"created_by":{"format":"uuid","type":"string"},"id":{"format":"uuid","type":"string"},"meta":{"type":"object"}},"type":"object"},"success":{"type":"boolean"}},"type":"object"}}},"description":"Deal updated successfully"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/ValidationError"}},"summary":"Update deal","tags":["Deals"]}},"/api/mobile/account":{"delete":{"description":"Permanently delete the authenticated user's account. This performs a soft delete on the user record (sets deleted_at timestamp) and hard deletes all PII data (email, name, etc.) for GDPR compliance. This action cannot be undone. Users can re-register with the same email after deletion.","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"deleted_at":{"description":"Timestamp when the account was deleted","format":"date-time","type":"string"},"message":{"example":"Account successfully deleted","type":"string"},"success":{"example":true,"type":"boolean"}},"required":["success","message","deleted_at"],"type":"object"}}},"description":"Account successfully deleted"},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"content":{"application/json":{"schema":{"properties":{"details":{"example":"Unable to process deletion","type":"string"},"error":{"example":"Failed to delete account","type":"string"}},"type":"object"}}},"description":"Failed to delete account"}},"summary":"Delete user account","tags":["User"]}}},"security":[{"bearerAuth":[]}],"servers":[{"description":"Production server","url":"https://local.foundation"}]}