{"openapi":"3.1.0","info":{"title":"NeoCore","description":"NeoCore API - Multi-Database FastAPI application","version":"1.0.0"},"paths":{"/":{"get":{"tags":["System"],"summary":"Root","description":"Root endpoint with API information","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/access-token":{"post":{"tags":["Authentication"],"summary":"Get Access Token","description":"API key authentication - returns JWT token.","operationId":"get_access_token_auth_access_token_post","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admins":{"get":{"tags":["Admins"],"summary":"List Admins","description":"List business admins with filtering and pagination.\n\nQuery parameters:\n- **email__eq**: Filter by email (exact match)\n- **email__contains**: Filter by email (contains text)\n- **business_id__eq**: Filter by business ID\n- **created_at__gte**: Filter by created date (greater than or equal)\n- **created_at__lte**: Filter by created date (less than or equal)\n- **sort**: Sort fields (e.g., \"-created_at\" for descending, \"email\" for ascending)\n- **page**: Page number (default: 1)\n- **limit**: Items per page (default: 10, max: 100)\n\nSupported filter operators:\n- eq: Equals\n- ne: Not equals\n- gt: Greater than\n- gte: Greater than or equal\n- lt: Less than\n- lte: Less than or equal\n- in: In list (comma-separated values)\n- nin: Not in list (comma-separated values)\n- contains: Contains text (case-insensitive)\n- startswith: Starts with text (case-insensitive)\n- endswith: Ends with text (case-insensitive)\n\nExample: `/api/v1/admins?email__contains=admin&sort=-created_at&page=1&limit=10`\n\nNote: password_hash field is automatically excluded from responses for security.","operationId":"list_admins_api_v1_admins_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":10,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAdminsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/api-keys":{"get":{"tags":["API Keys"],"summary":"List Api Keys","description":"List API key metadata for the current business.\n\nReturns only non-sensitive metadata (id, masked prefix, scopes, dates,\nlegacy flag). The plaintext key value is never returned — it is shown only\nonce at creation. See SEC-21.","operationId":"list_api_keys_api_v1_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListApiKeysResponse"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["API Keys"],"summary":"Create Api Key","description":"Create a new API key for the current business.\n\nThe request body is optional; omitting it creates a key with the default\nscope (`admin`) and expiry (365 days). The plaintext key is returned\n**once** in this response and never again; only its HMAC-SHA256 hash and a\nmasked prefix are persisted.\n\n**Security:** Store this key securely - it won't be shown again!","operationId":"create_api_key_api_v1_api_keys_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/CreateApiKeyRequest"},{"type":"null"}],"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"delete":{"tags":["API Keys"],"summary":"Delete Api Key","description":"Delete an API key from the current business by its id.\n\n**Request Body:** `{\"key_id\": \"ak_...\"}` (from the listing endpoint).","operationId":"delete_api_key_api_v1_api_keys_delete","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteApiKeyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteApiKeyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/api-keys/{key_id}/rotate":{"post":{"tags":["API Keys"],"summary":"Rotate Api Key","description":"Rotate an API key: invalidate the old secret and issue a new one atomically,\npreserving the key's id, name, and scopes.\n\nThe new plaintext key is returned **once** in this response.","operationId":"rotate_api_key_api_v1_api_keys__key_id__rotate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateApiKeyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/events":{"post":{"tags":["Events"],"summary":"Create Field Event","description":"Record a field sales event such as a check-in or check-out at an outlet.\nOnly `event`, `event_timestamp`, and `user_id` are required. All other fields are optional.\n\n## Fields\n\n| Payload Field        | Reference Field                                  | Type                   |\n|----------------------|--------------------------------------------------|------------------------|\n| `event`              | determines `tcpl_checkIn__c`/`tcpl_checkOut__c`  | Enum                   |\n| `event_timestamp`    | `tcpl_checkIn__c` or `tcpl_checkOut__c`          | DateTime (ISO 8601 UTC)|\n| `user_id`            | `tcpl_salesRep__c`                               | String                 |\n| `outlet_id`          | `tcpl_beatPlanOutlet__c`                         | String                 |\n| `latitude`           | `tcpl_GeolocationCaptured__Latitude__s`          | String (Decimal 18,15) |\n| `longitude`          | `tcpl_GeolocationCaptured__Longitude__s`         | String (Decimal 18,15) |\n| `visit_type`         | `tcpl_visitType__c`                              | Picklist               |\n| `geo_adherence`      | `tcpl_Geo_Adherence__c`                          | Boolean                |\n| `beat_id`            | `tcpl_Beat_Master__c`                            | String                 |\n| `outlet_geo_change`  | `tcpl_OultetGeoChange__c`                        | String                 |\n\n## IMPORTANT: Latitude and Longitude must be STRINGS\nSend coordinates as quoted strings to preserve full decimal precision.\n- Correct:   `\"latitude\": \"28.613929500000000\"`\n- Incorrect: `\"latitude\": 28.613929500000000` (precision lost due to float conversion)\n\n## Visit Type Allowed Values (case-sensitive)\n- `Joint Visit`\n- `Visit`\n- `Sub DB Check-In`\n- `Pragati DB Check-In`\n- `RPD DB Check-In`\n- `DB Check-In`\n- `Super DB Check-In`\n- `Jump call`\n\n## Example Request\n```json\n{\n  \"event\": \"CHECK_IN\",\n  \"event_timestamp\": \"2026-02-12T08:00:55.944Z\",\n  \"user_id\": \"+91 2222222222\",\n  \"outlet_id\": \"a1JTE000000cU1w2AE\",\n  \"latitude\": \"13.0378136\",\n  \"longitude\": \"77.6167799\",\n  \"visit_type\": \"Visit\",\n  \"geo_adherence\": false,\n  \"beat_id\": \"a10TE000000fQeTYAU\",\n  \"outlet_geo_change\": \"RequestBypass\"\n}\n```","operationId":"create_field_event_api_v1_events_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventCreateRequest"},"examples":{"check_in":{"summary":"Check-in event","description":"Sales rep checking in at an outlet","value":{"event":"CHECK_IN","event_timestamp":"2026-02-12T08:00:55.944Z","user_id":"+91 2222222222","outlet_id":"a1JTE000000cU1w2AE","latitude":"13.0378136","longitude":"77.6167799","visit_type":"Visit","geo_adherence":false,"beat_id":"a10TE000000fQeTYAU","outlet_geo_change":"RequestBypass"}},"check_out":{"summary":"Check-out event","description":"Sales rep checking out from an outlet","value":{"event":"CHECK_OUT","event_timestamp":"2026-02-12T08:30:12.000Z","user_id":"+91 2222222222","outlet_id":"a1JTE000000cU1w2AE","latitude":"13.0378136","longitude":"77.6167799","visit_type":"Visit","geo_adherence":true,"beat_id":"a10TE000000fQeTYAU","outlet_geo_change":"RequestBypass"}}}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/invitations":{"get":{"tags":["Invitations"],"summary":"List Invitations","description":"List invitations for the current business with filtering and pagination.\n\nQuery parameters:\n- **status__eq**: Filter by status (pending, accepted, rejected, expired, revoked)\n- **business_id__eq**: Filter by business ID (alias for inviter_business_id__eq)\n- **inviter_business_id__eq**: Filter by inviter business ID\n- **invitee_user_id__eq**: Filter by invitee user ID\n- **created_at__gte**: Filter by created date (greater than or equal)\n- **created_at__lte**: Filter by created date (less than or equal)\n- **expires_at__gte**: Filter by expiry date (greater than or equal)\n- **expires_at__lte**: Filter by expiry date (less than or equal)\n- **sort**: Sort fields (e.g., \"-created_at\" for descending, \"status\" for ascending)\n- **page**: Page number (default: 1)\n- **limit**: Items per page (default: 10, max: 100)\n\nExample: `/api/v1/invitations?status__eq=pending&business_id__eq=123&sort=-created_at&page=1&limit=10`\n\nNote: By default, invitations are filtered to the current authenticated business.\nYou can override this by specifying business_id__eq or inviter_business_id__eq.","operationId":"list_invitations_api_v1_invitations_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":10,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimplePaginatedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/invitations/create":{"post":{"tags":["Invitations"],"summary":"Create New Invites","description":"Unified endpoint to create invitations for users OR admins based on role.\n\n**Authorization:**\n- Only admin users can create invitations (for both admins and regular users)\n- Non-admin users will receive 403 Forbidden\n\n**For Admin Invitations (role=\"admin\"):**\n- Creates Firebase user with SSO authentication\n- Sends activation email with 24-hour expiry token\n- Admin can belong to only one organization\n- Uses business_admins collection\n\n**For User Invitations (role != \"admin\"):**\n- Validates emails exist in Firestore\n- Checks users are not already in any business\n- Creates invitation and sends email\n- Uses invitations collection\n\n**Request Body:**\n- user_emails: List of email addresses\n- role: \"admin\" | \"user\"\n- invitation_expiry: Days until expiry (default: 7 for users, 24 hours for admins)","operationId":"create_new_invites_api_v1_invitations_create_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNewInvitesReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvitesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/memories/sync":{"get":{"tags":["Memories"],"summary":"Sync Memories","description":"Server-to-Server Sync API with strict retry enforcement.\n\n**First Sync (No History):**\n- Call without session_id to start new session\n- Returns ALL historical memories (paginated)\n- No time window restriction\n- Rate limited: 2 hours between sync sessions\n\n**Incremental Sync (Has History):**\n- Returns only new memories since last completed sync\n- Paginated results\n\n**Pagination:**\n- Use session_id + cursor from previous response to fetch next page\n- Cursor-based pagination for consistency\n- Max 2 retries per cursor (3 total attempts)\n\n**Rate Limiting:**\n- New sessions: 2-hour minimum between syncs\n- Pagination within session: No rate limit\n- Cursor retry limit: 2 retries per cursor\n\n**Session Management:**\n- Sessions expire after 1 hour of inactivity\n- Session auto-completes when all pages fetched\n\nExample Flow:\n```\n# Start first sync\nGET /sync?limit=100\n→ Returns: session_id=abc123, cursor=page1, memories=[...]\n\n# Continue pagination\nGET /sync?session_id=abc123&cursor=page1&limit=100\n→ Returns: cursor=page2, memories=[...]\n\n# Retry on error (max 2 retries)\nGET /sync?session_id=abc123&cursor=page1&limit=100\n→ Returns: Same data (idempotent)\n```","operationId":"sync_memories_api_v1_memories_sync_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Pagination cursor for continuing sync session","title":"Cursor"},"description":"Pagination cursor for continuing sync session"},{"name":"session_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Session ID from previous sync request","title":"Session Id"},"description":"Session ID from previous sync request"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":10,"description":"Number of memories per page (10-500)","default":100,"title":"Limit"},"description":"Number of memories per page (10-500)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncMemoriesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/memories/org_memories":{"get":{"tags":["Memories"],"summary":"List Org Memories","description":"Get paginated organization memories for the authenticated organization with optional date filtering.","operationId":"list_org_memories_api_v1_memories_org_memories_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Base64 cursor for pagination","title":"Cursor"},"description":"Base64 cursor for pagination"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Number of items per page","default":20,"title":"Limit"},"description":"Number of items per page"},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","pattern":"^(created_at|updated_at|title)$","description":"Field to sort by","default":"created_at","title":"Sort By"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sort order","default":"desc","title":"Sort Order"},"description":"Sort order"},{"name":"archived","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by archived status. If not provided, returns all memories.","title":"Archived"},"description":"Filter by archived status. If not provided, returns all memories."},{"name":"start_ts","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start date/time for filtering in UTC (ISO 8601)","title":"Start Ts"},"description":"Start date/time for filtering in UTC (ISO 8601)"},{"name":"end_ts","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"End date/time for filtering in UTC (ISO 8601)","title":"End Ts"},"description":"End date/time for filtering in UTC (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/B2bMemoryListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/memories/{memory_id}":{"get":{"tags":["Memories"],"summary":"Get Memory","operationId":"get_memory_api_v1_memories__memory_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"memory_id","in":"path","required":true,"schema":{"type":"string","title":"Memory Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/memories/filtered":{"post":{"tags":["Memories"],"summary":"List Filtered Memories","description":"Get paginated memories filtered by memory IDs from metadata filter API.\n\nThis endpoint accepts memory IDs from the `/metadata` endpoint and returns\nthe full memory objects with pagination support.\n\n**Usage Flow:**\n1. Call `GET /api/v1/memories/metadata` with your filters\n2. Extract `memory_ids` from the response\n3. POST those `memory_ids` to this endpoint to get paginated memories\n\n**Example:**\n```json\n{\n  \"memory_ids\": [\"uuid-1\", \"uuid-2\", \"uuid-3\"],\n  \"limit\": 20,\n  \"sort_by\": \"created_at\",\n  \"sort_order\": \"desc\",\n  \"page\": 1\n}\n```","operationId":"list_filtered_memories_api_v1_memories_filtered_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilteredMemoriesRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/memories/export":{"post":{"tags":["Memories"],"summary":"Export Memories","operationId":"export_memories_api_v1_memories_export_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoriesExportRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users":{"get":{"tags":["Users"],"summary":"List Users","description":"List all users from Firestore that belong to the authenticated business.\n\n**Important:** Only returns users whose IDs are in the business's user_ids array.\n\nNo pagination, filtering, or sorting - returns all users for the business.\n\n**Response:**\n- `items`: Array of user objects\n- `total`: Total number of users in the business\n\n**Example:** `/api/v1/users`","operationId":"list_users_api_v1_users_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListUsersResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/memory-stats":{"get":{"tags":["Users"],"summary":"Get User Memory Stats","description":"Get memory statistics for all users in the organization.\n\nReturns per user: name, user_id, total hours of memory duration,\nnumber of memories, last online timestamp, and device status.\n\nOnly non-archived, non-deleted memories are counted.\n\n**Filter Options:**\n- `today` - current day's data\n- `week` - past 7 days (default)\n- `month` - past 30 days\n- `all_time` - complete historical data\n- `custom` - user-defined date range (requires start_date and end_date)\n\n**Sorting:**\n- `sort_by`: total_hours (default), name, memory_count, last_online\n- `sort_order`: desc (default) or asc\n\n**Pagination:**\n- `page`: Page number, 1-based (default: 1)\n- `per_page`: Items per page, 1-100 (default: 10)","operationId":"get_user_memory_stats_api_v1_users_memory_stats_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"time_range","in":"query","required":false,"schema":{"$ref":"#/components/schemas/TimeRange","description":"Time range filter: today, week, month, all_time, custom","default":"week"},"description":"Time range filter: today, week, month, all_time, custom"},{"name":"start_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start date for custom range (ISO 8601)","title":"Start Date"},"description":"Start date for custom range (ISO 8601)"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"End date for custom range (ISO 8601)","title":"End Date"},"description":"End date for custom range (ISO 8601)"},{"name":"sort_by","in":"query","required":false,"schema":{"$ref":"#/components/schemas/StatsSortBy","description":"Field to sort by: name, total_hours, memory_count, last_online","default":"total_hours"},"description":"Field to sort by: name, total_hours, memory_count, last_online"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sort direction: asc or desc","default":"desc","title":"Sort Order"},"description":"Sort direction: asc or desc"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page (1-100)","default":10,"title":"Per Page"},"description":"Items per page (1-100)"},{"name":"tz_info","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"User's IANA timezone (e.g. Asia/Kolkata). Used to align date boundaries to the user's local midnight.","title":"Tz Info"},"description":"User's IANA timezone (e.g. Asia/Kolkata). Used to align date boundaries to the user's local midnight."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserMemoryStatsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/memory-stats/export":{"post":{"tags":["Users"],"summary":"Export User Memory Stats","operationId":"export_user_memory_stats_api_v1_users_memory_stats_export_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserStatsExportRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/{user_id}/reset-password":{"post":{"tags":["Users"],"summary":"Reset User Password","description":"Reset a NeoCore user's Firebase password.\n\nOnly Firebase-authenticated business admins with role=\"admin\" may perform this action.\nThe target user must belong to the authenticated organization.","operationId":"reset_user_password_api_v1_users__user_id__reset_password_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetUserPasswordRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetUserPasswordResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/{user_id}/memories":{"get":{"tags":["Users"],"summary":"Get User Memories","description":"Get paginated memories for a specific user.\n\n**Authentication Required**: Valid organization token\n\n**Access Control**: User must belong to the authenticated organization\n\n**Query Parameters:**\n- `cursor`: Base64-encoded cursor for pagination (optional)\n- `limit`: Number of memories per page (1-100, default: 20)\n- `sort_by`: Field to sort by (created_at, updated_at, title, default: created_at)\n- `sort_order`: Sort direction (asc, desc, default: desc)\n\n**Response:**\n- `memories`: Array of memory objects for the user\n- `pagination`: Pagination metadata including:\n  - `count`: Number of memories in current page\n  - `has_more`: Whether there are more pages available\n  - `next_cursor`: Cursor for the next page (if has_more is true)\n  - `total_count`: Total number of memories for this user\n\n**Pagination:**\nUses cursor-based pagination for efficient navigation through large datasets.\nUse the `next_cursor` from the response to fetch the next page.\n\n**Sorting:**\nSupports sorting by:\n- `created_at`: When the memory was created (default)\n- `updated_at`: When the memory was last modified\n- `title`: Memory title (alphabetical)\n\n**Error Responses:**\n- 400: Invalid parameters (limit, sort_by, sort_order, cursor)\n- 403: User does not belong to authenticated organization\n- 404: User not found\n- 500: Internal server error","operationId":"get_user_memories_api_v1_users__user_id__memories_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Cursor for pagination","title":"Cursor"},"description":"Cursor for pagination"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Number of memories per page (1-100)","default":20,"title":"Limit"},"description":"Number of memories per page (1-100)"},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","description":"Field to sort by","default":"created_at","title":"Sort By"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sort direction","default":"desc","title":"Sort Order"},"description":"Sort direction"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserMemoriesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/{user_id}":{"get":{"tags":["Users"],"summary":"Get User Basic Info","operationId":"get_user_basic_info_api_v1_users__user_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserBasicInfoResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks/register":{"post":{"tags":["Webhooks"],"summary":"Register Webhook","description":"Register a new webhook endpoint for receiving event notifications.\n\n**Webhook Events:**\nAvailable events to subscribe to:\n- `memory_processing_started`: Triggered when memory processing begins\n- `memory_completed`: Triggered when memory processing completes successfully\n- `memory_failed`: Triggered when memory processing fails\n\n**Webhook Delivery Headers:**\nAll webhook delivery requests include:\n- `Content-Type: application/json`\n- `User-Agent: NeoCore-Webhook/1.0`\n- `X-NeoSapien-Event: <event_type>` — The event type that triggered this delivery\n- `X-NeoSapien-Delivery: <uuid>` — Unique delivery identifier\n\nWhen `secret_token` is configured (always provided at registration), these additional headers are included:\n- `X-NeoSapien-Signature: sha256=<HMAC-SHA256 hex digest>` — HMAC-SHA256 signature of `{timestamp}.{payload}`\n- `X-NeoSapien-Timestamp: <unix_timestamp>` — Unix timestamp of when the signature was generated\n\n**Signature Verification (HMAC-SHA256):**\nTo verify the authenticity and integrity of a webhook delivery:\n1. Extract the `X-NeoSapien-Timestamp` and `X-NeoSapien-Signature` headers\n2. Construct the signature payload: `{timestamp}.{raw_request_body}`\n3. Compute HMAC-SHA256 using your `secret_token` as the key\n4. Compare with the signature from the header using a constant-time comparison\n5. Optionally reject requests where the timestamp is older than 5 minutes (replay protection)\n\nExample (Python):\n```python\nimport hmac, hashlib\nexpected = hmac.new(secret_token.encode(), f\"{timestamp}.{body}\".encode(), hashlib.sha256).hexdigest()\nis_valid = hmac.compare_digest(f\"sha256={expected}\", signature_header)\n```\n\n**Request Requirements:**\n- `webhook_url`: Valid HTTPS URL endpoint to receive webhooks\n- `events`: Array of event types to subscribe to (minimum 1)\n- `description`: Optional description for webhook identification\n\n**Response Data:**\n- `webhook_id`: Unique identifier for the registered webhook\n- `secret_token`: Secret token for HMAC signature verification (store securely — returned only once)\n- `webhook_url`: Confirmed webhook URL\n- `events`: Subscribed event types\n- `status`: Webhook status (active by default)\n- `created_at`: Registration timestamp\n\n**Error Handling:**\n- 400: Invalid URL format, empty events list, or validation errors\n- 409: Webhook URL already registered for this account\n- 500: Internal server error with detailed error information\n\n**Use Cases:**\n- Real-time notifications for memory processing events\n- Integration with external systems and workflows\n- Automated triggers for downstream processing\n- Event-driven architecture implementation","operationId":"register_webhook","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterWebhookRequest"}}},"required":true},"responses":{"201":{"description":"Webhook registered successfully with secret token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRegisterSuccessResponse"}}}},"400":{"description":"Invalid webhook data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookValidationErrorResponse"}}}},"409":{"description":"Webhook URL already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookConflictResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookInternalServerErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/webhooks":{"get":{"tags":["Webhooks"],"summary":"List Webhooks","description":"Retrieve all registered webhook endpoints for the authenticated user.\n\n**Response Data:**\nReturns a list of webhook objects containing:\n- `webhook_id`: Unique identifier for each webhook\n- `webhook_url`: The URL endpoint for receiving webhooks\n- `events`: Array of subscribed event types\n- `status`: Current webhook status (active, inactive, disabled)\n- `created_at`: Registration timestamp\n\n**Webhook Statuses:**\n- `active`: Webhook is active and receiving events\n- `inactive`: Webhook is temporarily disabled\n- `disabled`: Webhook is permanently disabled due to failures\n\n**Available Events:**\n- `memory_processing_started`: Triggered when memory processing begins\n- `memory_completed`: Triggered when memory processing completes successfully\n- `memory_failed`: Triggered when memory processing fails\n\n**Use Cases:**\n- Review all registered webhook endpoints\n- Monitor webhook status and health\n- Audit webhook configurations\n- Manage webhook subscriptions\n\n**Response Format:**\nReturns a simple success response with webhook data array. No pagination is currently implemented.","operationId":"list_webhooks","responses":{"200":{"description":"List of registered webhooks","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookListSuccessResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookInternalServerErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/webhooks/{webhook_id}":{"delete":{"tags":["Webhooks"],"summary":"Delete Webhook","description":"Delete a specific webhook endpoint by its unique identifier.\n\n**Request Parameters:**\n- `webhook_id`: Unique identifier of the webhook to delete (path parameter)\n\n**Response Behavior:**\n- Successfully deletes the webhook and returns a confirmation message\n- Returns 404 if webhook doesn't exist or user doesn't have access\n- Returns 500 for internal server errors\n\n**Security:**\n- Only the webhook owner can delete their webhook\n- Webhook ID must be a valid MongoDB ObjectId format\n- Requires valid authentication token\n\n**Use Cases:**\n- Remove unused webhook endpoints\n- Clean up webhook configurations\n- Disable event notifications for specific URLs\n- Maintain webhook hygiene and security\n\n**Important Notes:**\n- This action is irreversible - deleted webhooks cannot be recovered\n- All webhook event subscriptions are immediately terminated\n- No events will be sent to the deleted webhook URL\n- Consider temporarily disabling webhooks instead of deletion for testing\n\n**Error Handling:**\n- 404: Webhook not found or access denied\n- 500: Internal server error with detailed error information","operationId":"delete_webhook","security":[{"HTTPBearer":[]}],"parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}}],"responses":{"200":{"description":"Webhook deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeleteSuccessResponse"}}}},"404":{"description":"Webhook not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookNotFoundErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookInternalServerErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ota/updates/check":{"get":{"tags":["OTA Client"],"summary":"Check Update","operationId":"check_update_api_v1_ota_updates_check_get","parameters":[{"name":"platform","in":"query","required":true,"schema":{"type":"string","title":"Platform"}},{"name":"current_version","in":"query","required":true,"schema":{"type":"string","title":"Current Version"}},{"name":"environment","in":"query","required":false,"schema":{"type":"string","default":"prod","title":"Environment"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ota/updates/report":{"post":{"tags":["OTA Client"],"summary":"Report Event","operationId":"report_event_api_v1_ota_updates_report_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/ReportEventRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ota/devices/register":{"post":{"tags":["OTA Client"],"summary":"Register Neo Device","operationId":"register_neo_device_api_v1_ota_devices_register_post","parameters":[{"name":"authorization","in":"header","required":true,"schema":{"type":"string","title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterDeviceRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ota/electron/{platform}/latest.yml":{"get":{"tags":["OTA Client"],"summary":"Electron Manifest","operationId":"electron_manifest_api_v1_ota_electron__platform__latest_yml_get","parameters":[{"name":"platform","in":"path","required":true,"schema":{"type":"string","title":"Platform"}},{"name":"X-Current-Version","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Current-Version"}},{"name":"X-Environment","in":"header","required":false,"schema":{"type":"string","default":"prod","title":"X-Environment"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"text/plain":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ota/electron/{platform}/latest-mac.yml":{"get":{"tags":["OTA Client"],"summary":"Electron Manifest","operationId":"electron_manifest_api_v1_ota_electron__platform__latest_mac_yml_get","parameters":[{"name":"platform","in":"path","required":true,"schema":{"type":"string","title":"Platform"}},{"name":"X-Current-Version","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Current-Version"}},{"name":"X-Environment","in":"header","required":false,"schema":{"type":"string","default":"prod","title":"X-Environment"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"text/plain":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ota/electron/{platform}/{filename}":{"get":{"tags":["OTA Client"],"summary":"Electron Download","operationId":"electron_download_api_v1_ota_electron__platform___filename__get","parameters":[{"name":"platform","in":"path","required":true,"schema":{"type":"string","title":"Platform"}},{"name":"filename","in":"path","required":true,"schema":{"type":"string","title":"Filename"}},{"name":"X-Environment","in":"header","required":false,"schema":{"type":"string","default":"prod","title":"X-Environment"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mcp/authorize":{"get":{"tags":["MCP OAuth"],"summary":"Authorize Get","description":"Serve the Firebase Sign-In page (Google, Microsoft, Apple).","operationId":"authorize_get_mcp_authorize_get","parameters":[{"name":"redirect_uri","in":"query","required":false,"schema":{"type":"string","default":"","title":"Redirect Uri"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","default":"","title":"State"}},{"name":"response_type","in":"query","required":false,"schema":{"type":"string","default":"code","title":"Response Type"}},{"name":"code_challenge","in":"query","required":false,"schema":{"type":"string","default":"","title":"Code Challenge"}},{"name":"code_challenge_method","in":"query","required":false,"schema":{"type":"string","default":"S256","title":"Code Challenge Method"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["MCP OAuth"],"summary":"Authorize Post","description":"Exchange a Firebase ID token for an authorization code (PKCE flow).","operationId":"authorize_post_mcp_authorize_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/mcp/token":{"post":{"tags":["MCP OAuth"],"summary":"Token Exchange","description":"RFC 6749 token endpoint — authorization code + PKCE → MCP JWT.\nmcp-remote sends: grant_type, code, code_verifier, redirect_uri (form-encoded).","operationId":"token_exchange_mcp_token_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"tags":["MCP OAuth"],"summary":"Oauth Metadata","description":"OAuth 2.0 Authorization Server Metadata (RFC 8414).","operationId":"oauth_metadata__well_known_oauth_authorization_server_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"tags":["MCP OAuth"],"summary":"Protected Resource Metadata","description":"OAuth 2.0 Protected Resource Metadata (RFC 9728).","operationId":"protected_resource_metadata__well_known_oauth_protected_resource_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/register":{"post":{"tags":["MCP OAuth"],"summary":"Dynamic Client Registration","description":"mcp-remote calls this before starting OAuth to obtain a client_id.\nWe accept any public client and issue a unique client_id per registration.","operationId":"dynamic_client_registration_register_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"ApiKeyMetadata":{"properties":{"id":{"type":"string","title":"Id"},"prefix":{"type":"string","title":"Prefix"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"scopes":{"items":{"$ref":"#/components/schemas/ApiKeyScope"},"type":"array","title":"Scopes"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"legacy":{"type":"boolean","title":"Legacy","default":false},"created_by_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By Email"}},"type":"object","required":["id","prefix"],"title":"ApiKeyMetadata","description":"Non-sensitive metadata for an API key. Never includes the key value."},"ApiKeyScope":{"type":"string","enum":["read_only","webhook","admin"],"title":"ApiKeyScope","description":"Permission scopes that may be attached to an API key.\n\nNOTE: scopes are currently *modeled and recorded* but not yet enforced at\nprotected endpoints — enforcement is tracked as a separate follow-up ticket."},"AuthorizeRequest":{"properties":{"firebase_token":{"type":"string","title":"Firebase Token"},"redirect_uri":{"type":"string","title":"Redirect Uri"},"state":{"type":"string","title":"State","default":""},"response_type":{"type":"string","title":"Response Type","default":"code"},"code_challenge":{"type":"string","title":"Code Challenge","default":""},"code_challenge_method":{"type":"string","title":"Code Challenge Method","default":"S256"},"timezone":{"type":"string","title":"Timezone","default":"UTC"}},"type":"object","required":["firebase_token","redirect_uri"],"title":"AuthorizeRequest"},"B2bMemoryListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/B2bMemorySummary"},"type":"array","title":"Items"},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"type":"object","title":"B2bMemoryListResponse","description":"Response model for B2B organization memories list."},"B2bMemorySummary":{"properties":{"id":{"type":"string","title":"Id","description":"Unique memory identifier (memory_id)"},"user_id":{"type":"string","title":"User Id","description":"User who created the memory"},"title":{"type":"string","title":"Title","description":"Specific, descriptive title capturing the sales interaction"},"summary":{"type":"string","title":"Summary","description":"75-100 word summary highlighting products discussed, competitors mentioned, and outcome"},"custom_summary":{"type":"string","title":"Custom Summary","description":"Structured sales intelligence with markdown headings: **What was pitched**, **What was asked**, **What worked**, **What didn't work**, **Follow-ups**. Only include headings that have content. Empty string if no insights available.","default":""},"transcript":{"items":{"$ref":"#/components/schemas/TranscriptSegment"},"type":"array","title":"Transcript","description":"List of TranscriptSegment objects"},"mom":{"type":"string","title":"Mom","description":"MARKDOWN formatted meeting notes with sections, bullets, pricing, objections, outcomes"},"participants":{"items":{"type":"string"},"type":"array","title":"Participants","description":"Entities present in the meeting (people, retailer, roles)"},"mentioned_entities":{"items":{"type":"string"},"type":"array","title":"Mentioned Entities","description":"Entities mentioned but not present (brands, competitors, people, locations)"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags","description":"Short tags like [\"order placement\", \"pricing discussion\"]"},"domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Domain","description":"Primary domain - always \"Sales\" for this schema"},"product":{"items":{"type":"string"},"type":"array","title":"Product","description":"List of products discussed or pitched in the meeting"},"customer_details":{"anyOf":[{"$ref":"#/components/schemas/CustomerDetails"},{"type":"null"}],"description":"Details of the customer (nested object)"},"competitors_mentioned":{"items":{"type":"string"},"type":"array","title":"Competitors Mentioned","description":"Competing brands or products mentioned by the customer"},"feedbacks":{"items":{"type":"string"},"type":"array","title":"Feedbacks","description":"Customer feedbacks including direct quotes where applicable"},"archived":{"type":"boolean","title":"Archived","description":"Mark true if no meaningful outcome or actionable content","default":false},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type","description":"Fixed type identifier for sales memories (e.g., \"sales\")"},"created_at":{"type":"string","title":"Created At","description":"Memory creation timestamp (ISO 8601)"},"started_at":{"type":"string","title":"Started At","description":"When recording started (ISO 8601)"},"finished_at":{"type":"string","title":"Finished At","description":"When recording ended (ISO 8601)"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At","description":"Last update timestamp (ISO 8601)"},"coordinates":{"items":{"$ref":"#/components/schemas/Location"},"type":"array","title":"Coordinates","description":"List of location data points"},"mavic_user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mavic User Id","description":"Partner user ID (phone number) from CHECK_IN event"},"mavic_outlet_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mavic Outlet Id","description":"Partner outlet ID from CHECK_IN event"}},"type":"object","required":["id","user_id","title","summary","mom","created_at","started_at","finished_at"],"title":"B2bMemorySummary","description":"B2B-specific memory summary schema with only essential sales fields."},"CreateApiKeyRequest":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"scopes":{"items":{"$ref":"#/components/schemas/ApiKeyScope"},"type":"array","title":"Scopes"},"expires_in_days":{"type":"integer","minimum":1.0,"title":"Expires In Days","default":365}},"type":"object","title":"CreateApiKeyRequest","description":"Request model for creating a new API key."},"CreateApiKeyResponse":{"properties":{"api_key":{"type":"string","title":"Api Key"},"key":{"$ref":"#/components/schemas/ApiKeyMetadata"},"message":{"type":"string","title":"Message","default":"API key created successfully"}},"type":"object","required":["api_key","key"],"title":"CreateApiKeyResponse","description":"Response model for creating a new API key.\n\n`api_key` is the plaintext value, returned exactly once at creation."},"CreateInvitesResponse":{"properties":{"success_count":{"type":"integer","title":"Success Count"},"failed_count":{"type":"integer","title":"Failed Count"},"invitations":{"items":{"$ref":"#/components/schemas/InvitationCreated"},"type":"array","title":"Invitations"}},"type":"object","required":["success_count","failed_count","invitations"],"title":"CreateInvitesResponse","description":"Response model for creating multiple invitations"},"CreateNewInvitesReq":{"properties":{"user_emails":{"items":{"type":"string","format":"email"},"type":"array","title":"User Emails"},"invitation_expiry":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Invitation Expiry","default":7},"role":{"anyOf":[{"type":"string","enum":["admin","manager","viewer","user"]},{"type":"null"}],"title":"Role","default":"user"},"send_email_notification":{"type":"boolean","title":"Send Email Notification","default":true},"country_code":{"type":"string","title":"Country Code","default":"+91"},"mobile_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mobile Number"}},"type":"object","required":["user_emails"],"title":"CreateNewInvitesReq"},"CustomerDetails":{"properties":{"name":{"type":"string","title":"Name","description":"Customer name if known, otherwise empty string","default":""},"contact_number":{"type":"string","title":"Contact Number","description":"Customer phone number if available, otherwise empty string","default":""},"type":{"type":"string","enum":["Retailer","Distributor","Customer"],"title":"Type","description":"Type of customer"},"location":{"type":"string","title":"Location","description":"Shop name, area, or location if available","default":""}},"type":"object","required":["type"],"title":"CustomerDetails"},"DeleteApiKeyRequest":{"properties":{"key_id":{"type":"string","title":"Key Id"}},"type":"object","required":["key_id"],"title":"DeleteApiKeyRequest","description":"Request model for deleting an API key (by stable id)."},"DeleteApiKeyResponse":{"properties":{"message":{"type":"string","title":"Message"},"deleted":{"type":"boolean","title":"Deleted"}},"type":"object","required":["message","deleted"],"title":"DeleteApiKeyResponse","description":"Response model for deleting an API key."},"DeviceInfo":{"properties":{"os_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Os Version"},"hardware_revision":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hardware Revision"},"battery_level":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Battery Level"},"app_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"App Version"},"ble_mtu":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ble Mtu"}},"type":"object","title":"DeviceInfo"},"ErrorData":{"properties":{"code":{"type":"string","title":"Code","description":"Error code"},"message":{"type":"string","title":"Message","description":"Error message"},"details":{"items":{"$ref":"#/components/schemas/ErrorDetail"},"type":"array","title":"Details","description":"List of error details"},"trace_id":{"type":"string","title":"Trace Id","description":"Request trace ID"}},"type":"object","required":["code","message","details","trace_id"],"title":"ErrorData","description":"Base error data structure"},"ErrorDetail":{"properties":{"field":{"type":"string","title":"Field","description":"Field that caused the error"},"message":{"type":"string","title":"Message","description":"Error message"},"code":{"type":"string","title":"Code","description":"Error code"}},"type":"object","required":["field","message","code"],"title":"ErrorDetail","description":"Error detail structure"},"EventCreateRequest":{"properties":{"event":{"$ref":"#/components/schemas/app__api__v1__events__models__EventType","description":"Event type: CHECK_IN or CHECK_OUT"},"event_timestamp":{"type":"string","format":"date-time","title":"Event Timestamp","description":"ISO 8601 date-time in UTC. Examples: '2026-02-11T09:08:18.000Z', '2024-01-15T10:30:00Z'"},"user_id":{"type":"string","minLength":1,"title":"User Id","description":"DSR / sales rep identifier (phone number with country code). Example: '+91 1234123412'"},"outlet_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outlet Id","description":"Beat plan outlet identifier."},"latitude":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latitude","description":"Latitude coordinate as STRING to preserve precision. Decimal(18,15): up to 3 digits before decimal, up to 15 after. Example: '28.613929500000000'"},"longitude":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Longitude","description":"Longitude coordinate as STRING to preserve precision. Decimal(18,15): up to 4 digits before decimal, up to 15 after. Example: '77.209015500000000'"},"visit_type":{"anyOf":[{"$ref":"#/components/schemas/VisitType"},{"type":"null"}],"description":"Visit type picklist. Case-sensitive."},"geo_adherence":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Geo Adherence","description":"Whether the visit location is within allowed geo radius."},"beat_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beat Id","description":"Beat master identifier."},"outlet_geo_change":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outlet Geo Change","description":"Outlet geo-fence change request status. Example: 'RequestBypass'"},"mavic_user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mavic User Id","description":"Mavic platform user identifier."}},"additionalProperties":true,"type":"object","required":["event","event_timestamp","user_id"],"title":"EventCreateRequest","description":"Request model for field sales events (check-in / check-out).\n\nReference field mapping:\n    user_id            -> tcpl_salesRep__c\n    event              -> determines tcpl_checkIn__c or tcpl_checkOut__c\n    event_timestamp    -> tcpl_checkIn__c / tcpl_checkOut__c value\n    outlet_id          -> tcpl_beatPlanOutlet__c\n    beat_id            -> tcpl_Beat_Master__c\n    visit_type         -> tcpl_visitType__c\n    geo_adherence      -> tcpl_Geo_Adherence__c\n    latitude           -> tcpl_GeolocationCaptured__Latitude__s\n    longitude          -> tcpl_GeolocationCaptured__Longitude__s\n    outlet_geo_change  -> tcpl_OultetGeoChange__c","examples":[{"beat_id":"a10TE000000fQeTYAU","event":"CHECK_IN","event_timestamp":"2026-02-12T08:00:55.944Z","geo_adherence":false,"latitude":"13.0378136","longitude":"77.6167799","outlet_geo_change":"RequestBypass","outlet_id":"a1JTE000000cU1w2AE","user_id":"+91 2222222222","visit_type":"Visit"}]},"EventCreateResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Event logged successfully","default":true},"message":{"type":"string","title":"Message","description":"Confirmation message"},"neo_user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Neo User Id","description":"Resolved NeoSapien user ID. Present for CHECK_IN/CHECK_OUT events."}},"type":"object","required":["message"],"title":"EventCreateResponse","description":"Response model for event creation."},"FilteredMemoriesRequest":{"properties":{"memory_ids":{"items":{"type":"string"},"type":"array","title":"Memory Ids","description":"List of memory IDs from metadata filter API"},"cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor","description":"Base64 cursor for pagination"},"limit":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Limit","description":"Number of items per page","default":20},"sort_by":{"type":"string","pattern":"^(created_at|updated_at|title)$","title":"Sort By","description":"Field to sort by","default":"created_at"},"sort_order":{"type":"string","pattern":"^(asc|desc)$","title":"Sort Order","description":"Sort order (asc or desc)","default":"desc"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Page number for page-based pagination (when cursor is not provided)","default":1}},"type":"object","required":["memory_ids"],"title":"FilteredMemoriesRequest","description":"Request model for fetching paginated filtered memories."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"InvitationCreated":{"properties":{"user_id":{"type":"string","title":"User Id"},"email":{"type":"string","title":"Email"},"invitation_id":{"type":"string","title":"Invitation Id"},"status":{"type":"string","enum":["created","failed"],"title":"Status"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["user_id","email","invitation_id","status"],"title":"InvitationCreated","description":"Single invitation creation result"},"ListAdminsResponse":{"properties":{"items":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"has_next":{"type":"boolean","title":"Has Next"},"has_prev":{"type":"boolean","title":"Has Prev"}},"type":"object","required":["items","total","has_next","has_prev"],"title":"ListAdminsResponse","description":"Response model for listing admins with pagination"},"ListApiKeysResponse":{"properties":{"api_keys":{"items":{"type":"string"},"type":"array","title":"Api Keys"},"keys":{"items":{"$ref":"#/components/schemas/ApiKeyMetadata"},"type":"array","title":"Keys"}},"type":"object","required":["api_keys","keys"],"title":"ListApiKeysResponse","description":"Response model for listing API keys (metadata only).\n\n`api_keys` retains the legacy `List[str]` shape (masked prefixes only) so\nthe pre-SEC-34 dashboard renders instead of throwing; `keys` carries the\nfull metadata. Remove `api_keys` once SEC-34 ships and the UI reads `keys`."},"ListUsersResponse":{"properties":{"items":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["items","total"],"title":"ListUsersResponse","description":"Response model for listing users"},"Location":{"properties":{"type":{"type":"string","title":"Type"},"coordinates":{"items":{"type":"number"},"type":"array","title":"Coordinates"},"timestamp":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Timestamp"}},"type":"object","required":["type","coordinates"],"title":"Location"},"MemoriesExportRequest":{"properties":{"memory_ids":{"items":{"type":"string"},"type":"array","minItems":1,"title":"Memory Ids","description":"List of memory IDs to include in the export"},"format":{"type":"string","enum":["json","csv"],"title":"Format","description":"Export format: json or csv","default":"json"},"sort_by":{"type":"string","pattern":"^(created_at|updated_at|title)$","title":"Sort By","description":"Field to sort by before exporting","default":"created_at"},"sort_order":{"type":"string","enum":["asc","desc"],"title":"Sort Order","description":"Sort order for export (asc or desc)","default":"desc"}},"type":"object","required":["memory_ids"],"title":"MemoriesExportRequest"},"Memory":{"properties":{"_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"user_id":{"type":"string","title":"User Id"},"title":{"type":"string","title":"Title"},"summary":{"type":"string","title":"Summary"},"emotions":{"items":{"type":"string"},"type":"array","title":"Emotions","default":[]},"topics":{"items":{"type":"string"},"type":"array","title":"Topics","default":[]},"transcript":{"items":{"$ref":"#/components/schemas/TranscriptSegment"},"type":"array","title":"Transcript","default":[]},"domains":{"items":{"type":"string"},"type":"array","title":"Domains","default":[]},"mom":{"type":"string","title":"Mom"},"participants":{"items":{},"type":"array","title":"Participants","default":[]},"archived":{"type":"boolean","title":"Archived","default":false},"rating":{"anyOf":[{},{"type":"null"}],"title":"Rating"},"source":{"type":"string","title":"Source"},"coordinates":{"anyOf":[{"items":{"$ref":"#/components/schemas/Location"},"type":"array"},{"type":"null"}],"title":"Coordinates","default":[]},"chat_ids":{"items":{"type":"string"},"type":"array","title":"Chat Ids","default":[]},"created_at":{"type":"string","format":"date-time","title":"Created At"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"finished_at":{"type":"string","format":"date-time","title":"Finished At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"},"deleted":{"type":"boolean","title":"Deleted","default":false},"visibility":{"type":"string","enum":["private","public"],"title":"Visibility","default":"private"},"processing_memory_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Processing Memory Id"},"status":{"type":"string","title":"Status"},"transcript_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transcript Source"},"present_entities":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Present Entities","default":[]},"mentioned_entities":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Mentioned Entities","default":[]},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags","default":[]},"product":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Product","default":[]},"customer_details":{"anyOf":[{"$ref":"#/components/schemas/CustomerDetails"},{"type":"null"}]},"competitors_mentioned":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Competitors Mentioned","default":[]},"feedbacks":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Feedbacks","default":[]},"custom_summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Custom Summary","description":"Structured sales intelligence with markdown headings: **What was pitched**, **What was asked**, **What worked**, **What didn't work**, **Follow-ups**. Only include headings that have content. Empty string if no insights available.","default":""},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"},"checkin_event_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Checkin Event Id"},"mavic_user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mavic User Id"},"mavic_outlet_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mavic Outlet Id"}},"type":"object","required":["user_id","title","summary","mom","source","created_at","started_at","finished_at","status"],"title":"Memory"},"MemoryListItem":{"properties":{"memory":{"$ref":"#/components/schemas/Memory"},"user":{"$ref":"#/components/schemas/MemoryUserInfo"}},"type":"object","required":["memory","user"],"title":"MemoryListItem"},"MemoryListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/MemoryListItem"},"type":"array","title":"Items"},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"type":"object","title":"MemoryListResponse"},"MemoryUserInfo":{"properties":{"id":{"type":"string","title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","default":""},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","default":""}},"type":"object","required":["id"],"title":"MemoryUserInfo"},"MetaData":{"properties":{"timestamp":{"type":"string","title":"Timestamp","description":"Response timestamp"},"request_id":{"type":"string","title":"Request Id","description":"Request ID"},"api_version":{"type":"string","title":"Api Version","description":"API version"},"execution_time_ms":{"type":"integer","title":"Execution Time Ms","description":"Execution time in milliseconds"}},"type":"object","required":["timestamp","request_id","api_version","execution_time_ms"],"title":"MetaData","description":"Response metadata structure"},"PaginationInfo":{"properties":{"count":{"type":"integer","title":"Count","default":0},"has_more":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has More","default":false},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"total_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Count","default":0},"per_page":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Per Page","default":20}},"type":"object","title":"PaginationInfo"},"RegisterDeviceRequest":{"properties":{"device_id":{"type":"string","title":"Device Id"},"hardware_revision":{"type":"string","title":"Hardware Revision"},"bootloader_version":{"type":"string","title":"Bootloader Version"},"current_firmware_version":{"type":"string","title":"Current Firmware Version"}},"type":"object","required":["device_id","hardware_revision","bootloader_version","current_firmware_version"],"title":"RegisterDeviceRequest"},"RegisterWebhookRequest":{"properties":{"webhook_url":{"type":"string","maxLength":2083,"minLength":1,"format":"uri","title":"Webhook Url","description":"The URL to send webhook events to"},"events":{"items":{"type":"string"},"type":"array","minItems":1,"title":"Events","description":"List of events to subscribe to"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Optional description of the webhook"}},"type":"object","required":["webhook_url","events"],"title":"RegisterWebhookRequest","description":"Request model for registering a webhook"},"ReportEventRequest":{"properties":{"release_id":{"type":"string","title":"Release Id"},"device_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Id"},"platform":{"type":"string","title":"Platform"},"from_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Version"},"to_version":{"type":"string","title":"To Version"},"event_type":{"$ref":"#/components/schemas/app__internal__ota__models__event__EventType"},"error_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Code"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"method":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Method"},"transfer_duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Transfer Duration Seconds"},"device_info":{"anyOf":[{"$ref":"#/components/schemas/DeviceInfo"},{"type":"null"}]}},"type":"object","required":["release_id","platform","to_version","event_type"],"title":"ReportEventRequest"},"ResetUserPasswordRequest":{"properties":{"password":{"anyOf":[{"type":"string","minLength":6},{"type":"null"}],"title":"Password","description":"Optional temporary password. If omitted, the default temporary password is used."},"consent_confirmed":{"type":"boolean","title":"Consent Confirmed","description":"Explicit admin acknowledgement that this password reset is authorized.","default":false},"consent_statement_version":{"type":"string","const":"user_password_reset_v1","title":"Consent Statement Version","description":"Version of the consent statement acknowledged by the admin.","default":"user_password_reset_v1"}},"type":"object","title":"ResetUserPasswordRequest","description":"Request model for resetting a NeoCore user's Firebase password."},"ResetUserPasswordResponse":{"properties":{"user_id":{"type":"string","title":"User Id"},"email":{"type":"string","title":"Email"},"used_default_password":{"type":"boolean","title":"Used Default Password"},"audit_log_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Audit Log Id"},"message":{"type":"string","title":"Message"}},"type":"object","required":["user_id","email","used_default_password","message"],"title":"ResetUserPasswordResponse","description":"Response model for a successful password reset."},"RotateApiKeyResponse":{"properties":{"api_key":{"type":"string","title":"Api Key"},"key":{"$ref":"#/components/schemas/ApiKeyMetadata"},"message":{"type":"string","title":"Message","default":"API key rotated successfully"}},"type":"object","required":["api_key","key"],"title":"RotateApiKeyResponse","description":"Response model for rotating an API key. Returns the new plaintext once."},"SimplePaginatedResponse":{"properties":{"items":{"items":{},"type":"array","title":"Items","description":"List of items for current page"},"total":{"type":"integer","title":"Total","description":"Total number of items matching filters"},"has_next":{"type":"boolean","title":"Has Next","description":"Whether there is a next page"},"has_prev":{"type":"boolean","title":"Has Prev","description":"Whether there is a previous page"}},"type":"object","required":["items","total","has_next","has_prev"],"title":"SimplePaginatedResponse","description":"Simplified paginated response wrapper.\n\nReturns only essential pagination metadata: items, total, has_next, has_prev."},"StatsPaginationInfo":{"properties":{"total":{"type":"integer","title":"Total","description":"Total number of users"},"page":{"type":"integer","title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","title":"Per Page","description":"Items per page"},"total_pages":{"type":"integer","title":"Total Pages","description":"Total number of pages"},"has_next":{"type":"boolean","title":"Has Next","description":"Whether there is a next page"},"has_prev":{"type":"boolean","title":"Has Prev","description":"Whether there is a previous page"}},"type":"object","required":["total","page","per_page","total_pages","has_next","has_prev"],"title":"StatsPaginationInfo","description":"Pagination metadata for memory stats."},"StatsSortBy":{"type":"string","enum":["name","total_hours","memory_count","last_online"],"title":"StatsSortBy"},"SyncInfo":{"properties":{"session_id":{"type":"string","title":"Session Id","description":"Unique session ID for pagination continuity"},"is_first_sync":{"type":"boolean","title":"Is First Sync","description":"True if this is the first sync (all historical data)"},"since":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since","description":"Start of sync window (ISO 8601)"},"until":{"type":"string","title":"Until","description":"End of sync window (ISO 8601)"},"effective_since":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Effective Since","description":"Actual query start time (ISO 8601)"}},"type":"object","required":["session_id","is_first_sync","until"],"title":"SyncInfo"},"SyncMemoriesResponse":{"properties":{"memories":{"items":{"$ref":"#/components/schemas/Memory"},"type":"array","title":"Memories"},"pagination":{"$ref":"#/components/schemas/PaginationInfo"},"sync_info":{"$ref":"#/components/schemas/SyncInfo"}},"type":"object","required":["memories","pagination","sync_info"],"title":"SyncMemoriesResponse"},"TimeRange":{"type":"string","enum":["today","week","month","all_time","custom"],"title":"TimeRange"},"Token":{"properties":{"access_token":{"type":"string","title":"Access Token"},"token_type":{"type":"string","title":"Token Type"},"business_id":{"type":"string","title":"Business Id"}},"type":"object","required":["access_token","token_type","business_id"],"title":"Token"},"TranscriptSegment":{"properties":{"text":{"type":"string","title":"Text"},"speaker":{"type":"string","title":"Speaker"},"speaker_id":{"type":"integer","title":"Speaker Id"},"is_user":{"type":"boolean","title":"Is User"},"person_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Person Id"},"start":{"type":"number","title":"Start"},"end":{"type":"number","title":"End"}},"type":"object","required":["text","speaker","speaker_id","is_user","start","end"],"title":"TranscriptSegment"},"UserBasicInfoResponse":{"properties":{"user_id":{"type":"string","title":"User Id"},"name":{"type":"string","title":"Name"},"email":{"type":"string","title":"Email"}},"type":"object","required":["user_id","name","email"],"title":"UserBasicInfoResponse","description":"Response model for user basic information from Firebase"},"UserMemoriesResponse":{"properties":{"memories":{"items":{"$ref":"#/components/schemas/Memory"},"type":"array","title":"Memories"},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"type":"object","required":["memories","pagination"],"title":"UserMemoriesResponse"},"UserMemoryStats":{"properties":{"name":{"type":"string","title":"Name"},"user_id":{"type":"string","title":"User Id"},"total_hours":{"type":"number","title":"Total Hours","description":"Total memory duration in hours"},"memory_count":{"type":"integer","title":"Memory Count","description":"Number of non-archived memories"},"last_online":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Online","description":"Last online timestamp (ISO 8601)"},"device_status":{"type":"string","title":"Device Status","description":"Device status: online or offline","default":"offline"}},"type":"object","required":["name","user_id","total_hours","memory_count"],"title":"UserMemoryStats","description":"Memory statistics for a single user."},"UserMemoryStatsResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/UserMemoryStats"},"type":"array","title":"Items"},"pagination":{"$ref":"#/components/schemas/StatsPaginationInfo"},"time_range":{"type":"string","title":"Time Range"},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date","description":"Filter start date (ISO 8601)"},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date","description":"Filter end date (ISO 8601)"}},"type":"object","required":["items","pagination","time_range"],"title":"UserMemoryStatsResponse","description":"Response model for user memory stats endpoint."},"UserStatsExportRequest":{"properties":{"format":{"type":"string","enum":["json","csv"],"title":"Format","default":"json"},"time_range":{"$ref":"#/components/schemas/TimeRange","default":"week"},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date"},"sort_by":{"$ref":"#/components/schemas/StatsSortBy","default":"total_hours"},"sort_order":{"type":"string","enum":["asc","desc"],"title":"Sort Order","default":"desc"},"tz_info":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tz Info"}},"type":"object","title":"UserStatsExportRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VisitType":{"type":"string","enum":["Joint Visit","Visit","Sub DB Check-In","Pragati DB Check-In","RPD DB Check-In","DB Check-In","Super DB Check-In","Jump call"],"title":"VisitType","description":"Allowed visit types.\nMaps to tcpl_visitType__c picklist.\nCase-sensitive."},"WebhookConflictResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Operation success status - always false for error responses","default":false},"data":{"anyOf":[{},{"type":"null"}],"title":"Data","description":"Always null for error responses"},"error":{"$ref":"#/components/schemas/ErrorData","description":"Webhook conflict error details"},"meta":{"$ref":"#/components/schemas/MetaData","description":"Response metadata including timestamp, request_id, api_version, and execution_time_ms"}},"type":"object","required":["error","meta"],"title":"WebhookConflictResponse","description":"Webhook already exists response (HTTP 409)"},"WebhookData":{"properties":{"webhook_id":{"type":"string","title":"Webhook Id","description":"Unique webhook identifier"},"webhook_url":{"type":"string","title":"Webhook Url","description":"The URL to send webhook events to"},"secret_token":{"type":"string","title":"Secret Token","description":"Secret token for webhook signature verification"},"events":{"items":{"type":"string"},"type":"array","title":"Events","description":"List of subscribed events"},"status":{"type":"string","title":"Status","description":"Webhook status"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Webhook creation timestamp"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Optional description of the webhook"}},"type":"object","required":["webhook_id","webhook_url","secret_token","events","status","created_at"],"title":"WebhookData","description":"Webhook data structure for API responses"},"WebhookDeleteSuccessResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Operation success status - always true for successful responses","default":true},"message":{"type":"string","title":"Message","description":"Success message confirming webhook deletion"}},"type":"object","required":["message"],"title":"WebhookDeleteSuccessResponse","description":"Webhook delete success response (HTTP 200)"},"WebhookInternalServerErrorResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Operation success status - always false for error responses","default":false},"data":{"anyOf":[{},{"type":"null"}],"title":"Data","description":"Always null for error responses"},"error":{"$ref":"#/components/schemas/ErrorData","description":"Internal server error details"},"meta":{"$ref":"#/components/schemas/MetaData","description":"Response metadata including timestamp, request_id, api_version, and execution_time_ms"}},"type":"object","required":["error","meta"],"title":"WebhookInternalServerErrorResponse","description":"Internal server error response (HTTP 500)"},"WebhookListItem":{"properties":{"webhook_id":{"type":"string","title":"Webhook Id","description":"Unique webhook identifier"},"webhook_url":{"type":"string","title":"Webhook Url","description":"The URL to send webhook events to"},"events":{"items":{"type":"string"},"type":"array","title":"Events","description":"List of subscribed events"},"status":{"type":"string","title":"Status","description":"Webhook status"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Webhook creation timestamp"}},"type":"object","required":["webhook_id","webhook_url","events","status","created_at"],"title":"WebhookListItem","description":"Webhook item structure for list responses"},"WebhookListSuccessResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Operation success status - always true for successful responses","default":true},"data":{"items":{"$ref":"#/components/schemas/WebhookListItem"},"type":"array","title":"Data","description":"List of registered webhooks"}},"type":"object","required":["data"],"title":"WebhookListSuccessResponse","description":"Webhook list success response (HTTP 200)"},"WebhookNotFoundErrorResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Operation success status - always false for error responses","default":false},"data":{"anyOf":[{},{"type":"null"}],"title":"Data","description":"Always null for error responses"},"error":{"$ref":"#/components/schemas/ErrorData","description":"Webhook not found error details"},"meta":{"$ref":"#/components/schemas/MetaData","description":"Response metadata including timestamp, request_id, api_version, and execution_time_ms"}},"type":"object","required":["error","meta"],"title":"WebhookNotFoundErrorResponse","description":"Webhook not found error response (HTTP 404)"},"WebhookRegisterSuccessResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Operation success status - always true for 201 responses","default":true},"data":{"$ref":"#/components/schemas/WebhookData","description":"Webhook registration data"},"error":{"anyOf":[{},{"type":"null"}],"title":"Error","description":"Always null for successful responses"},"meta":{"$ref":"#/components/schemas/MetaData","description":"Response metadata including timestamp, request_id, api_version, and execution_time_ms"}},"type":"object","required":["data","meta"],"title":"WebhookRegisterSuccessResponse","description":"Webhook registration success response (HTTP 201)"},"WebhookValidationErrorResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Operation success status - always false for error responses","default":false},"data":{"anyOf":[{},{"type":"null"}],"title":"Data","description":"Always null for error responses"},"error":{"$ref":"#/components/schemas/ErrorData","description":"Validation error details with field-level information"},"meta":{"$ref":"#/components/schemas/MetaData","description":"Response metadata including timestamp, request_id, api_version, and execution_time_ms"}},"type":"object","required":["error","meta"],"title":"WebhookValidationErrorResponse","description":"Webhook validation error response (HTTP 400)"},"app__api__v1__events__models__EventType":{"type":"string","enum":["CHECK_IN","CHECK_OUT"],"title":"EventType","description":"Supported field event types."},"app__internal__ota__models__event__EventType":{"type":"string","enum":["check","download_start","download_complete","download_failure","flash_start","flash_complete","flash_failure","install_start","install_success","install_failure","boot_success","boot_failure","boot_unknown","rollback"],"title":"EventType"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}