{"openapi":"3.0.0","paths":{"/api/health":{"get":{"operationId":"HealthController_check","parameters":[],"responses":{"200":{"description":"The Health Check is successful","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"info":{"type":"object","example":{"database":{"status":"up"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"error":{"type":"object","example":{},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"details":{"type":"object","example":{"database":{"status":"up"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true}}}}}}},"503":{"description":"The Health Check is not successful","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"error"},"info":{"type":"object","example":{"database":{"status":"up"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"error":{"type":"object","example":{"redis":{"status":"down","message":"Could not connect"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"details":{"type":"object","example":{"database":{"status":"up"},"redis":{"status":"down","message":"Could not connect"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true}}}}}}}},"summary":"Check application health","tags":["Health"]}},"/api/health/ready":{"get":{"operationId":"HealthController_readiness","parameters":[],"responses":{"200":{"description":"The Health Check is successful","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"info":{"type":"object","example":{"database":{"status":"up"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"error":{"type":"object","example":{},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"details":{"type":"object","example":{"database":{"status":"up"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true}}}}}}},"503":{"description":"The Health Check is not successful","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"error"},"info":{"type":"object","example":{"database":{"status":"up"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"error":{"type":"object","example":{"redis":{"status":"down","message":"Could not connect"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"details":{"type":"object","example":{"database":{"status":"up"},"redis":{"status":"down","message":"Could not connect"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true}}}}}}}},"summary":"Check if application is ready to serve traffic","tags":["Health"]}},"/api/health/live":{"get":{"operationId":"HealthController_liveness","parameters":[],"responses":{"200":{"description":"The Health Check is successful","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"info":{"type":"object","example":{"database":{"status":"up"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"error":{"type":"object","example":{},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"details":{"type":"object","example":{"database":{"status":"up"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true}}}}}}},"503":{"description":"The Health Check is not successful","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"error"},"info":{"type":"object","example":{"database":{"status":"up"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"error":{"type":"object","example":{"redis":{"status":"down","message":"Could not connect"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true},"nullable":true},"details":{"type":"object","example":{"database":{"status":"up"},"redis":{"status":"down","message":"Could not connect"}},"additionalProperties":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}},"additionalProperties":true}}}}}}}},"summary":"Check if application is alive","tags":["Health"]}},"/api/custom-category":{"get":{"operationId":"CustomCategoryController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"code","required":false,"in":"query","description":"The code of the custom category","schema":{"example":"lead_status","type":"string"}},{"name":"name","required":false,"in":"query","description":"The name of the custom category","schema":{"example":"Lead Status","type":"string"}},{"name":"isSystem","required":false,"in":"query","description":"Whether this is a system category","schema":{"example":false,"type":"boolean"}}],"responses":{"200":{"description":"Custom categories fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllCustomCategoryDto"}}}}},"summary":"Get all custom categories with pagination","tags":["Custom Category"]},"post":{"operationId":"CustomCategoryController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomCategoryDto"}}}},"responses":{"201":{"description":"Custom category created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleCustomCategoryDto"}}}}},"summary":"Create a new custom category","tags":["Custom Category"]}},"/api/custom-category/code/{code}":{"get":{"operationId":"CustomCategoryController_findOneByCode","parameters":[{"name":"code","required":true,"in":"path","description":"Category code","schema":{"example":"lead_status","type":"string"}}],"responses":{"200":{"description":"Custom category fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleCustomCategoryDto"}}}},"404":{"description":"Custom category not found"}},"summary":"Get a single custom category by code with all options","tags":["Custom Category"]}},"/api/custom-category/{id}":{"get":{"operationId":"CustomCategoryController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Category ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Custom category fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleCustomCategoryDto"}}}},"404":{"description":"Custom category not found"}},"summary":"Get a single custom category with all options","tags":["Custom Category"]},"patch":{"operationId":"CustomCategoryController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Category ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomCategoryDto"}}}},"responses":{"200":{"description":"Custom category updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleCustomCategoryDto"}}}}},"summary":"Update a custom category","tags":["Custom Category"]},"delete":{"operationId":"CustomCategoryController_delete","parameters":[{"name":"id","required":true,"in":"path","description":"Category ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Custom category deleted successfully"}},"summary":"Delete a custom category","tags":["Custom Category"]}},"/api/custom-category/{categoryId}/options":{"post":{"operationId":"CustomCategoryController_createOption","parameters":[{"name":"categoryId","required":true,"in":"path","description":"Category ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomCategoryOptionDto"}}}},"responses":{"201":{"description":"Custom category option created successfully"}},"summary":"Create a new option for a custom category","tags":["Custom Category"]}},"/api/custom-category/{categoryId}/options/{optionId}":{"patch":{"operationId":"CustomCategoryController_updateOption","parameters":[{"name":"categoryId","required":true,"in":"path","description":"Category ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"optionId","required":true,"in":"path","description":"Option ID","schema":{"example":"cmieqoaba0000iymt4fab0346","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomCategoryOptionDto"}}}},"responses":{"200":{"description":"Custom category option updated successfully"}},"summary":"Update a custom category option","tags":["Custom Category"]},"delete":{"operationId":"CustomCategoryController_deleteOption","parameters":[{"name":"categoryId","required":true,"in":"path","description":"Category ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"optionId","required":true,"in":"path","description":"Option ID","schema":{"example":"cmieqoaba0000iymt4fab0346","type":"string"}}],"responses":{"200":{"description":"Custom category option deleted successfully"}},"summary":"Delete a custom category option","tags":["Custom Category"]}},"/api/organizations":{"post":{"operationId":"OrganizationController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrganizationDto"}}}},"responses":{"201":{"description":"Organization created successfully"},"403":{"description":"Forbidden - Super admin access required"},"409":{"description":"Conflict - Slug already exists"}},"summary":"Create a new organization","tags":["Organizations"]},"get":{"operationId":"OrganizationController_findAll","parameters":[{"name":"includeInactive","required":false,"in":"query","description":"Include inactive organizations in the response","schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of organizations"}},"summary":"Get all organizations (public)","tags":["Organizations"]}},"/api/organizations/check-slug/{slug}":{"get":{"operationId":"OrganizationController_checkSlug","parameters":[{"name":"slug","required":true,"in":"path","description":"Organization slug to check","schema":{"example":"my-organization","type":"string"}}],"responses":{"200":{"description":"Slug availability status"}},"summary":"Check if a slug is available","tags":["Organizations"]}},"/api/organizations/by-slug/{slug}":{"get":{"operationId":"OrganizationController_findBySlug","parameters":[{"name":"slug","required":true,"in":"path","description":"Organization slug","schema":{"example":"my-organization","type":"string"}}],"responses":{"200":{"description":"Organization details"},"404":{"description":"Organization not found"}},"summary":"Get organization by slug (public)","tags":["Organizations"]}},"/api/organizations/{id}":{"get":{"operationId":"OrganizationController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Organization ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Organization details"},"404":{"description":"Organization not found"}},"summary":"Get organization by ID","tags":["Organizations"]},"patch":{"operationId":"OrganizationController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Organization ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOrganizationDto"}}}},"responses":{"200":{"description":"Organization updated successfully"},"403":{"description":"Forbidden - Super admin access required"},"404":{"description":"Organization not found"}},"summary":"Update an organization (Super Admin only)","tags":["Organizations"]},"delete":{"operationId":"OrganizationController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Organization ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Organization deleted successfully"},"403":{"description":"Forbidden - Super admin access required"},"404":{"description":"Organization not found"},"409":{"description":"Conflict - Organization has users"}},"summary":"Delete an organization (Super Admin only)","tags":["Organizations"]}},"/api/organization-settings":{"get":{"operationId":"OrganizationSettingsController_getSettings","parameters":[],"responses":{"200":{"description":"Settings fetched successfully"}},"summary":"Get organization operational settings","tags":["Organization Settings"]},"patch":{"operationId":"OrganizationSettingsController_updateSettings","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOrganizationSettingsDto"}}}},"responses":{"200":{"description":"Settings updated successfully"}},"summary":"Update organization operational settings","tags":["Organization Settings"]}},"/api/organization-settings/app-version":{"get":{"operationId":"OrganizationSettingsController_getAppVersion","parameters":[{"name":"platform","required":false,"in":"query","description":"Platform the app is running on","schema":{"example":"ANDROID","type":"string","enum":["ANDROID","IOS"]}},{"name":"version","required":false,"in":"query","description":"Current app version name, e.g. \"4.0.2\"","schema":{"example":"4.0.2","type":"string"}}],"responses":{"200":{"description":"Force-update verdict for the caller"}},"summary":"Check whether the calling mobile app build must be updated (public)","tags":["Organization Settings"]}},"/api/organization-settings/logo":{"post":{"operationId":"OrganizationSettingsController_uploadLogo","parameters":[],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"image":{"type":"string","format":"binary"}}}}}},"responses":{"200":{"description":"Logo uploaded successfully"}},"summary":"Upload organization logo","tags":["Organization Settings"]},"delete":{"operationId":"OrganizationSettingsController_deleteLogo","parameters":[],"responses":{"200":{"description":"Logo deleted successfully"}},"summary":"Delete organization logo","tags":["Organization Settings"]}},"/api/dms/upload-sessions/limits":{"get":{"description":"So a client can validate against the real thresholds instead of a guessed constant.","operationId":"UploadSessionsController_getLimits","parameters":[],"responses":{"200":{"description":"Upload limits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadLimitsResponseDto"}}}}},"summary":"Get the server-configured upload size limits","tags":["DMS - Upload Sessions"]}},"/api/dms/upload-sessions":{"post":{"description":"Creates a new upload session and returns instructions for uploading the file based on its size.","operationId":"UploadSessionsController_createSession","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUploadSessionDto"}}}},"responses":{"201":{"description":"Upload session created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadSessionResponseDto"}}}}},"summary":"Create an upload session","tags":["DMS - Upload Sessions"]}},"/api/dms/upload-sessions/{id}":{"get":{"description":"Returns the current status of an upload session.","operationId":"UploadSessionsController_getSessionStatus","parameters":[{"name":"id","required":true,"in":"path","description":"Upload session ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Upload session status retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadSessionStatusResponseDto"}}}}},"summary":"Get upload session status","tags":["DMS - Upload Sessions"]}},"/api/dms/upload-sessions/{id}/file":{"post":{"description":"Upload a file directly to the server. Only available for INLINE upload mode.","operationId":"UploadSessionsController_uploadFile","parameters":[{"name":"id","required":true,"in":"path","description":"Upload session ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"200":{"description":"File uploaded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentResponseDto"}}}}},"summary":"Upload file (inline mode)","tags":["DMS - Upload Sessions"]}},"/api/dms/upload-sessions/{id}/confirm-upload":{"post":{"description":"Confirms that a file has been uploaded directly to storage. Only available for DIRECT_PUT mode.","operationId":"UploadSessionsController_confirmUpload","parameters":[{"name":"id","required":true,"in":"path","description":"Upload session ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Upload confirmed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentResponseDto"}}}}},"summary":"Confirm direct PUT upload","tags":["DMS - Upload Sessions"]}},"/api/dms/upload-sessions/{id}/parts/{partNumber}":{"get":{"description":"Returns a presigned URL for uploading a specific part. Only available for MULTIPART mode.","operationId":"UploadSessionsController_getPartUrl","parameters":[{"name":"id","required":true,"in":"path","description":"Upload session ID","schema":{"type":"string"}},{"name":"partNumber","required":true,"in":"path","description":"Part number (1-indexed)","schema":{"type":"string"}}],"responses":{"200":{"description":"Part URL generated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartUrlResponseDto"}}}}},"summary":"Get presigned URL for multipart part","tags":["DMS - Upload Sessions"]}},"/api/dms/upload-sessions/{id}/complete":{"post":{"description":"Completes a multipart upload with the provided part ETags. Only available for MULTIPART mode.","operationId":"UploadSessionsController_completeMultipartUpload","parameters":[{"name":"id","required":true,"in":"path","description":"Upload session ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteMultipartUploadDto"}}}},"responses":{"200":{"description":"Multipart upload completed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentResponseDto"}}}}},"summary":"Complete multipart upload","tags":["DMS - Upload Sessions"]}},"/api/dms/upload-sessions/{id}/abort":{"post":{"description":"Aborts an in-progress upload session.","operationId":"UploadSessionsController_abortUpload","parameters":[{"name":"id","required":true,"in":"path","description":"Upload session ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Upload session aborted successfully"}},"summary":"Abort upload session","tags":["DMS - Upload Sessions"]}},"/api/dms/entities/{entityType}/{entityId}/documents":{"get":{"description":"Returns all documents linked to a specific entity.","operationId":"DocumentsController_findByEntity","parameters":[{"name":"entityType","required":true,"in":"path","description":"Entity type (e.g., lead, participant)","schema":{"type":"string"}},{"name":"entityId","required":true,"in":"path","description":"Entity ID","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"documentTypeId","required":false,"in":"query","description":"Filter by document type ID (CustomCategoryOption)","schema":{"example":"clxyz123456789","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by document status","schema":{"example":"AVAILABLE","type":"string","enum":["DRAFT","UPLOADING","AVAILABLE","FAILED","QUARANTINED","ARCHIVED","DELETED"]}},{"name":"restricted","required":false,"in":"query","description":"Filter by restricted flag (requires documents.restricted_view permission)","schema":{"example":false,"type":"boolean"}},{"name":"dateFrom","required":false,"in":"query","description":"Filter by uploaded after this date","schema":{"example":"2024-01-01","type":"string"}},{"name":"dateTo","required":false,"in":"query","description":"Filter by uploaded before this date","schema":{"example":"2024-12-31","type":"string"}},{"name":"uploadedBy","required":false,"in":"query","description":"Filter by uploader user ID","schema":{"example":"cluser123456789","type":"string"}},{"name":"linkRole","required":false,"in":"query","description":"Filter by link role","schema":{"example":"primary","type":"string"}},{"name":"includeDeleted","required":false,"in":"query","description":"Include deleted documents","schema":{"default":false,"example":false,"type":"boolean"}},{"name":"includeArchived","required":false,"in":"query","description":"Include archived documents in the result set","schema":{"default":false,"example":false,"type":"boolean"}}],"responses":{"200":{"description":"Documents retrieved successfully"}},"summary":"List documents by entity","tags":["DMS - Documents"]}},"/api/dms/documents/{id}":{"get":{"description":"Returns detailed information about a document.","operationId":"DocumentsController_findById","parameters":[{"name":"id","required":true,"in":"path","description":"Document ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Document retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentResponseDto"}}}}},"summary":"Get document by ID","tags":["DMS - Documents"]},"patch":{"description":"Updates mutable document fields like displayName, documentType, tags, etc.","operationId":"DocumentsController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Document ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDocumentDto"}}}},"responses":{"200":{"description":"Document updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentResponseDto"}}}}},"summary":"Update document metadata","tags":["DMS - Documents"]},"delete":{"description":"Marks a document as deleted. Can be restored later.","operationId":"DocumentsController_delete","parameters":[{"name":"id","required":true,"in":"path","description":"Document ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Document deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentResponseDto"}}}}},"summary":"Soft delete document","tags":["DMS - Documents"]}},"/api/dms/documents/{id}/restore":{"post":{"description":"Restores a soft-deleted document.","operationId":"DocumentsController_restore","parameters":[{"name":"id","required":true,"in":"path","description":"Document ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Document restored successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentResponseDto"}}}}},"summary":"Restore deleted document","tags":["DMS - Documents"]}},"/api/dms/documents/{id}/archive":{"patch":{"description":"Marks a document as archived. Use for superseded records such as older care plans that have been reviewed and replaced.","operationId":"DocumentsController_archive","parameters":[{"name":"id","required":true,"in":"path","description":"Document ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArchiveDocumentDto"}}}},"responses":{"200":{"description":"Document archived successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentResponseDto"}}}}},"summary":"Archive a document","tags":["DMS - Documents"]}},"/api/dms/documents/{id}/unarchive":{"patch":{"description":"Restores an archived document back to AVAILABLE status.","operationId":"DocumentsController_unarchive","parameters":[{"name":"id","required":true,"in":"path","description":"Document ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Document unarchived successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentResponseDto"}}}}},"summary":"Unarchive a document","tags":["DMS - Documents"]}},"/api/dms/documents/{id}/download-url":{"get":{"description":"Returns a short-lived signed URL for downloading the document.","operationId":"DocumentsController_getDownloadUrl","parameters":[{"name":"id","required":true,"in":"path","description":"Document ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Download URL generated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadUrlResponseDto"}}}}},"summary":"Get download URL","tags":["DMS - Documents"]}},"/api/dms/documents/{id}/preview-url":{"get":{"description":"Returns a short-lived signed URL for previewing the document inline.","operationId":"DocumentsController_getPreviewUrl","parameters":[{"name":"id","required":true,"in":"path","description":"Document ID","schema":{"type":"string"}},{"name":"size","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Preview URL generated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DownloadUrlResponseDto"}}}}},"summary":"Get preview URL","tags":["DMS - Documents"]}},"/api/dms/documents/{id}/links":{"post":{"description":"Links a document to an additional entity.","operationId":"DocumentsController_addLink","parameters":[{"name":"id","required":true,"in":"path","description":"Document ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddDocumentLinkDto"}}}},"responses":{"201":{"description":"Link added successfully"}},"summary":"Add link to document","tags":["DMS - Documents"]}},"/api/dms/documents/{documentId}/links/{linkId}":{"delete":{"description":"Removes a link between a document and an entity.","operationId":"DocumentsController_removeLink","parameters":[{"name":"documentId","required":true,"in":"path","description":"Document ID","schema":{"type":"string"}},{"name":"linkId","required":true,"in":"path","description":"Link ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Link removed successfully"}},"summary":"Remove link from document","tags":["DMS - Documents"]}},"/api/audit":{"get":{"operationId":"AuditController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"entityType","required":false,"in":"query","description":"Filter by entity type (e.g., lead, note, booking)","schema":{"example":"lead","type":"string"}},{"name":"entityId","required":false,"in":"query","description":"Filter by specific entity ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"action","required":false,"in":"query","description":"Filter by action (e.g., leads.create, leads.status_change)","schema":{"example":"leads.create","type":"string"}},{"name":"actorUserId","required":false,"in":"query","description":"Filter by actor user ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"dateFrom","required":false,"in":"query","description":"Filter audit logs from this date","schema":{"example":"2024-01-01","type":"string"}},{"name":"dateTo","required":false,"in":"query","description":"Filter audit logs to this date","schema":{"example":"2024-12-31","type":"string"}}],"responses":{"200":{"description":"Audit logs fetched successfully"}},"summary":"Get all audit logs (admin-only)","tags":["Audit"]}},"/api/audit/entity/{entityType}/{entityId}":{"get":{"operationId":"AuditController_findByEntity","parameters":[{"name":"entityType","required":true,"in":"path","description":"The type of entity (e.g., lead, note)","schema":{"example":"lead","type":"string"}},{"name":"entityId","required":true,"in":"path","description":"The ID of the entity","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Entity audit trail fetched successfully"}},"summary":"Get audit trail for a specific entity","tags":["Audit"]}},"/api/audit/re-enrich":{"post":{"operationId":"AuditController_reEnrich","parameters":[],"responses":{"200":{"description":"Audit logs re-enriched successfully"}},"summary":"Re-enrich all audit logs (admin-only)","tags":["Audit"]}},"/api/role":{"get":{"operationId":"RoleController_findAll","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"name","required":false,"in":"query","description":"The name of the role","schema":{"example":"Admin","type":"string"}},{"name":"description","required":false,"in":"query","description":"The description of the role","schema":{"example":"Administrator role with full access","type":"string"}}],"responses":{"200":{"description":"Roles fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllRoleDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"Get all roles","tags":["Role"]},"post":{"operationId":"RoleController_createRole","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRoleDto"}}}},"responses":{"201":{"description":"Role created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleRoleDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"Create a new role","tags":["Role"]}},"/api/role/{id}":{"get":{"operationId":"RoleController_findOne","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","description":"Role ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Role fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleRoleDto"}}}},"404":{"description":"Role not found"}},"security":[{"bearer-auth":[]}],"summary":"Get a single role","tags":["Role"]},"patch":{"operationId":"RoleController_updateRole","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","description":"Role ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRoleDto"}}}},"responses":{"200":{"description":"Role updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleRoleDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"Update a role","tags":["Role"]},"delete":{"operationId":"RoleController_deleteRole","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","description":"Role ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Role deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleRoleDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"Delete a role","tags":["Role"]}},"/api/role/{id}/permissions/add":{"post":{"operationId":"RoleController_addPermissionsToRole","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","description":"Role ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManageRolePermissionsDto"}}}},"responses":{"200":{"description":"Permissions added to role successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleRoleDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"Add permissions to a role","tags":["Role"]}},"/api/role/{id}/permissions/remove":{"post":{"operationId":"RoleController_removePermissionsFromRole","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","description":"Role ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManageRolePermissionsDto"}}}},"responses":{"200":{"description":"Permissions removed from role successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleRoleDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"Remove permissions from a role","tags":["Role"]}},"/api/permissions":{"get":{"operationId":"PermissionController_findAll","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"name","required":false,"in":"query","description":"The name of the permission","schema":{"example":"leads.read","type":"string"}},{"name":"description","required":false,"in":"query","description":"The description of the permission","schema":{"example":"Permission to read leads","type":"string"}}],"responses":{"200":{"description":"Permissions fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllPermissionDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"Get all permissions","tags":["Permission"]}},"/api/permissions/catalogue":{"get":{"operationId":"PermissionController_catalogue","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}}],"responses":{"200":{"description":""}},"security":[{"bearer-auth":[]}],"summary":"Permissions grouped into areas for the roles screen","tags":["Permission"]}},"/api/permissions/{id}":{"get":{"operationId":"PermissionController_findOne","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","description":"Permission ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Permission fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSinglePermissionDto"}}}},"404":{"description":"Permission not found"}},"security":[{"bearer-auth":[]}],"summary":"Get a single permission","tags":["Permission"]}},"/api/address/autocomplete":{"get":{"description":"Proxies Google Places Autocomplete API. Pass an optional sessionToken (UUID) to group autocomplete + details calls for billing optimization.","operationId":"AddressController_autocomplete","parameters":[{"name":"input","required":true,"in":"query","description":"Search input for address autocomplete","schema":{"minLength":2,"maxLength":100,"example":"123 Collins St","type":"string"}},{"name":"country","required":false,"in":"query","description":"ISO 3166-1 alpha-2 country code to restrict results. Defaults to AU.","schema":{"minLength":2,"maxLength":2,"default":"AU","example":"AU","type":"string"}},{"name":"sessionToken","required":false,"in":"query","description":"Session token (UUID) to group autocomplete + details calls for billing","schema":{"example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","type":"string"}}],"responses":{"200":{"description":"Address suggestions fetched successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AddressSuggestionResponseDto"}}}}}},"summary":"Search for address suggestions","tags":["Address"]}},"/api/address/place-details":{"get":{"description":"Proxies Google Place Details API. Returns structured address components and geo coordinates.","operationId":"AddressController_placeDetails","parameters":[{"name":"placeId","required":true,"in":"query","description":"Google Place ID to retrieve details for","schema":{"example":"ChIJN1t_tDeuEmsRUsoyG83frY4","type":"string"}}],"responses":{"200":{"description":"Address details fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressDetailsResponseDto"}}}}},"summary":"Get full address details for a place","tags":["Address"]}},"/api/contracts/templates":{"post":{"operationId":"ContractTemplateController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContractTemplateDto"}}}},"responses":{"201":{"description":"Template registered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractTemplateResponseDto"}}}}},"summary":"Register a new contract template","tags":["Contracts - Templates"]},"get":{"operationId":"ContractTemplateController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by status","schema":{"example":"ACTIVE","type":"string","enum":["ACTIVE","ARCHIVED"]}}],"responses":{"200":{"description":"Templates fetched successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContractTemplateResponseDto"}}}}}},"summary":"List all contract templates","tags":["Contracts - Templates"]}},"/api/contracts/templates/{id}":{"get":{"operationId":"ContractTemplateController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Template ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Template fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractTemplateResponseDto"}}}},"404":{"description":"Template not found"}},"summary":"Get a contract template by ID","tags":["Contracts - Templates"]},"patch":{"operationId":"ContractTemplateController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Template ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContractTemplateDto"}}}},"responses":{"200":{"description":"Template updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractTemplateResponseDto"}}}}},"summary":"Update a contract template","tags":["Contracts - Templates"]},"delete":{"operationId":"ContractTemplateController_delete","parameters":[{"name":"id","required":true,"in":"path","description":"Template ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"deleteFromProvider","required":false,"in":"query","description":"Also delete from eSignatures.com provider","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Template deleted successfully"}},"summary":"Delete/archive a contract template","tags":["Contracts - Templates"]}},"/api/contracts/templates/{id}/sync":{"post":{"operationId":"ContractTemplateController_sync","parameters":[{"name":"id","required":true,"in":"path","description":"Template ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Template synced successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractTemplateResponseDto"}}}}},"summary":"Sync template metadata from eSignatures.com","tags":["Contracts - Templates"]}},"/api/contracts/config":{"get":{"operationId":"ConfigController_getConfig","parameters":[],"responses":{"200":{"description":"Configuration status fetched successfully"}},"summary":"Get eSignatures.com configuration status","tags":["Contracts - Configuration"]},"post":{"operationId":"ConfigController_saveConfig","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveConfigDto"}}}},"responses":{"200":{"description":"Configuration saved successfully"}},"summary":"Save eSignatures.com configuration","tags":["Contracts - Configuration"]},"delete":{"operationId":"ConfigController_deleteConfig","parameters":[],"responses":{"200":{"description":"Configuration deleted successfully"}},"summary":"Delete eSignatures.com configuration","tags":["Contracts - Configuration"]}},"/api/contracts":{"post":{"operationId":"ContractController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContractDto"}}}},"responses":{"201":{"description":"Contract created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractResponseDto"}}}}},"summary":"Create a new contract from a template","tags":["Contracts"]},"get":{"operationId":"ContractController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by status","schema":{"example":"SENT","type":"string","enum":["DRAFT","SENT","VIEWED","SIGNED","DECLINED","WITHDRAWN"]}},{"name":"templateId","required":false,"in":"query","description":"Filter by template ID","schema":{"example":"clx1234567890","type":"string"}}],"responses":{"200":{"description":"Contracts fetched successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContractResponseDto"}}}}}},"summary":"List all contracts","tags":["Contracts"]}},"/api/contracts/{id}":{"get":{"operationId":"ContractController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Contract ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Contract fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractResponseDto"}}}},"404":{"description":"Contract not found"}},"summary":"Get a contract by ID","tags":["Contracts"]}},"/api/contracts/{id}/withdraw":{"post":{"operationId":"ContractController_withdraw","parameters":[{"name":"id","required":true,"in":"path","description":"Contract ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Contract withdrawn successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractResponseDto"}}}}},"summary":"Withdraw a contract","tags":["Contracts"]}},"/api/contracts/{id}/generate-preview":{"post":{"operationId":"ContractController_generatePreview","parameters":[{"name":"id","required":true,"in":"path","description":"Contract ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"PDF preview generation requested"}},"summary":"Request PDF preview generation","tags":["Contracts"]}},"/api/contracts/{id}/refresh":{"post":{"operationId":"ContractController_refresh","parameters":[{"name":"id","required":true,"in":"path","description":"Contract ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Contract refreshed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractResponseDto"}}}}},"summary":"Refresh contract data from eSignatures.com","tags":["Contracts"]}},"/api/contracts/{id}/signers/{signerId}/resend":{"post":{"operationId":"ContractController_resend","parameters":[{"name":"id","required":true,"in":"path","description":"Contract ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"signerId","required":true,"in":"path","description":"Signer ID","schema":{"example":"clxsigner123","type":"string"}}],"responses":{"200":{"description":"Contract resent successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendContractResponseDto"}}}}},"summary":"Resend contract to a signer","tags":["Contracts"]}},"/api/notes":{"get":{"operationId":"NoteController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"includeRelated","required":false,"in":"query","description":"Include notes where this entity is not the primary context","schema":{"default":true,"example":true,"type":"boolean"}},{"name":"noteTypeOptionId","required":false,"in":"query","description":"Filter by note type option ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"visibility","required":false,"in":"query","description":"Filter by visibility","schema":{"example":"all","type":"string","enum":["all","internal","client_visible"]}},{"name":"pinnedFirst","required":false,"in":"query","description":"Sort pinned notes to the top","schema":{"default":true,"example":true,"type":"boolean"}},{"name":"sourceOptionId","required":false,"in":"query","description":"Filter by source option ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"ownerId","required":false,"in":"query","description":"Filter by createdByUserId (owner)","schema":{"example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"dateFrom","required":false,"in":"query","description":"Filter notes created after this date","schema":{"example":"2024-01-01","type":"string"}},{"name":"dateTo","required":false,"in":"query","description":"Filter notes created before this date","schema":{"example":"2024-12-31","type":"string"}},{"name":"entityType","required":false,"in":"query","description":"Filter by linked entity type","schema":{"example":"LEAD","type":"string","enum":["LEAD","PARTICIPANT","PARTNER","STAFF","PROVIDER"]}}],"responses":{"200":{"description":"Notes fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllNoteDto"}}}}},"summary":"Get all notes (global list)","tags":["Notes"]},"post":{"operationId":"NoteController_createNote","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNoteDto"}}}},"responses":{"201":{"description":"Note created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNoteResponseDto"}}}}},"summary":"Create a new note with entity links","tags":["Notes"]}},"/api/notes/{id}":{"get":{"operationId":"NoteController_findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Note fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleNoteDto"}}}}},"summary":"Get a single note by ID","tags":["Notes"]},"patch":{"operationId":"NoteController_updateNote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateNoteDto"}}}},"responses":{"200":{"description":"Note updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleNoteDto"}}}}},"summary":"Update a note","tags":["Notes"]},"delete":{"operationId":"NoteController_deleteNote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Note deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleNoteDto"}}}}},"summary":"Soft delete a note","tags":["Notes"]}},"/api/notes/{noteId}/links":{"post":{"operationId":"NoteController_addLinks","parameters":[{"name":"noteId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddNoteLinksDto"}}}},"responses":{"201":{"description":"Links added successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleNoteDto"}}}}},"summary":"Add entity links to a note","tags":["Notes"]}},"/api/notes/{noteId}/links/{linkId}":{"delete":{"operationId":"NoteController_removeLink","parameters":[{"name":"noteId","required":true,"in":"path","schema":{"type":"string"}},{"name":"linkId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Link removed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleNoteDto"}}}}},"summary":"Remove an entity link from a note","tags":["Notes"]}},"/api/notes/{noteId}/links/{linkId}/pin":{"patch":{"operationId":"NoteController_togglePinInContext","parameters":[{"name":"noteId","required":true,"in":"path","schema":{"type":"string"}},{"name":"linkId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TogglePinInContextDto"}}}},"responses":{"200":{"description":"Pin status updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleNoteDto"}}}}},"summary":"Toggle pin status for a note in a specific context","tags":["Notes"]}},"/api/notes/entity/{entityType}/{entityId}":{"post":{"operationId":"NoteController_createForEntity","parameters":[{"name":"entityId","required":true,"in":"path","description":"The ID of the entity","schema":{"type":"string"}},{"name":"entityType","required":true,"in":"path","description":"The type of entity (lead, participant, partner, staff, provider)","schema":{"enum":["lead","participant","partner","staff","provider"],"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEntityNoteDto"}}}},"responses":{"201":{"description":"Note created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNoteResponseDto"}}}}},"summary":"Create a note for a specific entity (auto-linked)","tags":["Notes"]},"get":{"operationId":"NoteController_findByEntity","parameters":[{"name":"entityId","required":true,"in":"path","description":"The ID of the entity","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"includeRelated","required":false,"in":"query","description":"Include notes where this entity is not the primary context","schema":{"default":true,"example":true,"type":"boolean"}},{"name":"noteTypeOptionId","required":false,"in":"query","description":"Filter by note type option ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"visibility","required":false,"in":"query","description":"Filter by visibility","schema":{"example":"all","type":"string","enum":["all","internal","client_visible"]}},{"name":"pinnedFirst","required":false,"in":"query","description":"Sort pinned notes to the top","schema":{"default":true,"example":true,"type":"boolean"}},{"name":"sourceOptionId","required":false,"in":"query","description":"Filter by source option ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"ownerId","required":false,"in":"query","description":"Filter by createdByUserId (owner)","schema":{"example":"123e4567-e89b-12d3-a456-426614174000","type":"string"}},{"name":"dateFrom","required":false,"in":"query","description":"Filter notes created after this date","schema":{"example":"2024-01-01","type":"string"}},{"name":"dateTo","required":false,"in":"query","description":"Filter notes created before this date","schema":{"example":"2024-12-31","type":"string"}},{"name":"entityType","required":true,"in":"path","description":"The type of entity (lead, participant, partner, staff, provider)","schema":{"enum":["lead","participant","partner","staff","provider"],"type":"string"}}],"responses":{"200":{"description":"Notes fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityNotesResponseDto"}}}}},"summary":"Get notes for a specific entity","tags":["Notes"]}},"/api/note-templates":{"post":{"operationId":"NoteTemplatesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNoteTemplateDto"}}}},"responses":{"201":{"description":"Template created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteTemplateResponseDto"}}}}},"summary":"Create a new note template with initial version","tags":["Note Templates"]},"get":{"operationId":"NoteTemplatesController_findAll","parameters":[{"name":"noteType","required":false,"in":"query","description":"Filter by note type","schema":{"example":"SHIFT","type":"string","enum":["SHIFT","SOAP","GENERAL"]}},{"name":"scope","required":false,"in":"query","description":"Filter by scope","schema":{"example":"ORG","type":"string","enum":["SYSTEM","ORG","PARTICIPANT"]}},{"name":"participantId","required":false,"in":"query","description":"Filter by participant ID (for participant-specific templates)","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"isActive","required":false,"in":"query","description":"Filter by active status","schema":{"example":true,"type":"boolean"}},{"name":"search","required":false,"in":"query","description":"Search in template name and description","schema":{"example":"shift","type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number (1-based)","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"default":20,"example":20,"type":"number"}}],"responses":{"200":{"description":"Templates fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteTemplateResponseDto"}}}}},"summary":"List note templates with filters","tags":["Note Templates"]}},"/api/note-templates/input-types":{"get":{"operationId":"NoteTemplatesController_getInputTypes","parameters":[],"responses":{"200":{"description":"Input types fetched successfully"}},"summary":"Get list of allowed form input types for template questions","tags":["Note Templates"]}},"/api/note-templates/org-defaults":{"get":{"operationId":"NoteTemplatesController_findOrgDefaults","parameters":[],"responses":{"200":{"description":"Org-wide defaults fetched successfully"}},"summary":"List org-wide default template assignments","tags":["Note Templates"]},"post":{"operationId":"NoteTemplatesController_setOrgDefault","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignTemplateDto"}}}},"responses":{"201":{"description":"Org-wide default set successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteTemplateAssignmentResponseDto"}}}}},"summary":"Set an org-wide default template for a note type","tags":["Note Templates"]}},"/api/note-templates/org-defaults/{id}":{"delete":{"operationId":"NoteTemplatesController_removeOrgDefault","parameters":[{"name":"id","required":true,"in":"path","description":"Assignment ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Org-wide default removed successfully"}},"summary":"Remove an org-wide default assignment","tags":["Note Templates"]}},"/api/note-templates/{id}":{"get":{"operationId":"NoteTemplatesController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Template ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Template fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteTemplateResponseDto"}}}}},"summary":"Get a note template with versions","tags":["Note Templates"]},"patch":{"operationId":"NoteTemplatesController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Template ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Template updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteTemplateResponseDto"}}}}},"summary":"Update template metadata","tags":["Note Templates"]}},"/api/note-templates/{id}/versions":{"post":{"operationId":"NoteTemplatesController_createVersion","parameters":[{"name":"id","required":true,"in":"path","description":"Template ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTemplateVersionDto"}}}},"responses":{"201":{"description":"Version created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteTemplateVersionResponseDto"}}}}},"summary":"Create a new version of the template","tags":["Note Templates"]}},"/api/user/team":{"post":{"operationId":"UserController_createTeamMember","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTeamMemberDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer-auth":[]}],"summary":"Add a team member with a password and a role","tags":["User"]}},"/api/user/{id}/password":{"post":{"operationId":"UserController_setPassword","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetMemberPasswordDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer-auth":[]}],"summary":"Set a team member's password","tags":["User"]}},"/api/user/{id}/role":{"post":{"operationId":"UserController_setRole","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetUserRoleDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer-auth":[]}],"summary":"Set a team member's role (replaces their other staff roles)","tags":["User"]}},"/api/user/{id}/deactivate":{"post":{"operationId":"UserController_deactivate","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"security":[{"bearer-auth":[]}],"summary":"Stop a team member signing in (their history is kept)","tags":["User"]}},"/api/user/{id}/reactivate":{"post":{"operationId":"UserController_reactivate","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"security":[{"bearer-auth":[]}],"summary":"Let a deactivated team member sign in again","tags":["User"]}},"/api/user/me":{"get":{"operationId":"UserController_getMyProfile","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}}],"responses":{"200":{"description":"Profile retrieved successfully"}},"security":[{"bearer-auth":[]}],"summary":"Get current user profile with role-specific data","tags":["User"]},"patch":{"description":"Self-service update of basic user fields (name, avatar). Email, phone, password, and role/account-type changes are not accepted here — they require admin or OTP-verified flows.","operationId":"UserController_updateMyProfile","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMyUserDto"}}}},"responses":{"200":{"description":"Profile updated successfully"}},"security":[{"bearer-auth":[]}],"summary":"Update own user record","tags":["User"]}},"/api/user":{"get":{"operationId":"UserController_findAll","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"name","required":false,"in":"query","description":"The name of the user","schema":{"example":"John Doe","type":"string"}},{"name":"email","required":false,"in":"query","description":"The email of the user","schema":{"example":"john@example.com","type":"string"}},{"name":"username","required":false,"in":"query","description":"The username of the user","schema":{"example":"johndoe","type":"string"}},{"name":"accountType","required":false,"in":"query","description":"Filter by account type","schema":{"example":"STAFF","type":"string","enum":["ADMIN","STAFF","PARTICIPANT","SUPPORT_COORDINATOR","GUARDIAN","PARTNER","OWNER","TENANT"]}},{"name":"onboardingStatus","required":false,"in":"query","description":"Filter by onboarding status","schema":{"example":"ACTIVE","type":"string","enum":["PENDING","ACTIVE","SUSPENDED"]}},{"name":"archivedOnly","required":false,"in":"query","description":"Show only archived (soft-deleted) users","schema":{"example":true,"type":"boolean"}},{"name":"teamOnly","required":false,"in":"query","description":"Only team members (Administrator and staff accounts)","schema":{"example":true,"type":"boolean"}}],"responses":{"200":{"description":"Users fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllUserDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"Get all users","tags":["User"]},"post":{"operationId":"UserController_create","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserDto"}}}},"responses":{"201":{"description":"User created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleUserDto"}}}},"409":{"description":"User with this email already exists"}},"security":[{"bearer-auth":[]}],"summary":"Create a new user","tags":["User"]}},"/api/user/{id}":{"get":{"operationId":"UserController_findOne","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","description":"User ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"User fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleUserDto"}}}},"404":{"description":"User not found"}},"security":[{"bearer-auth":[]}],"summary":"Get a single user","tags":["User"]},"patch":{"description":"Update user profile fields including name, image, accountType, and onboardingStatus","operationId":"UserController_update","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","description":"User ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserDto"}}}},"responses":{"200":{"description":"User updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleUserDto"}}}},"404":{"description":"User not found"}},"security":[{"bearer-auth":[]}],"summary":"Update a user","tags":["User"]},"delete":{"description":"Soft-deletes a user. If the user has linked staff/participant entities, returns 409 with details unless force: true is provided. Use archiveLinkedEntities: true to cascade-archive linked entities before deletion.","operationId":"UserController_delete","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","description":"User ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"force","required":false,"in":"query","description":"Confirm deletion despite linked entities","schema":{"default":false,"type":"boolean"}},{"name":"archiveLinkedEntities","required":false,"in":"query","description":"Cascade-archive linked staff/participant entities before deleting the user","schema":{"default":false,"type":"boolean"}}],"responses":{"200":{"description":"User deleted successfully"},"404":{"description":"User not found"},"409":{"description":"User has linked entities — use force to proceed"}},"security":[{"bearer-auth":[]}],"summary":"Delete a user and all related data","tags":["User"]}},"/api/user/invite":{"post":{"operationId":"UserController_invite","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteUserDto"}}}},"responses":{"201":{"description":"Invite created"}},"security":[{"bearer-auth":[]}],"summary":"Invite a staff, owner, or tenant user","tags":["User"]}},"/api/user/{id}/restore":{"post":{"description":"Restores a soft-deleted user by clearing deletedAt and reversing email/username masking.","operationId":"UserController_restore","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","description":"User ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"restoreLinkedEntities","required":false,"in":"query","description":"Cascade-restore linked staff/participant entities that were archived alongside this user","schema":{"default":false,"type":"boolean"}}],"responses":{"200":{"description":"User restored successfully"},"404":{"description":"Archived user not found"},"409":{"description":"Another user with this email already exists"}},"security":[{"bearer-auth":[]}],"summary":"Restore an archived user","tags":["User"]}},"/api/user/{id}/roles/add":{"post":{"operationId":"UserController_assignRoles","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","description":"User ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManageUserRolesDto"}}}},"responses":{"200":{"description":"Roles assigned to user successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleUserDto"}}}},"400":{"description":"Invalid role IDs or already assigned"},"404":{"description":"User not found"}},"security":[{"bearer-auth":[]}],"summary":"Assign roles to a user","tags":["User"]}},"/api/user/{id}/roles/remove":{"post":{"operationId":"UserController_removeRoles","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string","example":"cmieqoaba0000iymt4fab0345"}},{"name":"id","required":true,"in":"path","description":"User ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManageUserRolesDto"}}}},"responses":{"200":{"description":"Roles removed from user successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleUserDto"}}}},"400":{"description":"Roles not assigned to user"},"404":{"description":"User not found"}},"security":[{"bearer-auth":[]}],"summary":"Remove roles from a user","tags":["User"]}},"/api/conversations":{"get":{"operationId":"ConversationController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string","enum":["updatedAt","lastMessageAt","createdAt"]}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"channel","required":false,"in":"query","schema":{"type":"string","enum":["SMS","EMAIL","CALL","CHAT"]}},{"name":"status","required":false,"in":"query","description":"Filter by status (multiple)","schema":{"type":"array","items":{"type":"string","enum":["OPEN","CLOSED"]}}},{"name":"assignedToUserId","required":false,"in":"query","schema":{"type":"string"}},{"name":"entityType","required":false,"in":"query","schema":{"type":"string","enum":["LEAD","PARTICIPANT","PARTNER","STAFF","PROVIDER","PROPERTY","TENANCY","OWNER","TENANT","SUPPLIER"]}},{"name":"entityId","required":false,"in":"query","schema":{"type":"string"}},{"name":"unreadOnly","required":false,"in":"query","schema":{"type":"boolean"}},{"name":"includeArchived","required":false,"in":"query","description":"Include archived conversations in results","schema":{"type":"boolean"}},{"name":"archivedOnly","required":false,"in":"query","description":"Return only archived conversations","schema":{"type":"boolean"}},{"name":"search","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllConversationsDto"}}}}},"summary":"List all conversations","tags":["Conversations"]},"post":{"operationId":"ConversationController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateConversationDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleConversationDto"}}}}},"summary":"Create a new conversation","tags":["Conversations"]}},"/api/conversations/{id}":{"get":{"operationId":"ConversationController_findById","parameters":[{"name":"id","required":true,"in":"path","description":"Conversation ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleConversationDto"}}}},"404":{"description":"Conversation not found"}},"summary":"Get a conversation by ID","tags":["Conversations"]},"patch":{"operationId":"ConversationController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Conversation ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateConversationDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleConversationDto"}}}}},"summary":"Update a conversation","tags":["Conversations"]}},"/api/conversations/{id}/archive":{"post":{"operationId":"ConversationController_archive","parameters":[{"name":"id","required":true,"in":"path","description":"Conversation ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleConversationDto"}}}}},"summary":"Archive a conversation","tags":["Conversations"]}},"/api/conversations/{id}/restore":{"post":{"operationId":"ConversationController_restore","parameters":[{"name":"id","required":true,"in":"path","description":"Conversation ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleConversationDto"}}}}},"summary":"Restore an archived conversation","tags":["Conversations"]}},"/api/conversations/{id}/timeline":{"get":{"operationId":"ConversationController_getTimeline","parameters":[{"name":"id","required":true,"in":"path","description":"Conversation ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"includeNotes","required":false,"in":"query","schema":{"default":true,"type":"boolean"}}],"responses":{"200":{"description":"Timeline retrieved"}},"summary":"Get conversation timeline","tags":["Conversations"]}},"/api/conversations/{id}/read":{"post":{"operationId":"ConversationController_markAsRead","parameters":[{"name":"id","required":true,"in":"path","description":"Conversation ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Conversation marked as read"}},"summary":"Mark conversation as read","tags":["Conversations"]}},"/api/conversations/{id}/links":{"post":{"operationId":"ConversationController_linkEntity","parameters":[{"name":"id","required":true,"in":"path","description":"Conversation ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkEntityDto"}}}},"responses":{"200":{"description":"Entity linked"}},"summary":"Link an entity to conversation","tags":["Conversations"]}},"/api/conversations/{id}/links/{linkId}":{"delete":{"operationId":"ConversationController_unlinkEntity","parameters":[{"name":"id","required":true,"in":"path","description":"Conversation ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"linkId","required":true,"in":"path","description":"Link ID","schema":{"example":"cmieqoaba0000iymt4fab0346","type":"string"}}],"responses":{"200":{"description":"Entity unlinked"}},"summary":"Unlink an entity from conversation","tags":["Conversations"]}},"/api/conversations/{id}/identifiers":{"post":{"operationId":"ConversationController_addContactIdentifier","parameters":[{"name":"id","required":true,"in":"path","description":"Conversation ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddContactIdentifierDto"}}}},"responses":{"200":{"description":"Contact identifier added"}},"summary":"Add contact identifier to conversation","tags":["Conversations"]}},"/api/conversations/{id}/identifiers/{identifierId}":{"delete":{"operationId":"ConversationController_removeContactIdentifier","parameters":[{"name":"id","required":true,"in":"path","description":"Conversation ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"identifierId","required":true,"in":"path","description":"Contact Identifier ID","schema":{"example":"cmieqoaba0000iymt4fab0347","type":"string"}}],"responses":{"200":{"description":"Contact identifier removed"}},"summary":"Remove contact identifier from conversation","tags":["Conversations"]}},"/api/conversations/{id}/notes":{"post":{"operationId":"ConversationController_addNote","parameters":[{"name":"id","required":true,"in":"path","description":"Conversation ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddNoteDto"}}}},"responses":{"200":{"description":"Note added"}},"summary":"Add internal note to conversation","tags":["Conversations"]}},"/api/messages/sms":{"post":{"operationId":"MessageController_sendSms","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendSmsDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleMessageDto"}}}}},"summary":"Send an SMS message","tags":["Messages"]}},"/api/messages/email":{"post":{"operationId":"MessageController_sendEmail","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleMessageDto"}}}}},"summary":"Send an email message","tags":["Messages"]}},"/api/conversations/{conversationId}/messages":{"get":{"operationId":"MessageController_findByConversation","parameters":[{"name":"conversationId","required":true,"in":"path","description":"Conversation ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"direction","required":false,"in":"query","schema":{"type":"string","enum":["IN","OUT"]}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["QUEUED","SENT","DELIVERED","FAILED","BOUNCED"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllMessagesDto"}}}}},"summary":"Get messages in a conversation","tags":["Messages"]}},"/api/conversations/{conversationId}/messages/sms":{"post":{"operationId":"MessageController_sendSmsInConversation","parameters":[{"name":"conversationId","required":true,"in":"path","description":"Conversation ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendSmsDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleMessageDto"}}}}},"summary":"Send SMS in a conversation","tags":["Messages"]}},"/api/conversations/{conversationId}/messages/email":{"post":{"operationId":"MessageController_sendEmailInConversation","parameters":[{"name":"conversationId","required":true,"in":"path","description":"Conversation ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleMessageDto"}}}}},"summary":"Send email in a conversation","tags":["Messages"]}},"/api/messages/call":{"post":{"operationId":"MessageController_logCall","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogCallDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleMessageDto"}}}}},"summary":"Log a phone call","tags":["Messages"]}},"/api/messages/{id}":{"get":{"operationId":"MessageController_findById","parameters":[{"name":"id","required":true,"in":"path","description":"Message ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleMessageDto"}}}},"404":{"description":"Message not found"}},"summary":"Get a message by ID","tags":["Messages"]}},"/api/communications/templates":{"get":{"operationId":"TemplateController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"type","required":false,"in":"query","description":"Filter by channel (email/sms)","schema":{"type":"string","enum":["SMS","EMAIL","CALL","CHAT"]}},{"name":"status","required":false,"in":"query","description":"Filter by status","schema":{"type":"string","enum":["DRAFT","APPROVED","ARCHIVED"]}},{"name":"search","required":false,"in":"query","description":"Search in name and description","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllTemplatesDto"}}}}},"summary":"List all templates","tags":["Communication Templates"]},"post":{"operationId":"TemplateController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCommunicationTemplateDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleTemplateDto"}}}}},"summary":"Create a new template","tags":["Communication Templates"]}},"/api/communications/templates/placeholders":{"get":{"operationId":"TemplateController_getPlaceholders","parameters":[],"responses":{"200":{"description":"Placeholders retrieved"}},"summary":"Get available template placeholders","tags":["Communication Templates"]}},"/api/communications/templates/{id}":{"get":{"operationId":"TemplateController_findById","parameters":[{"name":"id","required":true,"in":"path","description":"Template ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleTemplateDto"}}}},"404":{"description":"Template not found"}},"summary":"Get a template by ID","tags":["Communication Templates"]},"patch":{"operationId":"TemplateController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Template ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCommunicationTemplateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleTemplateDto"}}}}},"summary":"Update a template","tags":["Communication Templates"]}},"/api/communications/templates/{id}/approve":{"post":{"operationId":"TemplateController_approve","parameters":[{"name":"id","required":true,"in":"path","description":"Template ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleTemplateDto"}}}}},"summary":"Approve a template","tags":["Communication Templates"]}},"/api/communications/templates/{id}/archive":{"post":{"operationId":"TemplateController_archive","parameters":[{"name":"id","required":true,"in":"path","description":"Template ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleTemplateDto"}}}}},"summary":"Archive a template","tags":["Communication Templates"]}},"/api/communications/templates/{id}/new-version":{"post":{"operationId":"TemplateController_createNewVersion","parameters":[{"name":"id","required":true,"in":"path","description":"Template ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleTemplateDto"}}}}},"summary":"Create new version from approved template","tags":["Communication Templates"]}},"/api/communications/templates/{id}/preview":{"post":{"operationId":"TemplateController_preview","parameters":[{"name":"id","required":true,"in":"path","description":"Template ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewTemplateDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplatePreviewDto"}}}}},"summary":"Preview a template with entity data","tags":["Communication Templates"]}},"/api/communications/config/telnyx":{"get":{"operationId":"ConfigController_getTelnyxConfig","parameters":[],"responses":{"200":{"description":""}},"summary":"Get Telnyx configuration (masked)","tags":["Communication Config"]},"put":{"operationId":"ConfigController_updateTelnyxConfig","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelnyxConfigDto"}}}},"responses":{"200":{"description":""}},"summary":"Update Telnyx configuration","tags":["Communication Config"]}},"/api/communications/config/telnyx/test":{"post":{"operationId":"ConfigController_testTelnyxConfig","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestSmsDto"}}}},"responses":{"201":{"description":""}},"summary":"Send a test SMS to verify Telnyx configuration","tags":["Communication Config"]}},"/api/communications/config/sms/active":{"post":{"operationId":"ConfigController_setActiveSmsProvider","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetActiveSmsProviderDto"}}}},"responses":{"201":{"description":""}},"summary":"Set the active SMS provider for the org (Telnyx only — Twilio deprecated)","tags":["Communication Config"]}},"/api/communications/config/smtp":{"get":{"operationId":"ConfigController_getSmtpConfig","parameters":[],"responses":{"200":{"description":""}},"summary":"Get SMTP configuration (masked)","tags":["Communication Config"]},"put":{"operationId":"ConfigController_updateSmtpConfig","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmtpConfigDto"}}}},"responses":{"200":{"description":""}},"summary":"Update SMTP configuration","tags":["Communication Config"]}},"/api/communications/config/smtp/test":{"post":{"operationId":"ConfigController_testSmtpConnection","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestEmailDto"}}}},"responses":{"201":{"description":""}},"summary":"Test SMTP connection and optionally send a test email","tags":["Communication Config"]}},"/api/communications/config/status":{"get":{"operationId":"ConfigController_getConfigStatus","parameters":[],"responses":{"200":{"description":""}},"summary":"Get configuration status for all providers","tags":["Communication Config"]}},"/api/tenancies/{tenancyId}/messages":{"get":{"operationId":"TenancyMessagesController_list","parameters":[{"name":"tenancyId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"List a tenancy's comms log","tags":["Tenancies"]},"post":{"operationId":"TenancyMessagesController_send","parameters":[{"name":"tenancyId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendTenancyMessageDto"}}}},"responses":{"201":{"description":""}},"summary":"Log (and send if configured) a tenancy message","tags":["Tenancies"]}},"/api/tenancies/{tenancyId}/messages/preview":{"post":{"operationId":"TenancyMessagesController_preview","parameters":[{"name":"tenancyId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendTenancyMessageDto"}}}},"responses":{"201":{"description":""}},"summary":"Render a tenancy email without sending it or writing a message.","tags":["Tenancies"]}},"/api/stream/token":{"post":{"operationId":"StreamChatController_generateToken","parameters":[],"responses":{"201":{"description":""}},"security":[{"bearer-auth":[]}],"summary":"Generate Stream Chat user token","tags":["Stream Chat"]}},"/api/stream/users/search":{"get":{"operationId":"StreamChatController_searchUsers","parameters":[{"name":"query","required":false,"in":"query","description":"Search query for user name","schema":{"type":"string"}},{"name":"roles","required":false,"in":"query","description":"Filter by account types (comma-separated)","schema":{"example":"ADMIN,STAFF","type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer-auth":[]}],"summary":"Search users for chat (filtered by account type)","tags":["Stream Chat"]}},"/api/stream/channels/direct":{"post":{"operationId":"StreamChatController_createDirectChannel","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDirectChannelDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer-auth":[]}],"summary":"Create or get a direct 1:1 channel","tags":["Stream Chat"]}},"/api/stream/channels/group":{"post":{"operationId":"StreamChatController_createGroupChannel","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGroupChannelDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer-auth":[]}],"summary":"Create a group channel","tags":["Stream Chat"]}},"/api/stream/channels":{"get":{"operationId":"StreamChatController_listChannels","parameters":[],"responses":{"200":{"description":""}},"security":[{"bearer-auth":[]}],"summary":"List channel refs for the org","tags":["Stream Chat"]}},"/api/stream/channels/entity/{type}/{id}":{"get":{"operationId":"StreamChatController_getEntityChannels","parameters":[{"name":"type","required":true,"in":"path","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer-auth":[]}],"summary":"Get channels linked to a participant/staff","tags":["Stream Chat"]}},"/api/stream/channels/{id}/members":{"post":{"operationId":"StreamChatController_addMembers","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddChannelMembersDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer-auth":[]}],"summary":"Add members to a channel","tags":["Stream Chat"]}},"/api/stream/channels/{id}/members/{uid}":{"delete":{"operationId":"StreamChatController_removeMember","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"uid","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer-auth":[]}],"summary":"Remove a member from a channel","tags":["Stream Chat"]}},"/api/icon":{"get":{"operationId":"IconController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"icon","required":false,"in":"query","description":"Search term to filter icons by name","schema":{"example":"home","type":"string"}}],"responses":{"200":{"description":"Icons fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAllIconDto"}}}}},"summary":"Get all icons","tags":["Icon"]},"post":{"operationId":"IconController_createIcon","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIconDto"}}}},"responses":{"201":{"description":"Icon created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleIconDto"}}}}},"summary":"Create a new icon","tags":["Icon"]}},"/api/icon/{id}":{"get":{"operationId":"IconController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Icon ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Icon fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleIconDto"}}}},"404":{"description":"Icon not found"}},"summary":"Get a single icon","tags":["Icon"]},"patch":{"operationId":"IconController_updateIcon","parameters":[{"name":"id","required":true,"in":"path","description":"Icon ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateIconDto"}}}},"responses":{"200":{"description":"Icon updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleIconDto"}}}}},"summary":"Update an icon","tags":["Icon"]},"delete":{"operationId":"IconController_deleteIcon","parameters":[{"name":"id","required":true,"in":"path","description":"Icon ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Icon deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSingleIconDto"}}}}},"summary":"Delete an icon","tags":["Icon"]}},"/api/scheduler/jobs":{"get":{"operationId":"SchedulerController_getJobs","parameters":[],"responses":{"200":{"description":"Jobs retrieved successfully"}},"summary":"List all scheduled jobs","tags":["Scheduler"]}},"/api/scheduler/queue/stats":{"get":{"operationId":"SchedulerController_getQueueStats","parameters":[],"responses":{"200":{"description":"Stats retrieved successfully"}},"summary":"Get notification queue statistics","tags":["Scheduler"]}},"/api/scheduler/jobs/notification-sender/run":{"post":{"operationId":"SchedulerController_triggerNotificationSender","parameters":[],"responses":{"200":{"description":"Job triggered successfully"}},"summary":"Manually trigger notification processing","tags":["Scheduler"]}},"/api/scheduler/queue/metrics":{"get":{"operationId":"SchedulerController_getQueueMetrics","parameters":[],"responses":{"200":{"description":"Metrics retrieved successfully"}},"summary":"Get notification throughput metrics","tags":["Scheduler"]}},"/api/scheduler/health":{"get":{"operationId":"SchedulerController_health","parameters":[],"responses":{"200":{"description":"Scheduler is healthy"}},"summary":"Scheduler health check","tags":["Scheduler"]}},"/api/notifications/settings":{"get":{"description":"Returns all active notification types with their current enabled/disabled state and enabled channels for the organization.","operationId":"NotificationSettingController_getSettings","parameters":[],"responses":{"200":{"description":"Settings retrieved successfully"}},"summary":"Get notification settings","tags":["Notification Settings"]},"put":{"operationId":"NotificationSettingController_bulkUpdate","parameters":[],"responses":{"200":{"description":"Settings updated successfully"}},"summary":"Bulk update notification settings","tags":["Notification Settings"]}},"/api/notifications/settings/{notificationType}":{"put":{"operationId":"NotificationSettingController_updateSetting","parameters":[{"name":"notificationType","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Setting updated successfully"}},"summary":"Update a notification type setting","tags":["Notification Settings"]}},"/api/notifications/settings/reset":{"post":{"operationId":"NotificationSettingController_resetToDefaults","parameters":[],"responses":{"200":{"description":"Settings reset successfully"}},"summary":"Reset notification settings to defaults","tags":["Notification Settings"]}},"/api/notifications":{"get":{"operationId":"NotificationController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"unreadOnly","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Notifications retrieved"}},"security":[{"bearer-auth":[]}],"summary":"List notifications for current user","tags":["Notifications"]}},"/api/notifications/unread-count":{"get":{"operationId":"NotificationController_unreadCount","parameters":[],"responses":{"200":{"description":"Unread count retrieved"}},"security":[{"bearer-auth":[]}],"summary":"Get unread notification count","tags":["Notifications"]}},"/api/notifications/{id}/read":{"patch":{"operationId":"NotificationController_markAsRead","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Notification marked as read"}},"security":[{"bearer-auth":[]}],"summary":"Mark notification as read","tags":["Notifications"]}},"/api/notifications/read-all":{"post":{"operationId":"NotificationController_markAllAsRead","parameters":[],"responses":{"200":{"description":"All notifications marked as read"}},"security":[{"bearer-auth":[]}],"summary":"Mark all notifications as read","tags":["Notifications"]}},"/api/notifications/{id}/dismiss":{"patch":{"operationId":"NotificationController_dismiss","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Notification dismissed"}},"security":[{"bearer-auth":[]}],"summary":"Dismiss a notification","tags":["Notifications"]}},"/api/device-tokens":{"post":{"operationId":"DeviceTokenController_register","parameters":[],"responses":{"201":{"description":"Token registered"}},"security":[{"bearer-auth":[]}],"summary":"Register a device token for push notifications","tags":["Device Tokens"]}},"/api/device-tokens/test-notification":{"post":{"operationId":"DeviceTokenController_sendTestNotification","parameters":[],"responses":{"200":{"description":"Notification sent"}},"security":[{"bearer-auth":[]}],"summary":"Send a test push notification to a user","tags":["Device Tokens"]}},"/api/device-tokens/{deviceId}":{"delete":{"operationId":"DeviceTokenController_deactivate","parameters":[{"name":"deviceId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Token deactivated"}},"security":[{"bearer-auth":[]}],"summary":"Deactivate a device token","tags":["Device Tokens"]}},"/api/workflow/config":{"get":{"operationId":"WorkflowAdminController_getWorkflowConfig","parameters":[],"responses":{"200":{"description":"Workflow configuration with available events and actions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowConfigResponseDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"Get workflow configuration for frontend","tags":["Workflow"]}},"/api/workflow/test/emit":{"post":{"operationId":"WorkflowAdminController_emitTestEvent","parameters":[{"name":"x-workflow-test-key","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"201":{"description":"Event emitted"}},"security":[{"bearer-auth":[]}],"summary":"Emit a domain event directly to EventEmitter (development testing only)","tags":["Workflow"]}},"/api/workflow/provision":{"post":{"operationId":"WorkflowAdminController_provisionWorkflows","parameters":[],"responses":{"201":{"description":"Provisioning result (counts of created/added/skipped)."}},"security":[{"bearer-auth":[]}],"summary":"Provision (backfill) the seeded workflow definitions + bindings for the current org. Additive and idempotent — never deletes. Run after deploying new workflows so existing orgs pick them up.","tags":["Workflow"]}},"/api/workflow/definitions":{"get":{"operationId":"WorkflowAdminController_listDefinitions","parameters":[{"name":"status","required":false,"in":"query","description":"Filter by workflow status","schema":{"enum":["DRAFT","ACTIVE","DISABLED"],"type":"string"}}],"responses":{"200":{"description":"List of workflow definitions","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowDefinitionResponseDto"}}}}}},"security":[{"bearer-auth":[]}],"summary":"List workflow definitions","tags":["Workflow"]},"post":{"operationId":"WorkflowAdminController_createDefinition","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWorkflowDefinitionDto"}}}},"responses":{"201":{"description":"Workflow definition created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowDefinitionResponseDto"}}}},"400":{"description":"Invalid request body"}},"security":[{"bearer-auth":[]}],"summary":"Create a workflow definition","tags":["Workflow"]}},"/api/workflow/definitions/{id}":{"get":{"operationId":"WorkflowAdminController_getDefinition","parameters":[{"name":"id","required":true,"in":"path","description":"Workflow definition ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Workflow definition found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowDefinitionResponseDto"}}}},"404":{"description":"Workflow definition not found"}},"security":[{"bearer-auth":[]}],"summary":"Get a workflow definition by ID","tags":["Workflow"]},"patch":{"operationId":"WorkflowAdminController_updateDefinition","parameters":[{"name":"id","required":true,"in":"path","description":"Workflow definition ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWorkflowDefinitionDto"}}}},"responses":{"200":{"description":"Workflow definition updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowDefinitionResponseDto"}}}},"404":{"description":"Workflow definition not found"}},"security":[{"bearer-auth":[]}],"summary":"Update a workflow definition","tags":["Workflow"]},"delete":{"operationId":"WorkflowAdminController_deleteDefinition","parameters":[{"name":"id","required":true,"in":"path","description":"Workflow definition ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Workflow definition deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowDefinitionResponseDto"}}}},"400":{"description":"Cannot delete active workflow"},"404":{"description":"Workflow definition not found"}},"security":[{"bearer-auth":[]}],"summary":"Delete a workflow definition","tags":["Workflow"]}},"/api/workflow/definitions/{id}/activate":{"post":{"operationId":"WorkflowAdminController_activateDefinition","parameters":[{"name":"id","required":true,"in":"path","description":"Workflow definition ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Workflow definition activated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowDefinitionResponseDto"}}}},"404":{"description":"Workflow definition not found"}},"security":[{"bearer-auth":[]}],"summary":"Activate a workflow definition","tags":["Workflow"]}},"/api/workflow/definitions/{id}/run":{"post":{"operationId":"WorkflowAdminController_runDefinition","parameters":[{"name":"id","required":true,"in":"path","description":"Workflow definition ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManualRunDto"}}}},"responses":{"201":{"description":"Workflow execution queued successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowExecutionResponseDto"}}}},"400":{"description":"Workflow cannot be executed"},"404":{"description":"Workflow definition not found"}},"security":[{"bearer-auth":[]}],"summary":"Manually trigger a workflow execution","tags":["Workflow"]}},"/api/workflow/definitions/{id}/disable":{"post":{"operationId":"WorkflowAdminController_disableDefinition","parameters":[{"name":"id","required":true,"in":"path","description":"Workflow definition ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Workflow definition disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowDefinitionResponseDto"}}}},"404":{"description":"Workflow definition not found"}},"security":[{"bearer-auth":[]}],"summary":"Disable a workflow definition","tags":["Workflow"]}},"/api/workflow/definitions/{id}/clone":{"post":{"operationId":"WorkflowAdminController_cloneDefinition","parameters":[{"name":"id","required":true,"in":"path","description":"Workflow definition ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"201":{"description":"Workflow definition cloned successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowDefinitionResponseDto"}}}},"404":{"description":"Workflow definition not found"}},"security":[{"bearer-auth":[]}],"summary":"Clone a workflow definition","tags":["Workflow"]}},"/api/workflow/executions":{"get":{"operationId":"WorkflowAdminController_listExecutions","parameters":[{"name":"status","required":false,"in":"query","description":"Filter by execution status","schema":{"example":"SUCCEEDED","type":"string","enum":["QUEUED","RUNNING","SUCCEEDED","FAILED","CANCELLED"]}},{"name":"entityType","required":false,"in":"query","description":"Filter by entity type (e.g., participant, staff)","schema":{"example":"participant","type":"string"}},{"name":"entityId","required":false,"in":"query","description":"Filter by entity ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"workflowDefinitionId","required":false,"in":"query","description":"Filter by workflow definition ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"limit","required":false,"in":"query","description":"Maximum number of results to return (default 50)","schema":{"example":20,"type":"number"}},{"name":"offset","required":false,"in":"query","description":"Number of results to skip for pagination","schema":{"example":0,"type":"number"}}],"responses":{"200":{"description":"List of workflow executions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowExecutionListResponseDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"List workflow executions","tags":["Workflow"]}},"/api/workflow/executions/{id}":{"get":{"operationId":"WorkflowAdminController_getExecution","parameters":[{"name":"id","required":true,"in":"path","description":"Workflow execution ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Workflow execution found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowExecutionDetailResponseDto"}}}},"404":{"description":"Workflow execution not found"}},"security":[{"bearer-auth":[]}],"summary":"Get a workflow execution with steps and logs","tags":["Workflow"]}},"/api/workflow/executions/{id}/rerun":{"post":{"operationId":"WorkflowAdminController_rerunExecution","parameters":[{"name":"id","required":true,"in":"path","description":"Workflow execution ID to re-run","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"201":{"description":"New execution created from failed execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowExecutionResponseDto"}}}},"400":{"description":"Can only re-run failed executions"},"404":{"description":"Execution not found"}},"security":[{"bearer-auth":[]}],"summary":"Re-run a failed execution","tags":["Workflow"]}},"/api/workflow/stats":{"get":{"operationId":"WorkflowAdminController_getStats","parameters":[],"responses":{"200":{"description":"Workflow statistics retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowStatsResponseDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"Get workflow statistics","tags":["Workflow"]}},"/api/doc-verification/verify":{"post":{"description":"Upload a document image and provide fields to verify as a JSON string. The AI compares the provided details against the document and returns per-field match results.","operationId":"DocVerificationController_verify","parameters":[],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file","fields"],"properties":{"file":{"type":"string","format":"binary","description":"Document image file (JPEG, PNG, or WebP)"},"fields":{"type":"string","description":"JSON string of key-value pairs to verify. Example: '{\"fullName\":\"Jane Smith\",\"dateOfBirth\":\"1990-05-15\",\"address\":\"123 Main St\"}'","example":"{\"fullName\":\"Jane Smith\",\"dateOfBirth\":\"1990-05-15\"}"},"documentType":{"type":"string","description":"Optional document type (e.g., \"drivers_licence\", \"passport\", \"medicare_card\")","example":"drivers_licence"}}}}}},"responses":{"200":{"description":"Document verification completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationResponseDto"}}}},"400":{"description":"Invalid input (bad image, missing fields)"},"500":{"description":"AI service unavailable or misconfigured"}},"summary":"Verify user details against a document image","tags":["Document Verification"]}},"/api/auth-logs":{"get":{"operationId":"AuthLogController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"eventType","required":false,"in":"query","description":"Filter by event type (LOGIN_SUCCESS, LOGIN_FAILURE, LOGOUT, OTP_SENT, OTP_VERIFIED, SESSION_REVOKED, PASSWORD_RESET, SESSION_EXPIRED)","schema":{"example":"LOGIN_SUCCESS","type":"string"}},{"name":"userId","required":false,"in":"query","description":"Filter by user ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"method","required":false,"in":"query","description":"Filter by auth method (EMAIL_PASSWORD, EMAIL_OTP, PHONE_OTP)","schema":{"example":"EMAIL_PASSWORD","type":"string"}},{"name":"ipAddress","required":false,"in":"query","description":"Filter by IP address (partial match)","schema":{"example":"192.168.1","type":"string"}},{"name":"dateFrom","required":false,"in":"query","description":"Filter auth logs from this date","schema":{"example":"2024-01-01","type":"string"}},{"name":"dateTo","required":false,"in":"query","description":"Filter auth logs to this date","schema":{"example":"2024-12-31","type":"string"}}],"responses":{"200":{"description":"Auth logs fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthLogResponseDto"}}}}},"summary":"Get all auth logs with filters and pagination (admin)","tags":["Auth Logs"]}},"/api/auth-logs/me":{"get":{"operationId":"AuthLogController_findMyLogs","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"eventType","required":false,"in":"query","description":"Filter by event type (LOGIN_SUCCESS, LOGIN_FAILURE, LOGOUT, OTP_SENT, OTP_VERIFIED, SESSION_REVOKED, PASSWORD_RESET, SESSION_EXPIRED)","schema":{"example":"LOGIN_SUCCESS","type":"string"}},{"name":"userId","required":false,"in":"query","description":"Filter by user ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"method","required":false,"in":"query","description":"Filter by auth method (EMAIL_PASSWORD, EMAIL_OTP, PHONE_OTP)","schema":{"example":"EMAIL_PASSWORD","type":"string"}},{"name":"ipAddress","required":false,"in":"query","description":"Filter by IP address (partial match)","schema":{"example":"192.168.1","type":"string"}},{"name":"dateFrom","required":false,"in":"query","description":"Filter auth logs from this date","schema":{"example":"2024-01-01","type":"string"}},{"name":"dateTo","required":false,"in":"query","description":"Filter auth logs to this date","schema":{"example":"2024-12-31","type":"string"}}],"responses":{"200":{"description":"User auth logs fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthLogResponseDto"}}}}},"summary":"Get current user auth logs (no special permission required)","tags":["Auth Logs"]}},"/api/auth-logs/user/{userId}":{"get":{"operationId":"AuthLogController_findByUser","parameters":[{"name":"userId","required":true,"in":"path","description":"User ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"eventType","required":false,"in":"query","description":"Filter by event type (LOGIN_SUCCESS, LOGIN_FAILURE, LOGOUT, OTP_SENT, OTP_VERIFIED, SESSION_REVOKED, PASSWORD_RESET, SESSION_EXPIRED)","schema":{"example":"LOGIN_SUCCESS","type":"string"}},{"name":"method","required":false,"in":"query","description":"Filter by auth method (EMAIL_PASSWORD, EMAIL_OTP, PHONE_OTP)","schema":{"example":"EMAIL_PASSWORD","type":"string"}},{"name":"ipAddress","required":false,"in":"query","description":"Filter by IP address (partial match)","schema":{"example":"192.168.1","type":"string"}},{"name":"dateFrom","required":false,"in":"query","description":"Filter auth logs from this date","schema":{"example":"2024-01-01","type":"string"}},{"name":"dateTo","required":false,"in":"query","description":"Filter auth logs to this date","schema":{"example":"2024-12-31","type":"string"}}],"responses":{"200":{"description":"User auth logs fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthLogResponseDto"}}}}},"summary":"Get auth logs for a specific user (admin)","tags":["Auth Logs"]}},"/api/message-centre":{"post":{"operationId":"MessageCentreController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMessageCentrePostDto"}}}},"responses":{"201":{"description":"Post created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageCentrePostResponseDto"}}}},"400":{"description":"Validation error"}},"summary":"Create a message centre post (announcement)","tags":["Message Centre"]},"get":{"operationId":"MessageCentreController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by status","schema":{"type":"string","enum":["DRAFT","SCHEDULED","PUBLISHED","ARCHIVED","COMPLETED","PAUSED"]}},{"name":"channel","required":false,"in":"query","description":"Filter by channel","schema":{"type":"string","enum":["IN_APP","EMAIL","SMS"]}},{"name":"targetAudience","required":false,"in":"query","description":"Filter by target audience account type","schema":{"type":"string","enum":["ADMIN","STAFF","PARTICIPANT","SUPPORT_COORDINATOR","GUARDIAN","PARTNER","OWNER","TENANT"]}},{"name":"isPinned","required":false,"in":"query","description":"Filter: only pinned posts","schema":{"type":"boolean"}},{"name":"activeOnly","required":false,"in":"query","description":"Filter: only non-expired posts","schema":{"type":"boolean"}},{"name":"search","required":false,"in":"query","description":"Search by title or summary","schema":{"type":"string"}}],"responses":{"200":{"description":"Posts fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageCentrePostResponseDto"}}}}},"summary":"List message centre posts with filters","tags":["Message Centre"]}},"/api/message-centre/latest":{"get":{"operationId":"MessageCentreController_getLatest","parameters":[{"name":"limit","required":false,"in":"query","description":"Number of posts to return","schema":{"example":10,"type":"string"}},{"name":"accountType","required":true,"in":"query","description":"Account type to filter by","schema":{"enum":["ADMIN","STAFF","PARTICIPANT","SUPPORT_COORDINATOR","GUARDIAN","PARTNER","OWNER","TENANT"],"type":"string"}}],"responses":{"200":{"description":"Latest posts fetched successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MessageCentrePostResponseDto"}}}}}},"summary":"Get latest published posts for a specific account type (mobile/dashboard)","tags":["Message Centre"]}},"/api/message-centre/{id}":{"get":{"operationId":"MessageCentreController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Post ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Post fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageCentrePostResponseDto"}}}},"404":{"description":"Post not found"}},"summary":"Get a single message centre post by ID","tags":["Message Centre"]},"patch":{"operationId":"MessageCentreController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Post ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMessageCentrePostDto"}}}},"responses":{"200":{"description":"Post updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageCentrePostResponseDto"}}}},"404":{"description":"Post not found"},"409":{"description":"Cannot update an archived post"}},"summary":"Update a message centre post","tags":["Message Centre"]},"delete":{"operationId":"MessageCentreController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Post ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Post deleted successfully"},"404":{"description":"Post not found"}},"summary":"Delete a message centre post","tags":["Message Centre"]}},"/api/message-centre/{id}/publish":{"post":{"operationId":"MessageCentreController_publish","parameters":[{"name":"id","required":true,"in":"path","description":"Post ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Post published successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageCentrePostResponseDto"}}}},"404":{"description":"Post not found"},"409":{"description":"Post is already published or archived"}},"summary":"Publish a draft message centre post","tags":["Message Centre"]}},"/api/message-centre/{id}/archive":{"post":{"operationId":"MessageCentreController_archive","parameters":[{"name":"id","required":true,"in":"path","description":"Post ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}}],"responses":{"200":{"description":"Post archived successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageCentrePostResponseDto"}}}},"404":{"description":"Post not found"},"409":{"description":"Post is already archived"}},"summary":"Archive a message centre post","tags":["Message Centre"]}},"/api/message-centre/{id}/cancel-schedule":{"post":{"operationId":"MessageCentreController_cancelSchedule","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Cancel a scheduled (one-shot) broadcast and revert to DRAFT","tags":["Message Centre"]}},"/api/message-centre/{id}/pause":{"post":{"operationId":"MessageCentreController_pause","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Pause a recurring broadcast","tags":["Message Centre"]}},"/api/message-centre/{id}/resume":{"post":{"operationId":"MessageCentreController_resume","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Resume a paused recurring broadcast","tags":["Message Centre"]}},"/api/message-centre/{id}/dispatches":{"get":{"operationId":"MessageCentreController_getDispatchHistory","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Get dispatch history for a scheduled/recurring broadcast","tags":["Message Centre"]}},"/api/groups":{"post":{"operationId":"GroupController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGroupDto"}}}},"responses":{"201":{"description":"Group created successfully"}},"summary":"Create a new group","tags":["Groups"]},"get":{"operationId":"GroupController_findAll","parameters":[{"name":"search","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Groups fetched successfully"}},"summary":"List all groups","tags":["Groups"]}},"/api/groups/{id}":{"get":{"operationId":"GroupController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Group ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Group fetched successfully"}},"summary":"Get group by ID","tags":["Groups"]},"put":{"operationId":"GroupController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Group ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGroupDto"}}}},"responses":{"200":{"description":"Group updated successfully"}},"summary":"Update a group","tags":["Groups"]},"delete":{"operationId":"GroupController_delete","parameters":[{"name":"id","required":true,"in":"path","description":"Group ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Group deleted successfully"}},"summary":"Delete a group","tags":["Groups"]}},"/api/groups/{id}/members":{"post":{"operationId":"GroupController_addMembers","parameters":[{"name":"id","required":true,"in":"path","description":"Group ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddMembersDto"}}}},"responses":{"200":{"description":"Members added successfully"}},"summary":"Add members to a group","tags":["Groups"]}},"/api/groups/{id}/members/{userId}":{"delete":{"operationId":"GroupController_removeMember","parameters":[{"name":"id","required":true,"in":"path","description":"Group ID","schema":{"type":"string"}},{"name":"userId","required":true,"in":"path","description":"User ID to remove","schema":{"type":"string"}}],"responses":{"200":{"description":"Member removed successfully"}},"summary":"Remove a member from a group","tags":["Groups"]}},"/api/reminders/templates/placeholders":{"get":{"operationId":"ReminderController_getTemplatePlaceholders","parameters":[],"responses":{"200":{"description":"Placeholders fetched successfully"}},"summary":"Get available reminder template placeholders","tags":["Reminders"]}},"/api/reminders/templates":{"get":{"operationId":"ReminderController_getTemplates","parameters":[],"responses":{"200":{"description":"Templates fetched successfully"}},"summary":"Get all available reminder templates","tags":["Reminders"]},"post":{"operationId":"ReminderController_createTemplate","parameters":[],"responses":{"201":{"description":"Template created successfully"}},"summary":"Create a new reminder template","tags":["Reminders"]}},"/api/reminders/pending-count":{"get":{"operationId":"ReminderController_getPendingCount","parameters":[],"responses":{"200":{"description":"Count fetched successfully"}},"summary":"Get count of pending reminders for current user","tags":["Reminders"]}},"/api/reminders/entity/{entityType}/{entityId}":{"get":{"operationId":"ReminderController_findByEntity","parameters":[{"name":"entityType","required":true,"in":"path","description":"Entity type","schema":{"example":"LEAD","type":"string"}},{"name":"entityId","required":true,"in":"path","description":"Entity ID","schema":{"example":"clm456def","type":"string"}}],"responses":{"200":{"description":"Reminders fetched successfully"}},"summary":"Get reminders linked to an entity","tags":["Reminders"]}},"/api/reminders":{"get":{"operationId":"ReminderController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by reminder status","schema":{"example":"PENDING","type":"string","enum":["PENDING","FIRED","COMPLETED","SNOOZED","CANCELLED"]}},{"name":"entityType","required":false,"in":"query","description":"Filter by linked entity type","schema":{"example":"LEAD","type":"string"}},{"name":"entityId","required":false,"in":"query","description":"Filter by linked entity ID","schema":{"example":"clm456def","type":"string"}},{"name":"dateFrom","required":false,"in":"query","description":"Filter reminders from this date (ISO)","schema":{"example":"2026-03-01","type":"string"}},{"name":"dateTo","required":false,"in":"query","description":"Filter reminders until this date (ISO)","schema":{"example":"2026-03-31","type":"string"}}],"responses":{"200":{"description":"Reminders fetched successfully"}},"summary":"Get all reminders with filters and pagination","tags":["Reminders"]},"post":{"operationId":"ReminderController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReminderDto"}}}},"responses":{"201":{"description":"Reminder created successfully"}},"summary":"Create a new reminder","tags":["Reminders"]}},"/api/reminders/{id}":{"get":{"operationId":"ReminderController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Reminder ID","schema":{"example":"clm123abc","type":"string"}}],"responses":{"200":{"description":"Reminder fetched successfully"}},"summary":"Get a single reminder by ID","tags":["Reminders"]},"patch":{"operationId":"ReminderController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Reminder ID","schema":{"example":"clm123abc","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateReminderDto"}}}},"responses":{"200":{"description":"Reminder updated successfully"}},"summary":"Update a reminder","tags":["Reminders"]}},"/api/reminders/{id}/complete":{"post":{"operationId":"ReminderController_complete","parameters":[{"name":"id","required":true,"in":"path","description":"Reminder ID","schema":{"example":"clm123abc","type":"string"}}],"responses":{"200":{"description":"Reminder completed"}},"summary":"Mark a reminder as completed","tags":["Reminders"]}},"/api/reminders/{id}/snooze":{"post":{"operationId":"ReminderController_snooze","parameters":[{"name":"id","required":true,"in":"path","description":"Reminder ID","schema":{"example":"clm123abc","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnoozeReminderDto"}}}},"responses":{"200":{"description":"Reminder snoozed"}},"summary":"Snooze a reminder","tags":["Reminders"]}},"/api/reminders/{id}/cancel":{"post":{"operationId":"ReminderController_cancel","parameters":[{"name":"id","required":true,"in":"path","description":"Reminder ID","schema":{"example":"clm123abc","type":"string"}}],"responses":{"200":{"description":"Reminder cancelled"}},"summary":"Cancel a reminder","tags":["Reminders"]}},"/api/reminders/{id}/recipients/{recipientId}/retry":{"post":{"operationId":"ReminderController_retryRecipient","parameters":[{"name":"id","required":true,"in":"path","description":"Reminder ID","schema":{"type":"string"}},{"name":"recipientId","required":true,"in":"path","description":"Recipient ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Retry queued"}},"summary":"Retry sending a failed reminder recipient","tags":["Reminders"]}},"/api/reminders/{id}/recipients/{recipientId}/attempts":{"get":{"operationId":"ReminderController_getRecipientAttempts","parameters":[{"name":"id","required":true,"in":"path","description":"Reminder ID","schema":{"type":"string"}},{"name":"recipientId","required":true,"in":"path","description":"Recipient ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Attempt history fetched"}},"summary":"Get attempt history for a reminder recipient","tags":["Reminders"]}},"/api/reminders/{id}/delivery-status":{"get":{"operationId":"ReminderController_getDeliveryStatus","parameters":[{"name":"id","required":true,"in":"path","description":"Reminder ID","schema":{"example":"clm123abc","type":"string"}}],"responses":{"200":{"description":"Delivery status fetched successfully"}},"summary":"Get delivery status for a reminder","tags":["Reminders"]}},"/api/account-archive-requests":{"post":{"description":"Allowed for participants, staff, and support coordinators. Requires a reason. Only one PENDING request per user is allowed at a time.","operationId":"AccountArchiveRequestController_submit","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAccountArchiveRequestDto"}}}},"responses":{"201":{"description":"Archive request submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountArchiveRequestResponseDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"Submit a request to archive your own account (mobile self-service)","tags":["Account Archive Requests"]},"get":{"operationId":"AccountArchiveRequestController_findAll","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by status","schema":{"type":"array","items":{"type":"string","enum":["PENDING","APPROVED","REJECTED","CANCELLED"]}}},{"name":"accountType","required":false,"in":"query","description":"Filter by requester account type","schema":{"type":"string","enum":["ADMIN","STAFF","PARTICIPANT","SUPPORT_COORDINATOR","GUARDIAN","PARTNER","OWNER","TENANT"]}},{"name":"requesterUserId","required":false,"in":"query","description":"Filter by requester user ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of archive requests"}},"security":[{"bearer-auth":[]}],"summary":"List all archive requests (admin)","tags":["Account Archive Requests"]}},"/api/account-archive-requests/me":{"get":{"operationId":"AccountArchiveRequestController_listMine","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Requests list","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AccountArchiveRequestResponseDto"}}}}}},"security":[{"bearer-auth":[]}],"summary":"List the current user's own archive requests (mobile)","tags":["Account Archive Requests"]}},"/api/account-archive-requests/{id}/cancel":{"post":{"operationId":"AccountArchiveRequestController_cancel","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string"}},{"name":"id","required":true,"in":"path","description":"Archive request ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Request cancelled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountArchiveRequestResponseDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"Cancel your own pending archive request (mobile)","tags":["Account Archive Requests"]}},"/api/account-archive-requests/{id}":{"get":{"operationId":"AccountArchiveRequestController_findById","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string"}},{"name":"id","required":true,"in":"path","description":"Archive request ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Archive request details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountArchiveRequestResponseDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"Get archive request details (admin)","tags":["Account Archive Requests"]}},"/api/account-archive-requests/{id}/approve":{"post":{"description":"Marks the request APPROVED and cascade-archives the user along with the linked staff and/or participant record.","operationId":"AccountArchiveRequestController_approve","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string"}},{"name":"id","required":true,"in":"path","description":"Archive request ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewAccountArchiveRequestDto"}}}},"responses":{"200":{"description":"Request approved, account archived"}},"security":[{"bearer-auth":[]}],"summary":"Approve and archive the requesting user (admin)","tags":["Account Archive Requests"]}},"/api/account-archive-requests/{id}/reject":{"post":{"description":"Marks the request REJECTED. The user remains active.","operationId":"AccountArchiveRequestController_reject","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string"}},{"name":"id","required":true,"in":"path","description":"Archive request ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewAccountArchiveRequestDto"}}}},"responses":{"200":{"description":"Request rejected"}},"security":[{"bearer-auth":[]}],"summary":"Reject an archive request (admin)","tags":["Account Archive Requests"]}},"/api/account-archive-requests/debug/on-behalf-of/{userId}":{"post":{"description":"Temporary debug endpoint that lets an admin act as another user and submit an archive request without using the mobile app. Audited as submit-on-behalf.","operationId":"AccountArchiveRequestController_submitOnBehalf","parameters":[{"name":"x-org-id","in":"header","description":"Organization ID","required":true,"schema":{"type":"string"}},{"name":"userId","required":true,"in":"path","description":"User to submit the request for (the requester)","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAccountArchiveRequestDto"}}}},"responses":{"201":{"description":"Archive request submitted on behalf of user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountArchiveRequestResponseDto"}}}}},"security":[{"bearer-auth":[]}],"summary":"[DEBUG] Submit an archive request on behalf of a user (admin testing only)","tags":["Account Archive Requests"]}},"/api/settings/policy":{"get":{"operationId":"PolicyController_getPolicy","parameters":[],"responses":{"200":{"description":"Policy fetched successfully"}},"summary":"Get the org platform policy (creates defaults on first access)","tags":["Settings - Policy"]},"patch":{"operationId":"PolicyController_updatePolicy","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePolicyDto"}}}},"responses":{"200":{"description":"Policy updated successfully"}},"summary":"Update the org platform policy (tighten-only against NSW/platform floors)","tags":["Settings - Policy"]}},"/api/properties":{"get":{"operationId":"PropertyController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by property status","schema":{"type":"string","enum":["PROSPECTIVE","OCCUPIED","VACANT","VACATING","ARCHIVED"]}},{"name":"type","required":false,"in":"query","description":"Filter by property type","schema":{"type":"string","enum":["HOUSE","APARTMENT","TOWNHOUSE","DUPLEX","VILLA","STUDIO","COMMERCIAL"]}},{"name":"suburb","required":false,"in":"query","description":"Filter by suburb (exact match, case-insensitive)","schema":{"example":"Parramatta","type":"string"}},{"name":"managerUserId","required":false,"in":"query","description":"Filter by assigned property manager user ID","schema":{"type":"string"}},{"name":"ids","required":false,"in":"query","description":"Restrict to these property IDs (max 100, comma-separated)","schema":{"type":"array","items":{"type":"string"}}}],"responses":{"200":{"description":"Properties fetched successfully"}},"summary":"List properties with filters and pagination","tags":["Properties"]},"post":{"operationId":"PropertyController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePropertyDto"}}}},"responses":{"201":{"description":"Property created successfully"}},"summary":"Create a new property","tags":["Properties"]}},"/api/properties/directory":{"get":{"operationId":"PropertyController_findDirectory","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by property status","schema":{"type":"string","enum":["PROSPECTIVE","OCCUPIED","VACANT","VACATING","ARCHIVED"]}},{"name":"type","required":false,"in":"query","description":"Filter by property type","schema":{"type":"string","enum":["HOUSE","APARTMENT","TOWNHOUSE","DUPLEX","VILLA","STUDIO","COMMERCIAL"]}},{"name":"suburb","required":false,"in":"query","description":"Filter by suburb (exact match, case-insensitive)","schema":{"example":"Parramatta","type":"string"}},{"name":"managerUserId","required":false,"in":"query","description":"Filter by assigned property manager user ID","schema":{"type":"string"}},{"name":"ids","required":false,"in":"query","description":"Restrict to these property IDs (max 100, comma-separated)","schema":{"type":"array","items":{"type":"string"}}},{"name":"inArrears","required":false,"in":"query","description":"Only properties whose live tenancy is in arrears","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Properties fetched successfully"}},"summary":"Properties grid: one page with manager, live tenancy, weekly rent and arrears indicator resolved server-side","tags":["Properties"]}},"/api/properties/portfolio-summary":{"get":{"operationId":"PropertyController_portfolioSummary","parameters":[],"responses":{"200":{"description":"Summary fetched successfully"}},"summary":"Portfolio counters for the properties stat cards (whole organisation, database aggregates)","tags":["Properties"]}},"/api/properties/{id}":{"get":{"operationId":"PropertyController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Property ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Property fetched successfully"}},"summary":"Get a single property by ID","tags":["Properties"]},"patch":{"operationId":"PropertyController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Property ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePropertyDto"}}}},"responses":{"200":{"description":"Property updated successfully"}},"summary":"Update a property","tags":["Properties"]},"delete":{"operationId":"PropertyController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Property ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Property deleted successfully"}},"summary":"Soft-delete a property","tags":["Properties"]}},"/api/properties/{id}/owners":{"get":{"operationId":"PropertyController_listOwnerships","parameters":[{"name":"id","required":true,"in":"path","description":"Property ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Ownerships fetched successfully"}},"summary":"List owners attached to a property","tags":["Properties"]},"post":{"operationId":"PropertyController_addOwnership","parameters":[{"name":"id","required":true,"in":"path","description":"Property ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddOwnershipDto"}}}},"responses":{"201":{"description":"Owner attached successfully"}},"summary":"Attach an owner to a property","tags":["Properties"]}},"/api/properties/{id}/owners/{ownershipId}":{"patch":{"operationId":"PropertyController_updateOwnership","parameters":[{"name":"id","required":true,"in":"path","description":"Property ID","schema":{"type":"string"}},{"name":"ownershipId","required":true,"in":"path","description":"Ownership ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOwnershipDto"}}}},"responses":{"200":{"description":"Ownership updated successfully"}},"summary":"Update an owner's share/primary flag on a property","tags":["Properties"]},"delete":{"operationId":"PropertyController_removeOwnership","parameters":[{"name":"id","required":true,"in":"path","description":"Property ID","schema":{"type":"string"}},{"name":"ownershipId","required":true,"in":"path","description":"Ownership ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Owner detached successfully"}},"summary":"Detach an owner from a property","tags":["Properties"]}},"/api/properties/{id}/agreement":{"get":{"operationId":"PropertyController_getAgreement","parameters":[{"name":"id","required":true,"in":"path","description":"Property ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Agreement fetched successfully"}},"summary":"Get the management agreement for a property","tags":["Properties"]},"put":{"operationId":"PropertyController_upsertAgreement","parameters":[{"name":"id","required":true,"in":"path","description":"Property ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertManagementAgreementDto"}}}},"responses":{"200":{"description":"Agreement saved successfully"}},"summary":"Create or update the management agreement for a property","tags":["Properties"]}},"/api/owners":{"get":{"operationId":"OwnerController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"type","required":false,"in":"query","description":"Filter by owner type","schema":{"type":"string","enum":["INDIVIDUAL","COMPANY","TRUST","SMSF"]}}],"responses":{"200":{"description":"Owners fetched successfully"}},"summary":"List owners with filters and pagination","tags":["Owners"]},"post":{"operationId":"OwnerController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOwnerDto"}}}},"responses":{"201":{"description":"Owner created successfully"}},"summary":"Create a new owner","tags":["Owners"]}},"/api/owners/{id}/statements/{month}/pdf":{"get":{"operationId":"OwnerController_statementPdf","parameters":[{"name":"id","required":true,"in":"path","description":"Owner ID","schema":{"type":"string"}},{"name":"month","required":true,"in":"path","description":"YYYY-MM","schema":{"type":"string"}}],"responses":{"200":{"description":"PDF"}},"summary":"Download a ledger-summary PDF for one owner and calendar month","tags":["Owners"]}},"/api/owners/directory":{"get":{"operationId":"OwnerController_findDirectory","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search owner name, email or phone","schema":{"type":"string"}},{"name":"type","required":false,"in":"query","description":"Filter by owner type","schema":{"type":"string","enum":["INDIVIDUAL","COMPANY","TRUST","SMSF"]}}],"responses":{"200":{"description":"Owners fetched successfully"}},"summary":"Owner directory grid: one page with property count and rent roll aggregated in SQL","tags":["Owners"]}},"/api/owners/portfolio-summary":{"get":{"operationId":"OwnerController_portfolioSummary","parameters":[],"responses":{"200":{"description":"Summary fetched successfully"}},"summary":"Owner portfolio totals (whole organisation, SQL aggregates)","tags":["Owners"]}},"/api/owners/{id}":{"get":{"operationId":"OwnerController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Owner ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Owner fetched successfully"}},"summary":"Get a single owner by ID","tags":["Owners"]},"patch":{"operationId":"OwnerController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Owner ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOwnerDto"}}}},"responses":{"200":{"description":"Owner updated successfully"}},"summary":"Update an owner","tags":["Owners"]},"delete":{"operationId":"OwnerController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Owner ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Owner deleted successfully"}},"summary":"Soft-delete an owner","tags":["Owners"]}},"/api/portal/owner/overview":{"get":{"operationId":"OwnerPortalController_overview","parameters":[],"responses":{"200":{"description":"Overview fetched successfully"}},"summary":"Owner portfolio overview: properties with current tenancy, rent, latest valuation and counts","tags":["Portal · Owner"]}},"/api/portal/owner/properties":{"get":{"operationId":"OwnerPortalController_properties","parameters":[],"responses":{"200":{"description":"Properties fetched successfully"}},"summary":"Owner property detail incl. management agreement and per-tenancy ledger summary","tags":["Portal · Owner"]}},"/api/portal/owner/maintenance":{"get":{"operationId":"OwnerPortalController_maintenance","parameters":[{"name":"closedCursor","required":false,"in":"query","description":"Cursor from `closedNextCursor` of the previous page. When given, only the next page of closed jobs is returned (no open jobs).","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Maintenance jobs on this owner's properties — every open job plus one page of closed jobs (pass closedCursor for the next page)","tags":["Portal · Owner"]}},"/api/portal/owner/maintenance/{id}":{"get":{"operationId":"OwnerPortalController_maintenanceJob","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"One maintenance job with the owner-visible history and the quotes shared with them","tags":["Portal · Owner"]}},"/api/portal/owner/maintenance/{id}/direction":{"post":{"operationId":"OwnerPortalController_decideMaintenanceDirection","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideOwnerDirectionDto"}}}},"responses":{"200":{"description":""}},"summary":"Owner chooses quotes or a direct repair for a pending maintenance request","tags":["Portal · Owner"]}},"/api/portal/owner/maintenance/{id}/quote":{"post":{"operationId":"OwnerPortalController_decideMaintenanceQuote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideOwnerQuoteDto"}}}},"responses":{"200":{"description":""}},"summary":"Owner answers forwarded quotes: approve one, reject one, put the decision on hold, or ask for more. Approving does not dispatch a tradesperson.","tags":["Portal · Owner"]}},"/api/portal/owner/decisions":{"get":{"operationId":"OwnerPortalController_decisions","parameters":[],"responses":{"200":{"description":"Pending decisions fetched successfully"}},"summary":"Everything waiting on this owner — maintenance directions and agent approvals — from the one definition the dashboard count also uses","tags":["Portal · Owner"]}},"/api/portal/owner/approvals":{"get":{"operationId":"OwnerPortalController_approvals","parameters":[],"responses":{"200":{"description":"Approvals fetched successfully"}},"summary":"Pending OWNER-routed approvals for the owner’s portfolio, with decision + evidence","tags":["Portal · Owner"]}},"/api/portal/owner/approvals/{id}/approve":{"post":{"operationId":"OwnerPortalController_approve","parameters":[{"name":"id","required":true,"in":"path","description":"Approval ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalDecideApprovalDto"}}}},"responses":{"200":{"description":"Approval approved"}},"summary":"Approve an OWNER-routed decision (ownership enforced) and dispatch its action","tags":["Portal · Owner"]}},"/api/portal/owner/approvals/{id}/reject":{"post":{"operationId":"OwnerPortalController_reject","parameters":[{"name":"id","required":true,"in":"path","description":"Approval ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalDecideApprovalDto"}}}},"responses":{"200":{"description":"Approval rejected"}},"summary":"Reject an OWNER-routed decision (ownership enforced)","tags":["Portal · Owner"]}},"/api/portal/owner/market":{"get":{"operationId":"OwnerPortalController_market","parameters":[],"responses":{"200":{"description":"Market fetched successfully"}},"summary":"Market view: latest SuburbStats for the owner’s suburbs + latest valuations (incl. comps)","tags":["Portal · Owner"]}},"/api/portal/owner/statements":{"get":{"operationId":"OwnerPortalController_statements","parameters":[{"name":"year","required":false,"in":"query","description":"Calendar year, e.g. 2025","schema":{"type":"number"}},{"name":"propertyId","required":false,"in":"query","description":"One of the owner’s property ids","schema":{"type":"string"}}],"responses":{"200":{"description":"Statements fetched successfully"}},"summary":"Per-property monthly statements (rent charged/received + maintenance spend): the last 6 months, or one calendar year, optionally for one owned property","tags":["Portal · Owner"]}},"/api/portal/owner/statements/{month}/pdf":{"get":{"operationId":"OwnerPortalController_statementPdf","parameters":[{"name":"month","required":true,"in":"path","description":"YYYY-MM","schema":{"type":"string"}},{"name":"year","required":false,"in":"query","description":"Calendar year, e.g. 2025","schema":{"type":"number"}},{"name":"propertyId","required":false,"in":"query","description":"One of the owner’s property ids","schema":{"type":"string"}}],"responses":{"200":{"description":"PDF"}},"summary":"Download one calendar month as a ledger-summary PDF","tags":["Portal · Owner"]}},"/api/portal/tenant/rent-status":{"get":{"operationId":"TenantPortalController_rentStatus","parameters":[],"responses":{"200":{"description":"Rent status fetched successfully"}},"summary":"Rent schedule + ledger balance, arrears position and payment instructions","tags":["Portal · Tenant"]}},"/api/portal/tenant/payments":{"get":{"operationId":"TenantPortalController_payments","parameters":[{"name":"tenancyId","required":true,"in":"query","schema":{"type":"string"}},{"name":"year","required":false,"in":"query","description":"Calendar year; defaults to the newest year with payments","schema":{"type":"string"}}],"responses":{"200":{"description":"Payments fetched successfully"}},"summary":"Rent payments received on one of the tenant’s tenancies, one calendar year at a time","tags":["Portal · Tenant"]}},"/api/portal/tenant/jobs":{"get":{"operationId":"TenantPortalController_jobs","parameters":[],"responses":{"200":{"description":"Jobs fetched successfully"}},"summary":"The tenant’s maintenance jobs, newest first","tags":["Portal · Tenant"]},"post":{"operationId":"TenantPortalController_reportRepair","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportRepairDto"}}}},"responses":{"201":{"description":"Repair reported successfully"}},"summary":"Report a repair (auto-escalates to P1/urgent on statutory urgent-repair keywords)","tags":["Portal · Tenant"]}},"/api/portal/tenant/maintenance/jobs":{"get":{"operationId":"TenantPortalController_jobList","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"pageSize","required":false,"in":"query","schema":{"minimum":1,"maximum":100,"default":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","schema":{"default":"createdAt","type":"string","enum":["createdAt","status","title"]}},{"name":"sortDir","required":false,"in":"query","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"search","required":false,"in":"query","description":"Matches title or ref","schema":{"type":"string"}},{"name":"bucket","required":false,"in":"query","schema":{"default":"all","type":"string","enum":["open","visit_booked","completed","all"]}},{"name":"stages","required":false,"in":"query","description":"Status column filter: tenant stages (repeat the param)","schema":{"type":"array","items":{"type":"string","enum":["RECEIVED","BEING_ARRANGED","VISIT_SCHEDULED","WORK_IN_PROGRESS","COMPLETION_REVIEW","ON_HOLD","COMPLETED","CANCELLED"]}}},{"name":"title","required":false,"in":"query","description":"Issue column filter: title contains","schema":{"type":"string"}},{"name":"createdFrom","required":false,"in":"query","description":"Reported on/after (YYYY-MM-DD)","schema":{"type":"string"}},{"name":"createdTo","required":false,"in":"query","description":"Reported on/before (YYYY-MM-DD)","schema":{"type":"string"}},{"name":"scheduledFrom","required":false,"in":"query","description":"Visit on/after (YYYY-MM-DD)","schema":{"type":"string"}},{"name":"scheduledTo","required":false,"in":"query","description":"Visit on/before (YYYY-MM-DD)","schema":{"type":"string"}}],"responses":{"200":{"description":"Jobs page fetched successfully"}},"summary":"One server page of the tenant’s jobs (page/sort/search/bucket) plus per-tile counts","tags":["Portal · Tenant"]}},"/api/portal/tenant/jobs/{id}":{"get":{"operationId":"TenantPortalController_jobDetail","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"One of the tenant’s requests: their report, photos and updates","tags":["Portal · Tenant"]}},"/api/portal/tenant/photos":{"post":{"operationId":"TenantPortalController_uploadPhoto","parameters":[{"name":"tenancyId","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"201":{"description":"Photo stored"}},"summary":"Upload a repair photo before reporting a job","tags":["Portal · Tenant"]}},"/api/portal/tenant/requests":{"get":{"operationId":"TenantPortalController_requests","parameters":[],"responses":{"200":{"description":"Requests fetched successfully"}},"summary":"The tenant’s pet requests with daysRemaining (21-day NSW clock)","tags":["Portal · Tenant"]},"post":{"operationId":"TenantPortalController_createRequest","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePortalPetRequestDto"}}}},"responses":{"201":{"description":"Pet request lodged successfully"}},"summary":"Lodge a pet request (respondByDate = +21 days, NSW)","tags":["Portal · Tenant"]}},"/api/portal/tenant/documents":{"get":{"operationId":"TenantPortalController_documentList","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"pageSize","required":false,"in":"query","schema":{"minimum":1,"maximum":100,"default":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","schema":{"default":"date","type":"string","enum":["date","name","type","size"]}},{"name":"sortDir","required":false,"in":"query","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"search","required":false,"in":"query","description":"Matches file/display name or a linked job ref/title","schema":{"type":"string"}},{"name":"kind","required":false,"in":"query","schema":{"default":"all","type":"string","enum":["lease","inspection","notice","repair_photo","other","all"]}},{"name":"kinds","required":false,"in":"query","description":"Type column filter (repeat the param)","schema":{"type":"array","items":{"type":"string","enum":["lease","inspection","notice","repair_photo","other"]}}},{"name":"from","required":false,"in":"query","description":"Added on/after (YYYY-MM-DD)","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"Added on/before (YYYY-MM-DD)","schema":{"type":"string"}}],"responses":{"200":{"description":"Documents page fetched successfully"}},"summary":"One server page of the tenant’s documents (page/sort/search/kind/date) plus per-tile counts","tags":["Portal · Tenant"]}},"/api/portal/tenant/documents/links":{"get":{"operationId":"TenantPortalController_documents","parameters":[],"responses":{"200":{"description":"Documents fetched successfully"}},"summary":"Every document link on the tenant’s tenancy/property/jobs (flat)","tags":["Portal · Tenant"]}},"/api/portal/tenant/documents/{id}/url":{"get":{"description":"Authorised by exactly the same rule that builds GET /documents, so a tenant can only ever open a document they could already see. Use disposition=inline to preview (e.g. a served notice PDF) or attachment to download. Bytes never pass through the API.","operationId":"TenantPortalController_documentUrl","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"disposition","required":false,"in":"query","schema":{"enum":["inline","attachment"],"type":"string"}}],"responses":{"200":{"description":"Signed URL issued"}},"summary":"Short-lived signed URL to view or download one of the tenant’s documents","tags":["Portal · Tenant"]}},"/api/agents/runs":{"post":{"operationId":"AgentRunController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgentRunDto"}}}},"responses":{"201":{"description":"Run queued successfully"}},"summary":"Enqueue a QUEUED agent run (accepts sandbox flag)","tags":["Agent Runs"]},"get":{"operationId":"AgentRunController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"agentKey","required":false,"in":"query","description":"Filter by agent","schema":{"type":"string","enum":["valuation","rent-review","maintenance-triage","arrears","inspection-scheduler"]}},{"name":"status","required":false,"in":"query","description":"Filter by status","schema":{"type":"string","enum":["QUEUED","RUNNING","AWAITING_APPROVAL","AUTO_ACTIONED","APPROVED","REJECTED","COMPLETED","FAILED","CANCELLED"]}},{"name":"tenancyId","required":false,"in":"query","description":"Filter by tenancy id","schema":{"type":"string"}},{"name":"propertyId","required":false,"in":"query","description":"Filter by property id","schema":{"type":"string"}},{"name":"ownerId","required":false,"in":"query","description":"Filter by owner id","schema":{"type":"string"}}],"responses":{"200":{"description":"Runs fetched successfully"}},"summary":"List runs (paginated, filter agentKey/status)","tags":["Agent Runs"]}},"/api/agents/runs/cancel":{"post":{"description":"Cancels QUEUED and RUNNING runs in scope. In-flight model sessions may still finish their HTTP call, but finalize will not resurrect a cancelled run.","operationId":"AgentRunController_cancelQueued","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelAgentRunsDto"}}}},"responses":{"200":{"description":"Runs cancelled"}},"summary":"Cancel a sweep (queued + running, or one agent’s sweep)","tags":["Agent Runs"]}},"/api/agents/runs/{id}/cancel":{"post":{"operationId":"AgentRunController_cancelOne","parameters":[{"name":"id","required":true,"in":"path","description":"Run ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Run cancelled"}},"summary":"Cancel a single queued or running run","tags":["Agent Runs"]}},"/api/agents/runs/{id}":{"get":{"operationId":"AgentRunController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Run ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Run fetched successfully"}},"summary":"Get a run with its decisions","tags":["Agent Runs"]}},"/api/agents/runs/{id}/steps":{"get":{"operationId":"AgentRunController_listSteps","parameters":[{"name":"id","required":true,"in":"path","description":"Run ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Steps fetched successfully"}},"summary":"List a run’s replay steps, ordered by sequence","tags":["Agent Runs"]},"post":{"operationId":"AgentRunController_appendSteps","parameters":[{"name":"id","required":true,"in":"path","description":"Run ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppendRunStepsDto"}}}},"responses":{"201":{"description":"Steps appended successfully"}},"summary":"Append replay steps (append-only, sequence-validated)","tags":["Agent Runs"]}},"/api/agents":{"get":{"operationId":"AgentConfigController_list","parameters":[],"responses":{"200":{"description":"Agents fetched successfully"}},"summary":"List the agent roster, each merged with defaults","tags":["Agents"]}},"/api/agents/{key}/config/history":{"get":{"operationId":"AgentConfigController_getHistory","parameters":[{"name":"key","required":true,"in":"path","description":"Agent key, e.g. \"rent-review\"","schema":{"type":"string"}}],"responses":{"200":{"description":"Config history fetched successfully"}},"summary":"Config-change history for a single agent","tags":["Agents"]}},"/api/agents/{key}/config":{"get":{"operationId":"AgentConfigController_getConfig","parameters":[{"name":"key","required":true,"in":"path","description":"Agent key, e.g. \"rent-review\"","schema":{"type":"string"}}],"responses":{"200":{"description":"Config fetched successfully"}},"summary":"Get a single agent's effective config","tags":["Agents"]},"patch":{"operationId":"AgentConfigController_update","parameters":[{"name":"key","required":true,"in":"path","description":"Agent key, e.g. \"rent-review\"","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAgentConfigDto"}}}},"responses":{"200":{"description":"Config updated successfully"}},"summary":"Update an agent's config (approvalJson may only tighten policy)","tags":["Agents"]}},"/api/decisions":{"get":{"operationId":"DecisionController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by status","schema":{"type":"string","enum":["AUTO_ACTIONED","PENDING_APPROVAL","APPROVED","REJECTED","OVERRIDDEN","EXPIRED","ADVISORY"]}},{"name":"agentKey","required":false,"in":"query","description":"Filter by agent","schema":{"type":"string","enum":["valuation","rent-review","maintenance-triage","arrears","inspection-scheduler"]}}],"responses":{"200":{"description":"Decisions fetched successfully"}},"summary":"List decisions (paginated, filter status/agentKey)","tags":["Agent Decisions"]}},"/api/approvals/portfolio-summary":{"get":{"operationId":"ApprovalController_portfolioSummary","parameters":[],"responses":{"200":{"description":"Approval inbox summary fetched successfully"}},"summary":"Pending staff-inbox rollup: counts, urgent, value at stake, per-agent chips","tags":["Approvals"]}},"/api/approvals":{"get":{"operationId":"ApprovalController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by status","schema":{"type":"string","enum":["AUTO_ACTIONED","PENDING_APPROVAL","APPROVED","REJECTED","OVERRIDDEN","EXPIRED","ADVISORY"]}},{"name":"approverRole","required":false,"in":"query","description":"Filter by the routed approver role","schema":{"type":"string","enum":["OWNER","STAFF","MANAGER","PRINCIPAL"]}},{"name":"agentKey","required":false,"in":"query","description":"Filter by agent","schema":{"type":"string","enum":["valuation","rent-review","maintenance-triage","arrears","inspection-scheduler"]}},{"name":"ownerScoped","required":false,"in":"query","description":"Only approvals whose decision concerns an owner. Lets the Owners page read a count from meta.total instead of walking every page.","schema":{"type":"boolean"}},{"name":"search","required":false,"in":"query","description":"Search decision title/recommendation and linked property address","schema":{"type":"string"}}],"responses":{"200":{"description":"Approvals fetched successfully"}},"summary":"Approval inbox (paginated, filter status/approverRole/search)","tags":["Approvals"]}},"/api/approvals/{id}":{"get":{"operationId":"ApprovalController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Approval ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Approval fetched successfully"}},"summary":"Get one approval with its decision","tags":["Approvals"]}},"/api/approvals/{id}/approve":{"post":{"operationId":"ApprovalController_approve","parameters":[{"name":"id","required":true,"in":"path","description":"Approval ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideApprovalDto"}}}},"responses":{"200":{"description":"Approval approved"}},"summary":"Approve a decision and dispatch its action","tags":["Approvals"]}},"/api/approvals/{id}/reject":{"post":{"operationId":"ApprovalController_reject","parameters":[{"name":"id","required":true,"in":"path","description":"Approval ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideApprovalDto"}}}},"responses":{"200":{"description":"Approval rejected"}},"summary":"Reject a decision (no action dispatched)","tags":["Approvals"]}},"/api/approvals/{id}/override":{"post":{"operationId":"ApprovalController_override","parameters":[{"name":"id","required":true,"in":"path","description":"Approval ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideApprovalDto"}}}},"responses":{"200":{"description":"Approval overridden"}},"summary":"Override a decision without dispatching the proposed action","tags":["Approvals"]}},"/api/maintenance/jobs/{id}/split-trades":{"post":{"operationId":"MaintenanceSplitController_split","parameters":[{"name":"id","required":true,"in":"path","description":"Job ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SplitMaintenanceJobDto"}}}},"responses":{"200":{"description":"Job split"}},"summary":"Split a job into one child job per trade (staff confirmed), quote each and raise one bundle decision","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/trade-suggestion/dismiss":{"post":{"operationId":"MaintenanceSplitController_dismiss","parameters":[{"name":"id","required":true,"in":"path","description":"Job ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Suggestion dismissed"}},"summary":"Dismiss the suggested extra trades for a job","tags":["Maintenance"]}},"/api/pet-requests/due":{"get":{"operationId":"PetRequestController_findDue","parameters":[],"responses":{"200":{"description":"Due pet requests fetched successfully"}},"summary":"List pending pet requests with daysRemaining on the 21-day statutory clock (NSW)","tags":["Pet Requests"]}},"/api/pet-requests":{"get":{"operationId":"PetRequestController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by pet request status","schema":{"type":"string","enum":["PENDING","APPROVED","REFUSED","AUTO_APPROVED"]}},{"name":"tenancyId","required":false,"in":"query","description":"Filter by tenancy ID","schema":{"type":"string"}},{"name":"propertyId","required":false,"in":"query","description":"Filter by property ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Pet requests fetched successfully"}},"summary":"Get all pet requests with filters and pagination","tags":["Pet Requests"]},"post":{"operationId":"PetRequestController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePetRequestDto"}}}},"responses":{"201":{"description":"Pet request created successfully"}},"summary":"Create a new pet request (respondByDate = requestedDate + 21 days)","tags":["Pet Requests"]}},"/api/pet-requests/{id}":{"get":{"operationId":"PetRequestController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Pet request ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Pet request fetched successfully"}},"summary":"Get a single pet request by ID","tags":["Pet Requests"]},"patch":{"operationId":"PetRequestController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Pet request ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePetRequestDto"}}}},"responses":{"200":{"description":"Pet request updated successfully"}},"summary":"Update a pending pet request","tags":["Pet Requests"]}},"/api/pet-requests/{id}/approve":{"post":{"operationId":"PetRequestController_approve","parameters":[{"name":"id","required":true,"in":"path","description":"Pet request ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Pet request approved"}},"summary":"Approve a pending pet request","tags":["Pet Requests"]}},"/api/pet-requests/{id}/refuse":{"post":{"operationId":"PetRequestController_refuse","parameters":[{"name":"id","required":true,"in":"path","description":"Pet request ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefusePetRequestDto"}}}},"responses":{"200":{"description":"Pet request refused"}},"summary":"Refuse a pending pet request (requires a statutory ground)","tags":["Pet Requests"]}},"/api/notices":{"get":{"operationId":"NoticeController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"type","required":false,"in":"query","description":"Filter by notice type","schema":{"type":"string","enum":["RENT_INCREASE_S41","ENTRY_7DAY","TERMINATION_NONPAYMENT_14DAY","TERMINATION_OTHER"]}},{"name":"status","required":false,"in":"query","description":"Filter by notice status","schema":{"type":"string","enum":["DRAFT","SERVED","EFFECTIVE","WITHDRAWN","BLOCKED"]}},{"name":"tenancyId","required":false,"in":"query","description":"Filter by tenancy ID","schema":{"type":"string"}},{"name":"propertyId","required":false,"in":"query","description":"Filter by property ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Notices fetched successfully"}},"summary":"Get all statutory notices with filters and pagination","tags":["Notices"]},"post":{"description":"Validates statutory minimum lead times in code. Notices that fail validation are still created, but as BLOCKED with blockedReason set, rather than rejected outright.","operationId":"NoticeController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNoticeDto"}}}},"responses":{"201":{"description":"Notice created successfully"}},"summary":"Create a draft statutory notice","tags":["Notices"]}},"/api/notices/portfolio-summary":{"get":{"operationId":"NoticeController_portfolioSummary","parameters":[],"responses":{"200":{"description":""}},"summary":"Notice register rollup (status counts)","tags":["Notices"]}},"/api/notices/export":{"get":{"operationId":"NoticeController_exportCsv","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"type","required":false,"in":"query","description":"Filter by notice type","schema":{"type":"string","enum":["RENT_INCREASE_S41","ENTRY_7DAY","TERMINATION_NONPAYMENT_14DAY","TERMINATION_OTHER"]}},{"name":"status","required":false,"in":"query","description":"Filter by notice status","schema":{"type":"string","enum":["DRAFT","SERVED","EFFECTIVE","WITHDRAWN","BLOCKED"]}},{"name":"tenancyId","required":false,"in":"query","description":"Filter by tenancy ID","schema":{"type":"string"}},{"name":"propertyId","required":false,"in":"query","description":"Filter by property ID","schema":{"type":"string"}}],"responses":{"200":{"description":"CSV"}},"summary":"CSV export of notices matching the current list filters (capped)","tags":["Notices"]}},"/api/notices/{id}":{"get":{"operationId":"NoticeController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Notice ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Notice fetched successfully"}},"summary":"Get a single notice by ID","tags":["Notices"]}},"/api/notices/{id}/document":{"post":{"description":"Produces the servable document and records the template version and content hash on the notice (NFR §13). Rendering is not serving — the notice stays DRAFT. Only DRAFT notices can be rendered; a served notice's document is evidence and is never regenerated. Templates that are not approved render with a \"not for service\" banner and cannot be served. Current templates ship RTA 2010-aligned operational text (not NSW Fair Trading form PDFs).","operationId":"NoticeController_renderDocument","parameters":[{"name":"id","required":true,"in":"path","description":"Notice ID","schema":{"type":"string"}}],"responses":{"201":{"description":"Notice document rendered"}},"summary":"Render the notice to PDF and file it in the DMS","tags":["Notices"]}},"/api/notices/{id}/withdraw":{"post":{"description":"Withdraws a DRAFT. Used to cancel a held ENTRY_7DAY inspection notice before scheduledSendAt. Already served notices cannot be withdrawn.","operationId":"NoticeController_withdraw","parameters":[{"name":"id","required":true,"in":"path","description":"Notice ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Notice withdrawn"}},"summary":"Cancel a draft notice so it will not auto-send","tags":["Notices"]}},"/api/notices/{id}/serve":{"post":{"description":"The only path to NoticeStatus.SERVED. No notice type — including TERMINATION_NONPAYMENT_14DAY — is ever auto-served. Requires a rendered document from an approved template. On success the document is published to the tenant portal and emailed to every tenant with the PDF attached (set deliverByEmail=false to serve by post/in person). Delivery problems are reported in the response, never by un-serving the notice.","operationId":"NoticeController_serve","parameters":[{"name":"id","required":true,"in":"path","description":"Notice ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServeNoticeDto"}}}},"responses":{"200":{"description":"Notice served"}},"summary":"Serve a draft notice and deliver it (explicit staff action)","tags":["Notices"]}},"/api/tenancies":{"get":{"operationId":"TenancyController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by lifecycle status","schema":{"example":"ACTIVE","type":"string","enum":["PROSPECTIVE","ACTIVE","VACATING","VACATED","ARCHIVED"]}},{"name":"propertyId","required":false,"in":"query","description":"Filter by property ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"managerUserId","required":false,"in":"query","description":"Filter by managing staff user ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"ids","required":false,"in":"query","description":"Restrict to these tenancy IDs (max 100, comma-separated)","schema":{"type":"array","items":{"type":"string"}}}],"responses":{"200":{"description":"Tenancies fetched successfully"}},"summary":"Get all tenancies with filters and pagination","tags":["Tenancies"]},"post":{"operationId":"TenancyController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTenancyDto"}}}},"responses":{"201":{"description":"Tenancy created successfully"}},"summary":"Create a new tenancy","tags":["Tenancies"]}},"/api/tenancies/portfolio-summary":{"get":{"operationId":"TenancyController_portfolioSummary","parameters":[],"responses":{"200":{"description":""}},"summary":"Tenancy register rollup (status counts + leases expiring within 60 days)","tags":["Tenancies"]}},"/api/tenancies/export":{"get":{"operationId":"TenancyController_exportCsv","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by lifecycle status","schema":{"example":"ACTIVE","type":"string","enum":["PROSPECTIVE","ACTIVE","VACATING","VACATED","ARCHIVED"]}},{"name":"propertyId","required":false,"in":"query","description":"Filter by property ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"managerUserId","required":false,"in":"query","description":"Filter by managing staff user ID","schema":{"example":"cmieqoaba0000iymt4fab0345","type":"string"}},{"name":"ids","required":false,"in":"query","description":"Restrict to these tenancy IDs (max 100, comma-separated)","schema":{"type":"array","items":{"type":"string"}}}],"responses":{"200":{"description":"CSV"}},"summary":"CSV export of tenancies matching the current list filters (capped)","tags":["Tenancies"]}},"/api/tenancies/rent-reviews/portfolio-summary":{"get":{"operationId":"TenancyController_getRentReviewPortfolioSummary","parameters":[],"responses":{"200":{"description":"Rent review portfolio summary fetched successfully"}},"summary":"Rent-review portfolio rollup (BRD §7.7): reviews this quarter, average uplift, owner approval rate, due within 90 days","tags":["Tenancies"]}},"/api/tenancies/{id}":{"get":{"operationId":"TenancyController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Tenancy fetched successfully"}},"summary":"Get a single tenancy by ID","tags":["Tenancies"]},"patch":{"operationId":"TenancyController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTenancyDto"}}}},"responses":{"200":{"description":"Tenancy updated successfully"}},"summary":"Update a tenancy (fields and/or a single lifecycle status transition)","tags":["Tenancies"]},"delete":{"operationId":"TenancyController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Tenancy deleted successfully"}},"summary":"Soft-delete a tenancy","tags":["Tenancies"]}},"/api/tenancies/{id}/tenants":{"post":{"operationId":"TenancyController_addTenant","parameters":[{"name":"id","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddTenancyTenantDto"}}}},"responses":{"201":{"description":"Tenant linked successfully"}},"summary":"Link a tenant to a tenancy","tags":["Tenancies"]}},"/api/tenancies/{id}/tenants/{tenantId}":{"patch":{"operationId":"TenancyController_updateTenantLink","parameters":[{"name":"id","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}},{"name":"tenantId","required":true,"in":"path","description":"Tenant ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTenancyTenantDto"}}}},"responses":{"200":{"description":"Tenant link updated successfully"}},"summary":"Update a linked tenant's primary flag","tags":["Tenancies"]},"delete":{"operationId":"TenancyController_removeTenant","parameters":[{"name":"id","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}},{"name":"tenantId","required":true,"in":"path","description":"Tenant ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Tenant unlinked successfully"}},"summary":"Unlink a tenant from a tenancy","tags":["Tenancies"]}},"/api/tenancies/{id}/lease":{"get":{"operationId":"TenancyController_getLease","parameters":[{"name":"id","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Lease fetched successfully"}},"summary":"Get the lease for a tenancy","tags":["Tenancies"]},"put":{"operationId":"TenancyController_putLease","parameters":[{"name":"id","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertLeaseDto"}}}},"responses":{"200":{"description":"Lease saved successfully"}},"summary":"Create or replace the lease for a tenancy","tags":["Tenancies"]}},"/api/tenancies/{id}/bond":{"get":{"operationId":"TenancyController_getBond","parameters":[{"name":"id","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Bond fetched successfully"}},"summary":"Get the bond for a tenancy","tags":["Tenancies"]},"put":{"operationId":"TenancyController_putBond","parameters":[{"name":"id","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertBondDto"}}}},"responses":{"200":{"description":"Bond saved successfully"}},"summary":"Create or replace the bond for a tenancy","tags":["Tenancies"]}},"/api/tenancies/{id}/rent-schedule":{"get":{"operationId":"TenancyController_getRentSchedule","parameters":[{"name":"id","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Rent schedule fetched successfully"}},"summary":"Get the rent schedule for a tenancy","tags":["Tenancies"]},"put":{"operationId":"TenancyController_putRentSchedule","parameters":[{"name":"id","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertRentScheduleDto"}}}},"responses":{"200":{"description":"Rent schedule saved successfully"}},"summary":"Create or replace the rent schedule for a tenancy","tags":["Tenancies"]}},"/api/tenancies/{id}/rent-reviews":{"get":{"operationId":"TenancyController_listRentReviews","parameters":[{"name":"id","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}}],"responses":{"200":{"description":"Rent reviews fetched successfully"}},"summary":"List rent reviews for a tenancy","tags":["Tenancies"]},"post":{"operationId":"TenancyController_createRentReview","parameters":[{"name":"id","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRentReviewDto"}}}},"responses":{"201":{"description":"Rent review created successfully"}},"summary":"Create a rent review. Blocked (with earliest lawful date) if within the 12-month gate.","tags":["Tenancies"]}},"/api/tenants":{"get":{"operationId":"TenantController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}}],"responses":{"200":{"description":"Tenants fetched successfully"}},"summary":"Get all tenants (registry) with pagination","tags":["Tenants"]},"post":{"operationId":"TenantController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTenantDto"}}}},"responses":{"201":{"description":"Tenant created successfully"}},"summary":"Create a new tenant (registry entry)","tags":["Tenants"]}},"/api/tenants/directory":{"get":{"operationId":"TenantController_findDirectory","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search tenant name/email/phone, tenancy ref, property ref/address/suburb","schema":{"type":"string"}},{"name":"active","required":false,"in":"query","description":"true = holds a rent-bearing tenancy, false = only historical tenancies","schema":{"type":"boolean"}},{"name":"inArrears","required":false,"in":"query","description":"Only tenants whose current tenancy is in arrears","schema":{"type":"boolean"}},{"name":"leaseType","required":false,"in":"query","description":"Only tenants holding a live tenancy on this lease type","schema":{"type":"string","enum":["FIXED","PERIODIC"]}},{"name":"managerUserId","required":false,"in":"query","description":"Only tenants whose live tenancy has this property manager","schema":{"type":"string"}}],"responses":{"200":{"description":"Tenants fetched successfully"}},"summary":"Tenant directory grid: one page joined to the current tenancy, property and ledger balance","tags":["Tenants"]}},"/api/tenants/portfolio-summary":{"get":{"operationId":"TenantController_portfolioSummary","parameters":[],"responses":{"200":{"description":"Summary fetched successfully"}},"summary":"Tenant directory counters (whole organisation, database aggregates)","tags":["Tenants"]}},"/api/tenants/{id}":{"get":{"operationId":"TenantController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Tenant ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Tenant fetched successfully"}},"summary":"Get a single tenant by ID","tags":["Tenants"]},"patch":{"operationId":"TenantController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Tenant ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTenantDto"}}}},"responses":{"200":{"description":"Tenant updated successfully"}},"summary":"Update a tenant","tags":["Tenants"]},"delete":{"operationId":"TenantController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Tenant ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Tenant deleted successfully"}},"summary":"Soft-delete a tenant","tags":["Tenants"]}},"/api/maintenance/jobs":{"get":{"operationId":"MaintenanceJobController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by status","schema":{"type":"string","enum":["NEW","TRIAGE","AWAITING_OWNER","QUOTING","APPROVED","SCHEDULED","IN_PROGRESS","COMPLETION_REVIEW","COMPLETED","INVOICED","ON_HOLD","CANCELLED"]}},{"name":"statuses","required":false,"in":"query","description":"Filter by multiple statuses (comma-separated, max 20). Takes precedence over `status` when both are supplied.","schema":{"type":"array","items":{"type":"string"}}},{"name":"priority","required":false,"in":"query","description":"Filter by priority","schema":{"type":"string","enum":["P1","P2","P3","P4"]}},{"name":"responsibility","required":false,"in":"query","description":"Filter by responsibility","schema":{"type":"string","enum":["OWNER","TENANT","UNDETERMINED"]}},{"name":"propertyId","required":false,"in":"query","description":"Filter by property","schema":{"example":"cm123property","type":"string"}},{"name":"tenancyId","required":false,"in":"query","description":"Filter by tenancy","schema":{"example":"cm123tenancy","type":"string"}},{"name":"supplierId","required":false,"in":"query","description":"Filter by assigned supplier","schema":{"example":"cm123supplier","type":"string"}},{"name":"assignedToUserId","required":false,"in":"query","description":"Filter by managing staff user","schema":{"type":"string"}},{"name":"isUrgentRepair","required":false,"in":"query","description":"Filter to urgent-repair jobs only","schema":{"type":"boolean"}},{"name":"missingEvidence","required":false,"in":"query","description":"Closed jobs (COMPLETED / INVOICED) whose property file is still missing a work order, completion photos or an invoice. Open jobs are never included: absent evidence before the work is done is expected, not a gap.","schema":{"type":"boolean"}},{"name":"source","required":false,"in":"query","description":"Filter by origin. oneagency = logged here; propertyme = imported working copy. Default is both.","schema":{"type":"string","enum":["oneagency","propertyme"]}},{"name":"includeSplits","required":false,"in":"query","description":"Include the per-trade child jobs of split requests as their own rows. Default false: staff see one job per report, with its trades inside it.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Jobs fetched successfully"}},"summary":"List maintenance jobs with filters and pagination","tags":["Maintenance"]},"post":{"operationId":"MaintenanceJobController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMaintenanceJobDto"}}}},"responses":{"201":{"description":"Job created successfully"}},"summary":"Create a new maintenance job","tags":["Maintenance"]}},"/api/maintenance/jobs/portfolio-summary":{"get":{"operationId":"MaintenanceJobController_getPortfolioSummary","parameters":[],"responses":{"200":{"description":"Maintenance portfolio summary fetched successfully"}},"summary":"Maintenance portfolio rollup (BRD §7.4): owner spend MTD, auto-approved, cost vs estimate, open urgent","tags":["Maintenance"]}},"/api/maintenance/jobs/report/by-category":{"get":{"operationId":"MaintenanceJobController_reportByCategory","parameters":[{"name":"from","required":true,"in":"query","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Report fetched successfully"}},"summary":"Maintenance report roll-up by trade category over the complete matching dataset (optional from/to)","tags":["Maintenance"]}},"/api/maintenance/jobs/calendar":{"get":{"operationId":"MaintenanceJobController_calendar","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by status","schema":{"type":"string","enum":["NEW","TRIAGE","AWAITING_OWNER","QUOTING","APPROVED","SCHEDULED","IN_PROGRESS","COMPLETION_REVIEW","COMPLETED","INVOICED","ON_HOLD","CANCELLED"]}},{"name":"statuses","required":false,"in":"query","description":"Filter by multiple statuses (comma-separated, max 20). Takes precedence over `status` when both are supplied.","schema":{"type":"array","items":{"type":"string"}}},{"name":"priority","required":false,"in":"query","description":"Filter by priority","schema":{"type":"string","enum":["P1","P2","P3","P4"]}},{"name":"responsibility","required":false,"in":"query","description":"Filter by responsibility","schema":{"type":"string","enum":["OWNER","TENANT","UNDETERMINED"]}},{"name":"propertyId","required":false,"in":"query","description":"Filter by property","schema":{"example":"cm123property","type":"string"}},{"name":"tenancyId","required":false,"in":"query","description":"Filter by tenancy","schema":{"example":"cm123tenancy","type":"string"}},{"name":"supplierId","required":false,"in":"query","description":"Filter by assigned supplier","schema":{"example":"cm123supplier","type":"string"}},{"name":"assignedToUserId","required":false,"in":"query","description":"Filter by managing staff user","schema":{"type":"string"}},{"name":"isUrgentRepair","required":false,"in":"query","description":"Filter to urgent-repair jobs only","schema":{"type":"boolean"}},{"name":"missingEvidence","required":false,"in":"query","description":"Closed jobs (COMPLETED / INVOICED) whose property file is still missing a work order, completion photos or an invoice. Open jobs are never included: absent evidence before the work is done is expected, not a gap.","schema":{"type":"boolean"}},{"name":"source","required":false,"in":"query","description":"Filter by origin. oneagency = logged here; propertyme = imported working copy. Default is both.","schema":{"type":"string","enum":["oneagency","propertyme"]}},{"name":"includeSplits","required":false,"in":"query","description":"Include the per-trade child jobs of split requests as their own rows. Default false: staff see one job per report, with its trades inside it.","schema":{"type":"boolean"}},{"name":"from","required":false,"in":"query","description":"First Sydney day, YYYY-MM-DD","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"Last Sydney day (inclusive), YYYY-MM-DD","schema":{"type":"string"}}],"responses":{"200":{"description":"Calendar events fetched"}},"summary":"Activity calendar: workflow milestones per Australia/Sydney day (from/to YYYY-MM-DD, plus list filters)","tags":["Maintenance"]}},"/api/maintenance/jobs/urgent":{"get":{"operationId":"MaintenanceJobController_findUrgent","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by status","schema":{"type":"string","enum":["NEW","TRIAGE","AWAITING_OWNER","QUOTING","APPROVED","SCHEDULED","IN_PROGRESS","COMPLETION_REVIEW","COMPLETED","INVOICED","ON_HOLD","CANCELLED"]}},{"name":"statuses","required":false,"in":"query","description":"Filter by multiple statuses (comma-separated, max 20). Takes precedence over `status` when both are supplied.","schema":{"type":"array","items":{"type":"string"}}},{"name":"priority","required":false,"in":"query","description":"Filter by priority","schema":{"type":"string","enum":["P1","P2","P3","P4"]}},{"name":"responsibility","required":false,"in":"query","description":"Filter by responsibility","schema":{"type":"string","enum":["OWNER","TENANT","UNDETERMINED"]}},{"name":"propertyId","required":false,"in":"query","description":"Filter by property","schema":{"example":"cm123property","type":"string"}},{"name":"tenancyId","required":false,"in":"query","description":"Filter by tenancy","schema":{"example":"cm123tenancy","type":"string"}},{"name":"supplierId","required":false,"in":"query","description":"Filter by assigned supplier","schema":{"example":"cm123supplier","type":"string"}},{"name":"assignedToUserId","required":false,"in":"query","description":"Filter by managing staff user","schema":{"type":"string"}},{"name":"isUrgentRepair","required":false,"in":"query","description":"Filter to urgent-repair jobs only","schema":{"type":"boolean"}},{"name":"missingEvidence","required":false,"in":"query","description":"Closed jobs (COMPLETED / INVOICED) whose property file is still missing a work order, completion photos or an invoice. Open jobs are never included: absent evidence before the work is done is expected, not a gap.","schema":{"type":"boolean"}},{"name":"source","required":false,"in":"query","description":"Filter by origin. oneagency = logged here; propertyme = imported working copy. Default is both.","schema":{"type":"string","enum":["oneagency","propertyme"]}},{"name":"includeSplits","required":false,"in":"query","description":"Include the per-trade child jobs of split requests as their own rows. Default false: staff see one job per report, with its trades inside it.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Urgent jobs fetched successfully"}},"summary":"List active urgent-repair jobs (statutory path)","tags":["Maintenance"]}},"/api/maintenance/jobs/export":{"get":{"operationId":"MaintenanceJobController_exportCsv","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by status","schema":{"type":"string","enum":["NEW","TRIAGE","AWAITING_OWNER","QUOTING","APPROVED","SCHEDULED","IN_PROGRESS","COMPLETION_REVIEW","COMPLETED","INVOICED","ON_HOLD","CANCELLED"]}},{"name":"statuses","required":false,"in":"query","description":"Filter by multiple statuses (comma-separated, max 20). Takes precedence over `status` when both are supplied.","schema":{"type":"array","items":{"type":"string"}}},{"name":"priority","required":false,"in":"query","description":"Filter by priority","schema":{"type":"string","enum":["P1","P2","P3","P4"]}},{"name":"responsibility","required":false,"in":"query","description":"Filter by responsibility","schema":{"type":"string","enum":["OWNER","TENANT","UNDETERMINED"]}},{"name":"propertyId","required":false,"in":"query","description":"Filter by property","schema":{"example":"cm123property","type":"string"}},{"name":"tenancyId","required":false,"in":"query","description":"Filter by tenancy","schema":{"example":"cm123tenancy","type":"string"}},{"name":"supplierId","required":false,"in":"query","description":"Filter by assigned supplier","schema":{"example":"cm123supplier","type":"string"}},{"name":"assignedToUserId","required":false,"in":"query","description":"Filter by managing staff user","schema":{"type":"string"}},{"name":"isUrgentRepair","required":false,"in":"query","description":"Filter to urgent-repair jobs only","schema":{"type":"boolean"}},{"name":"missingEvidence","required":false,"in":"query","description":"Closed jobs (COMPLETED / INVOICED) whose property file is still missing a work order, completion photos or an invoice. Open jobs are never included: absent evidence before the work is done is expected, not a gap.","schema":{"type":"boolean"}},{"name":"source","required":false,"in":"query","description":"Filter by origin. oneagency = logged here; propertyme = imported working copy. Default is both.","schema":{"type":"string","enum":["oneagency","propertyme"]}},{"name":"includeSplits","required":false,"in":"query","description":"Include the per-trade child jobs of split requests as their own rows. Default false: staff see one job per report, with its trades inside it.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"CSV"}},"summary":"CSV export of maintenance jobs matching the current list filters (capped)","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}":{"get":{"operationId":"MaintenanceJobController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Job ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Job fetched successfully"}},"summary":"Get a single maintenance job by ID","tags":["Maintenance"]},"patch":{"operationId":"MaintenanceJobController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Job ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMaintenanceJobDto"}}}},"responses":{"200":{"description":"Job updated successfully"}},"summary":"Update a maintenance job","tags":["Maintenance"]},"delete":{"operationId":"MaintenanceJobController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Job ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Job deleted successfully"}},"summary":"Soft-delete a maintenance job","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/status":{"patch":{"operationId":"MaintenanceJobController_updateStatus","parameters":[{"name":"id","required":true,"in":"path","description":"Job ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMaintenanceJobStatusDto"}}}},"responses":{"200":{"description":"Status updated successfully"}},"summary":"Transition a job to a new lifecycle status","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/owner-pathway":{"post":{"operationId":"MaintenanceJobController_setOwnerPathway","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OwnerPathwayDto"}}}},"responses":{"201":{"description":""}},"summary":"Ask the owner quotes vs direct, or record their reply. Distinct from spend-cap approval.","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/owner-quote-action":{"post":{"operationId":"MaintenanceJobController_recordOwnerQuoteAction","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OwnerQuoteActionDto"}}}},"responses":{"201":{"description":""}},"summary":"Record owner approve / reject / hold / request-more on quotes","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/quote-review/reopen":{"post":{"operationId":"MaintenanceJobController_reopenQuoteReview","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReopenQuoteReviewDto"}}}},"responses":{"201":{"description":""}},"summary":"Reopen quote review after an owner selection so they can choose again. Does not assign or contact a tradesperson.","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/activity":{"get":{"operationId":"MaintenanceJobController_activity","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"cursor","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Chronological activity for one job (staff view, includes internal entries)","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/evidence/uploaded":{"post":{"operationId":"MaintenanceJobController_recordEvidenceUploaded","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordEvidenceUploadedDto"}}}},"responses":{"201":{"description":""}},"summary":"Record in Activity that reported-evidence files already uploaded via the DMS pipeline landed successfully. Uploads nothing itself — verifies and logs.","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/emergency":{"post":{"operationId":"MaintenanceJobController_emergencyBypass","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmergencyBypassDto"}}}},"responses":{"201":{"description":""}},"summary":"Administrator emergency bypass — skip owner permission and quoting, assign a tradesperson now","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/emergency/notify-owner":{"post":{"operationId":"MaintenanceJobController_notifyOwnerOfEmergency","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"summary":"Tell the owner an emergency repair was arranged","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/hold":{"post":{"operationId":"MaintenanceJobController_hold","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobReasonDto"}}}},"responses":{"201":{"description":""}},"summary":"Pause the job, remembering where it paused","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/resume":{"post":{"operationId":"MaintenanceJobController_resume","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"summary":"Return a held job to the stage it paused at","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/cancel":{"post":{"operationId":"MaintenanceJobController_cancel","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobReasonDto"}}}},"responses":{"201":{"description":""}},"summary":"Cancel the job with a recorded reason","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/completion-review":{"post":{"operationId":"MaintenanceJobController_reviewCompletion","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewCompletionDto"}}}},"responses":{"201":{"description":""}},"summary":"Staff accepts the tradesperson completion package, or sends it back","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/trade-links":{"get":{"operationId":"MaintenanceJobController_listTradeLinks","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Secure tradesperson links issued for this job","tags":["Maintenance"]},"post":{"operationId":"MaintenanceJobController_sendTradeLink","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendCompletionLinkDto"}}}},"responses":{"201":{"description":""}},"summary":"Issue a secure upload link and email it to the assigned tradesperson","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/trade-links/revoke":{"post":{"operationId":"MaintenanceJobController_revokeTradeLinks","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeLinksDto"}}}},"responses":{"201":{"description":""}},"summary":"Revoke every live tradesperson link on this job","tags":["Maintenance"]}},"/api/maintenance/jobs/comms/sms-status":{"get":{"operationId":"MaintenanceJobController_smsStatus","parameters":[],"responses":{"200":{"description":""}},"summary":"Whether SMS can actually be sent, so the UI can say so honestly","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/quote-requests":{"post":{"operationId":"MaintenanceJobController_requestQuotes","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestQuotesDto"}}}},"responses":{"201":{"description":""}},"summary":"Send a quote request to each chosen tradesperson. Staff pick the suppliers — selection is never automatic.","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/comms/preview":{"post":{"operationId":"MaintenanceJobController_previewComms","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaintenanceCommsPreviewDto"}}}},"responses":{"200":{"description":""}},"summary":"Preview the exact email an action will send — recipients, subject, body, attachments and any test redirect","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/quotes/{quoteId}/forward":{"post":{"operationId":"MaintenanceJobController_forwardQuote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"quoteId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForwardQuoteDto"}}}},"responses":{"201":{"description":""}},"summary":"Forward one quote to the owner, with the quote document attached. Sent per quote as each arrives.","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/work-order":{"post":{"operationId":"MaintenanceJobController_issueWorkOrder","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueWorkOrderDto"}}}},"responses":{"201":{"description":""}},"summary":"Issue a work order (timestamp + email to trades). Internal notes are not a work order.","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/notify-complete":{"post":{"operationId":"MaintenanceJobController_notifyOwnerComplete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotifyCompleteDto"}}}},"responses":{"201":{"description":""}},"summary":"Email the owner that the repair is complete","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/quotes":{"get":{"operationId":"MaintenanceJobController_listQuotes","parameters":[{"name":"id","required":true,"in":"path","description":"Job ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Quotes fetched successfully"}},"summary":"List quotes received for a job","tags":["Maintenance"]},"post":{"operationId":"MaintenanceJobController_addQuote","parameters":[{"name":"id","required":true,"in":"path","description":"Job ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMaintenanceQuoteDto"}}}},"responses":{"201":{"description":"Quote recorded successfully"}},"summary":"Record a quote received for a job","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/quotes/{quoteId}":{"patch":{"operationId":"MaintenanceJobController_updateQuote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"quoteId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMaintenanceQuoteDto"}}}},"responses":{"200":{"description":""}},"summary":"Edit a supplier-confirmed quote","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/quotes/{quoteId}/withdraw":{"post":{"operationId":"MaintenanceJobController_withdrawQuote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"quoteId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WithdrawMaintenanceQuoteDto"}}}},"responses":{"201":{"description":""}},"summary":"Mark a supplier-confirmed quote withdrawn or expired","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/messages":{"get":{"operationId":"MaintenanceJobController_listMessages","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"The job's email/SMS history and who can be written to","tags":["Maintenance"]},"post":{"operationId":"MaintenanceJobController_sendMessage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendJobMessageDto"}}}},"responses":{"201":{"description":""}},"summary":"Email or SMS the tenant, owner or tradesperson about this job","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/messages/{messageId}/resend":{"post":{"operationId":"MaintenanceJobController_resendMessage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"summary":"Resend a message that never went out","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/tenant-update/send":{"post":{"operationId":"MaintenanceJobController_sendTenantUpdate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendTenantUpdateDto"}}}},"responses":{"201":{"description":""}},"summary":"Send the tenant an update for the current stage, with optional subject/message wording.","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/quotes/{quoteId}/accept":{"post":{"operationId":"MaintenanceJobController_acceptQuote","parameters":[{"name":"id","required":true,"in":"path","description":"Job ID","schema":{"type":"string"}},{"name":"quoteId","required":true,"in":"path","description":"Quote ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptMaintenanceQuoteDto"}}}},"responses":{"200":{"description":"Quote accepted successfully"}},"summary":"Accept a quote — sets acceptedQuoteId/agreedCostCents/supplier and flips status to APPROVED or SCHEDULED","tags":["Maintenance"]}},"/api/maintenance/jobs/{id}/invoice":{"post":{"operationId":"MaintenanceJobController_recordInvoice","parameters":[{"name":"id","required":true,"in":"path","description":"Job ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordMaintenanceInvoiceDto"}}}},"responses":{"200":{"description":"Invoice recorded successfully"}},"summary":"Record the received invoice and compute variance/match against the agreed quote cost","tags":["Maintenance"]}},"/api/suppliers":{"get":{"operationId":"SupplierController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"trade","required":false,"in":"query","description":"Filter by trade","schema":{"example":"plumbing","type":"string"}},{"name":"preferred","required":false,"in":"query","description":"Filter to preferred suppliers only","schema":{"type":"boolean"}},{"name":"emergencyVendor","required":false,"in":"query","description":"Filter to emergency/after-hours vendors only","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Suppliers fetched successfully"}},"summary":"List suppliers with filters and pagination","tags":["Suppliers"]},"post":{"operationId":"SupplierController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSupplierDto"}}}},"responses":{"201":{"description":"Supplier created successfully"}},"summary":"Create a new supplier","tags":["Suppliers"]}},"/api/suppliers/directory":{"get":{"operationId":"SupplierController_findDirectory","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search name, trade, email or phone","schema":{"type":"string"}},{"name":"trade","required":false,"in":"query","description":"Filter by trade","schema":{"example":"plumber","type":"string"}},{"name":"preferred","required":false,"in":"query","description":"Only preferred suppliers","schema":{"type":"boolean"}},{"name":"emergencyVendor","required":false,"in":"query","description":"Only emergency/after-hours vendors","schema":{"type":"boolean"}},{"name":"hasOpenJobs","required":false,"in":"query","description":"Only suppliers with a non-terminal maintenance job","schema":{"type":"boolean"}},{"name":"complianceDue","required":false,"in":"query","description":"Only suppliers whose licence or insurance has expired or expires within 60 days","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Suppliers fetched successfully"}},"summary":"Supplier directory grid: one page with live open-job counts","tags":["Suppliers"]}},"/api/suppliers/portfolio-summary":{"get":{"operationId":"SupplierController_portfolioSummary","parameters":[],"responses":{"200":{"description":"Summary fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierPortfolioSummaryResponseDto"}}}}},"summary":"Supplier directory counters (whole organisation, database aggregates)","tags":["Suppliers"]}},"/api/suppliers/{id}":{"get":{"operationId":"SupplierController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Supplier ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Supplier fetched successfully"}},"summary":"Get a single supplier by ID","tags":["Suppliers"]},"patch":{"operationId":"SupplierController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Supplier ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSupplierDto"}}}},"responses":{"200":{"description":"Supplier updated successfully"}},"summary":"Update a supplier","tags":["Suppliers"]},"delete":{"operationId":"SupplierController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Supplier ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Supplier deleted successfully"}},"summary":"Soft-delete a supplier","tags":["Suppliers"]}},"/api/action-queue":{"get":{"description":"Actions an agent decided on that the platform cannot execute itself, because the target record is owned by an external system OneAgency holds read-only scopes for (ADR-0005). Pending items first.","operationId":"ActionQueueController_findAll","parameters":[],"responses":{"200":{"description":"Action queue items"}},"summary":"Manual actions awaiting human execution","tags":["Action queue"]}},"/api/action-queue/{id}/complete":{"post":{"description":"Records that a staff member carried the action out in the external system. Idempotent — completing an already-completed item is a no-op and never overwrites the original actor or timestamp.","operationId":"ActionQueueController_complete","parameters":[{"name":"id","required":true,"in":"path","description":"Action queue item id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteActionQueueItemDto"}}}},"responses":{"201":{"description":""}},"summary":"Confirm a manual action was performed","tags":["Action queue"]}},"/api/inspections/portfolio-summary":{"get":{"operationId":"InspectionController_getPortfolioSummary","parameters":[],"responses":{"200":{"description":"Inspection portfolio summary fetched successfully"}},"summary":"Inspection portfolio rollup (BRD §7.2): overdue, scheduled this week, no-show proxy, due unbooked","tags":["Inspections"]}},"/api/inspections/due":{"get":{"operationId":"InspectionController_findDue","parameters":[{"name":"days","required":false,"in":"query","description":"Look-ahead window in days (default 45 — matches Inspection Scheduler / Eve sweep)","schema":{"minimum":1,"maximum":365,"default":45,"example":45,"type":"number"}},{"name":"intervalMonths","required":false,"in":"query","description":"Routine inspection interval in months, used to compute next-due. Defaults to ROUTINE_INTERVAL_MONTHS (12).","schema":{"minimum":1,"maximum":24,"default":12,"example":12,"type":"number"}}],"responses":{"200":{"description":"Due inspections fetched successfully"}},"summary":"Calculated routine due list (due within N days, no upcoming appointment), on the ROUTINE_INTERVAL_MONTHS cadence by default. The monitoring workspace does not use it: it shows PropertyMe's own due dates.","tags":["Inspections"]}},"/api/inspections":{"get":{"operationId":"InspectionController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"propertyId","required":false,"in":"query","description":"Filter by property ID","schema":{"example":"clm123abc","type":"string"}},{"name":"tenancyId","required":false,"in":"query","description":"Filter by tenancy ID","schema":{"example":"clm456def","type":"string"}},{"name":"type","required":false,"in":"query","description":"Filter by inspection type","schema":{"example":"ROUTINE","type":"string","enum":["ENTRY","ROUTINE","EXIT"]}},{"name":"status","required":false,"in":"query","description":"Filter by inspection status","schema":{"example":"SCHEDULED","type":"string","enum":["SCHEDULED","IN_PROGRESS","COMPLETED","REPORT_SENT","OVERDUE"]}},{"name":"statuses","required":false,"in":"query","description":"Filter by multiple statuses (comma-separated, max 20). Takes precedence over `status` when both are supplied.","schema":{"type":"array","items":{"type":"string"}}},{"name":"scheduledFrom","required":false,"in":"query","description":"Filter inspections scheduled from this date (ISO)","schema":{"example":"2026-08-01","type":"string"}},{"name":"scheduledTo","required":false,"in":"query","description":"Filter inspections scheduled until this date (ISO)","schema":{"example":"2026-08-31","type":"string"}}],"responses":{"200":{"description":"Inspections fetched successfully"}},"summary":"List inspections with filters and pagination","tags":["Inspections"]},"post":{"operationId":"InspectionController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInspectionDto"}}}},"responses":{"201":{"description":"Inspection created successfully"}},"summary":"Create a new inspection","tags":["Inspections"]}},"/api/inspections/export":{"get":{"operationId":"InspectionController_exportCsv","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"example":"john","type":"string"}},{"name":"propertyId","required":false,"in":"query","description":"Filter by property ID","schema":{"example":"clm123abc","type":"string"}},{"name":"tenancyId","required":false,"in":"query","description":"Filter by tenancy ID","schema":{"example":"clm456def","type":"string"}},{"name":"type","required":false,"in":"query","description":"Filter by inspection type","schema":{"example":"ROUTINE","type":"string","enum":["ENTRY","ROUTINE","EXIT"]}},{"name":"status","required":false,"in":"query","description":"Filter by inspection status","schema":{"example":"SCHEDULED","type":"string","enum":["SCHEDULED","IN_PROGRESS","COMPLETED","REPORT_SENT","OVERDUE"]}},{"name":"statuses","required":false,"in":"query","description":"Filter by multiple statuses (comma-separated, max 20). Takes precedence over `status` when both are supplied.","schema":{"type":"array","items":{"type":"string"}}},{"name":"scheduledFrom","required":false,"in":"query","description":"Filter inspections scheduled from this date (ISO)","schema":{"example":"2026-08-01","type":"string"}},{"name":"scheduledTo","required":false,"in":"query","description":"Filter inspections scheduled until this date (ISO)","schema":{"example":"2026-08-31","type":"string"}}],"responses":{"200":{"description":"CSV"}},"summary":"CSV export of inspections matching the current list filters (capped)","tags":["Inspections"]}},"/api/inspections/{id}":{"patch":{"operationId":"InspectionController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Inspection ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateInspectionDto"}}}},"responses":{"200":{"description":"Inspection updated successfully"}},"summary":"Update an inspection","tags":["Inspections"]},"get":{"operationId":"InspectionController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Inspection ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Inspection fetched successfully"}},"summary":"Get a single inspection by ID","tags":["Inspections"]}},"/api/inspections/workspace/month":{"get":{"operationId":"InspectionController_workspace","parameters":[{"name":"month","required":false,"in":"query","description":"Sydney calendar month to scope to, as YYYY-MM. Defaults to the current Sydney month.","schema":{"example":"2026-09","type":"string"}},{"name":"scope","required":false,"in":"query","description":"'month' (default): items whose effective due date falls in the month. 'earlier': the outstanding backlog — overdue-condition items dated before the month starts. 'overdue': every outstanding item dated before today (the backlog plus this month's overdue). Backlog scopes leave out items already done by a later completed visit (see supersededRows).","schema":{"default":"month","type":"string","enum":["month","earlier","overdue"]}},{"name":"datelessOnly","required":false,"in":"query","description":"true: only items with no usable date (never bucketed into any month).","schema":{"type":"boolean"}},{"name":"types","required":false,"in":"query","description":"Inspection types (comma-separated).","schema":{"type":"array","items":{"type":"string"}}},{"name":"progress","required":false,"in":"query","description":"Progress buckets (comma-separated).","schema":{"type":"array","items":{"type":"string"}}},{"name":"search","required":false,"in":"query","description":"Free text over address, suburb, refs and tenant name.","schema":{"type":"string"}},{"name":"suburb","required":false,"in":"query","description":"Exact suburb (case-insensitive).","schema":{"type":"string"}},{"name":"manager","required":false,"in":"query","description":"Managing staff display name (exact, case-insensitive), or 'unassigned'.","schema":{"type":"string"}}],"responses":{"200":{"description":"Workspace fetched successfully"}},"summary":"Month-scoped monitoring read-model: records + calculated due items, summary counts, facets. Read-only — opening it writes nothing.","tags":["Inspections"]}},"/api/inspections/worklists":{"get":{"operationId":"InspectionController_listWorklists","parameters":[],"responses":{"200":{"description":""}},"summary":"Saved contractor property lists. Coordination only — nothing is booked or sent.","tags":["Inspections"]},"post":{"operationId":"InspectionController_createWorklist","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveInspectionWorklistDto"}}}},"responses":{"201":{"description":""}},"summary":"Save an ordered contractor property list","tags":["Inspections"]}},"/api/inspections/worklists/upcoming-membership":{"get":{"operationId":"InspectionController_worklistUpcomingMembership","parameters":[],"responses":{"200":{"description":""}},"summary":"Cheap map of which inspections sit on a list whose day is today or later — for a small 'on X's list' badge.","tags":["Inspections"]}},"/api/inspections/worklists/{id}":{"get":{"operationId":"InspectionController_getWorklist","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"One contractor list, with per-stop details for the run sheet.","tags":["Inspections"]},"patch":{"operationId":"InspectionController_updateWorklist","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveInspectionWorklistDto"}}}},"responses":{"200":{"description":""}},"summary":"Update an ordered contractor property list","tags":["Inspections"]},"delete":{"operationId":"InspectionController_removeWorklist","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Remove a contractor property list","tags":["Inspections"]}},"/api/inspections/worklists/{id}/pdf":{"get":{"operationId":"InspectionController_getWorklistPdf","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"inline","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"The contractor run sheet as a branded PDF — same data as the run sheet page. ?inline=1 previews instead of downloading.","tags":["Inspections"]}},"/api/inspections/{id}/activity":{"get":{"operationId":"InspectionController_activity","parameters":[{"name":"id","required":true,"in":"path","description":"Inspection ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Activity fetched successfully"}},"summary":"One inspection's activity feed (cursor-paged)","tags":["Inspections"]}},"/api/inspections/{id}/confirm-finalised":{"post":{"operationId":"InspectionController_confirmFinalised","parameters":[{"name":"id","required":true,"in":"path","description":"Inspection ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmInspectionFinalisedDto"}}}},"responses":{"200":{"description":"Finalisation confirmed"}},"summary":"Staff attestation that the inspection was finalised in Inspection Express. Kept beside the imported status — never rewrites it.","tags":["Inspections"]}},"/api/inspections/{id}/areas":{"put":{"operationId":"InspectionController_upsertAreas","parameters":[{"name":"id","required":true,"in":"path","description":"Inspection ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertInspectionAreasDto"}}}},"responses":{"200":{"description":"Areas saved successfully"}},"summary":"Bulk-upsert the areas and items for an inspection","tags":["Inspections"]}},"/api/inspections/{id}/prefill-from/{sourceId}":{"post":{"operationId":"InspectionController_prefillFrom","parameters":[{"name":"id","required":true,"in":"path","description":"Inspection ID to prefill","schema":{"type":"string"}},{"name":"sourceId","required":true,"in":"path","description":"Inspection ID to copy the structure from","schema":{"type":"string"}}],"responses":{"200":{"description":"Inspection prefilled successfully"}},"summary":"Copy the areas/items structure from another inspection for the same property (ratings/notes/photos are never carried over)","tags":["Inspections"]}},"/api/inspections/{id}/report":{"post":{"description":"Renders the areas, ratings and notes to a PDF, files it in the DMS against the inspection and the tenancy, shares it to the tenant portal, and moves the inspection to REPORT_SENT. Only available once the inspection is COMPLETED — a report records what was observed, not what is planned.","operationId":"InspectionController_generateReport","parameters":[{"name":"id","required":true,"in":"path","description":"Inspection ID","schema":{"type":"string"}}],"responses":{"201":{"description":"Condition report generated"}},"summary":"Generate the condition report PDF and share it with the tenant","tags":["Inspections"]}},"/api/ledger/receipts":{"post":{"operationId":"LedgerController_createReceipt","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReceiptDto"}}}},"responses":{"201":{"description":"Receipt recorded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LedgerEntryResultResponseDto"}}}}},"summary":"Record a staff manual rent receipt","tags":["Ledger"]}},"/api/ledger/adjustments":{"post":{"operationId":"LedgerController_createAdjustment","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAdjustmentDto"}}}},"responses":{"201":{"description":"Adjustment recorded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LedgerEntryResultResponseDto"}}}}},"summary":"Record a correction/adjustment entry (append-only — entries can never be edited or deleted)","tags":["Ledger"]}},"/api/ledger/entries":{"get":{"operationId":"LedgerController_listEntries","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"type","required":false,"in":"query","description":"Filter by entry type","schema":{"type":"string","enum":["RENT_CHARGE","RENT_RECEIPT","ADJUSTMENT","CREDIT","FEE","WATER"]}},{"name":"dateFrom","required":false,"in":"query","description":"Only entries effective on/after this date (ISO date)","schema":{"example":"2026-01-01","type":"string"}},{"name":"dateTo","required":false,"in":"query","description":"Only entries effective on/before this date (ISO date)","schema":{"example":"2026-12-31","type":"string"}},{"name":"tenancyId","required":false,"in":"query","description":"Filter to a single tenancy","schema":{"type":"string"}},{"name":"accountId","required":false,"in":"query","description":"Filter to a single ledger account","schema":{"type":"string"}}],"responses":{"200":{"description":"Ledger entries fetched successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RentLedgerEntryResponseDto"}}}}}},"summary":"Org-wide append-only ledger entries feed (filter by account/tenancy/type/date, paginated)","tags":["Ledger"]}},"/api/ledger/receipts/monthly":{"get":{"operationId":"LedgerController_monthlyReceipts","parameters":[],"responses":{"200":{"description":"Monthly receipts fetched"}},"summary":"Rent received by UTC calendar month (dashboard trend; last 6 months)","tags":["Ledger"]}},"/api/ledger/arrears/portfolio-summary":{"get":{"operationId":"LedgerController_getArrearsPortfolioSummary","parameters":[],"responses":{"200":{"description":"Arrears portfolio summary fetched successfully"}},"summary":"Arrears portfolio rollup (BRD §7.3): total $, % in arrears, at termination threshold","tags":["Ledger"]}},"/api/ledger/arrears":{"get":{"operationId":"LedgerController_getArrears","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search tenancy ref, property ref/address/suburb, tenant name","schema":{"type":"string"}},{"name":"bucket","required":false,"in":"query","description":"Ageing bucket by days behind","schema":{"type":"string","enum":["1-7","8-14","15+"]}},{"name":"minDaysBehind","required":false,"in":"query","description":"Only accounts at least this many days behind (1-3650)","schema":{"type":"number"}}],"responses":{"200":{"description":"Arrears fetched successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ArrearsEntryResponseDto"}}}}}},"summary":"Arrears worklist: one page of accounts in arrears, paginated, filtered and sorted in the database","tags":["Ledger"]}},"/api/tenancies/{tenancyId}/ledger":{"get":{"operationId":"TenancyLedgerController_getLedger","parameters":[{"name":"tenancyId","required":true,"in":"path","description":"Tenancy ID","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"type","required":false,"in":"query","description":"Filter by entry type","schema":{"type":"string","enum":["RENT_CHARGE","RENT_RECEIPT","ADJUSTMENT","CREDIT","FEE","WATER"]}},{"name":"dateFrom","required":false,"in":"query","description":"Only entries effective on/after this date (ISO date)","schema":{"example":"2026-01-01","type":"string"}},{"name":"dateTo","required":false,"in":"query","description":"Only entries effective on/before this date (ISO date)","schema":{"example":"2026-12-31","type":"string"}}],"responses":{"200":{"description":"Ledger fetched successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenancyLedgerResponseDto"}}}}},"summary":"Get a tenancy's rent ledger account + paginated entries","tags":["Ledger"]}},"/api/valuations/portfolio-summary":{"get":{"operationId":"ValuationController_portfolioSummary","parameters":[],"responses":{"200":{"description":"Portfolio summary fetched successfully"}},"summary":"Portfolio rollup: under-rented count, weekly upside, revalued-this-month count","tags":["Valuations"]}},"/api/valuations":{"get":{"operationId":"ValuationController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"default":10,"example":10,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (alias of limit; staff grids send this)","schema":{"default":10,"example":25,"type":"number"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field (must be on the endpoint allowlist)","schema":{"example":"createdAt","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Multi-sort as field:dir,field:dir (allowlisted fields only)","schema":{"example":"ref:asc,status:desc","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"colFilters","required":false,"in":"query","description":"AG Grid column filters as a JSON array of { field, filterType, type, ... }. Fields are allowlisted per endpoint.","schema":{"type":"string"}},{"name":"propertyId","required":false,"in":"query","description":"Filter valuation history by property","schema":{"example":"cm123property","type":"string"}}],"responses":{"200":{"description":"Valuations fetched successfully"}},"summary":"Get paginated valuation history, optionally by property","tags":["Valuations"]},"post":{"operationId":"ValuationController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateValuationDto"}}}},"responses":{"201":{"description":"Valuation created successfully"}},"summary":"Create a new valuation for a property","tags":["Valuations"]}},"/api/properties/{id}/valuation":{"get":{"operationId":"PropertyValuationController_findLatest","parameters":[{"name":"id","required":true,"in":"path","description":"Property ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Latest valuation fetched successfully"}},"summary":"Get the latest valuation for a property","tags":["Valuations"]}},"/api/suburb-stats":{"get":{"operationId":"SuburbStatsController_findLatest","parameters":[{"name":"suburb","required":true,"in":"query","description":"Suburb name","schema":{"example":"Parramatta","type":"string"}},{"name":"kind","required":true,"in":"query","description":"Property kind — separate markets","schema":{"example":"house","type":"string","enum":["house","unit"]}},{"name":"state","required":false,"in":"query","description":"State/territory (defaults to NSW)","schema":{"default":"NSW","example":"NSW","type":"string"}}],"responses":{"200":{"description":"Suburb stats fetched successfully"}},"summary":"Get the latest suburb stats for a suburb/property kind","tags":["Suburb Stats"]},"put":{"operationId":"SuburbStatsController_upsertBulk","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertSuburbStatsDto"}}}},"responses":{"200":{"description":"Suburb stats upserted successfully"}},"summary":"Bulk upsert suburb stats rows, keyed on [suburb, state, propertyKind, asOf]","tags":["Suburb Stats"]}},"/api/assistant/conversations":{"get":{"operationId":"AssistantConversationController_list","parameters":[],"responses":{"200":{"description":""}},"summary":"List this staff member’s Assistant chats","tags":["Assistant"]},"post":{"operationId":"AssistantConversationController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAssistantConversationDto"}}}},"responses":{"201":{"description":""}},"summary":"Start a new Assistant chat","tags":["Assistant"]}},"/api/assistant/conversations/{id}":{"get":{"operationId":"AssistantConversationController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Load one Assistant chat and its messages","tags":["Assistant"]},"patch":{"operationId":"AssistantConversationController_patch","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchAssistantConversationDto"}}}},"responses":{"200":{"description":""}},"summary":"Pin, unpin, or rename an Assistant chat","tags":["Assistant"]},"delete":{"operationId":"AssistantConversationController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Remove an Assistant chat from this staff member’s list","tags":["Assistant"]}},"/api/assistant/conversations/{id}/messages":{"post":{"operationId":"AssistantConversationController_append","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppendAssistantMessagesDto"}}}},"responses":{"200":{"description":""}},"summary":"Append finished turn messages to a chat","tags":["Assistant"]}},"/api/assistant/conversations/{id}/export":{"post":{"operationId":"AssistantConversationController_exportCsv","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"summary":"Build a CSV from the last exportable query in this chat","tags":["Assistant"]}},"/api/assistant/conversations/{id}/cancel":{"post":{"operationId":"AssistantConversationController_cancelTurn","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Cancel the in-flight Assistant turn and abandon unfinished exports","tags":["Assistant"]}},"/api/assistant/ready":{"get":{"operationId":"AssistantSettingsController_ready","parameters":[],"responses":{"200":{"description":""}},"summary":"Whether this org can use Assistant right now","tags":["Assistant"]}},"/api/assistant/settings":{"get":{"operationId":"AssistantSettingsController_getSettings","parameters":[],"responses":{"200":{"description":""}},"summary":"Staff Assistant settings for this organisation","tags":["Assistant"]},"patch":{"operationId":"AssistantSettingsController_patchSettings","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchAssistantSettingsDto"}}}},"responses":{"200":{"description":""}},"summary":"Update Staff Assistant settings","tags":["Assistant"]}},"/api/assistant/usage":{"get":{"operationId":"AssistantSettingsController_usage","parameters":[],"responses":{"200":{"description":""}},"summary":"Current-month Assistant token usage","tags":["Assistant"]}},"/api/assistant/lookups":{"get":{"operationId":"AssistantSettingsController_lookups","parameters":[{"name":"take","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Recent Assistant record lookups (audit)","tags":["Assistant"]}},"/api/assistant/exports/{id}/download":{"get":{"operationId":"AssistantSettingsController_downloadExport","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Download an Assistant-generated export","tags":["Assistant"]}},"/api/mcp/connections":{"get":{"operationId":"McpConnectionsController_list","parameters":[],"responses":{"200":{"description":""}},"summary":"Claude connector URL and my connected apps","tags":["Assistant"]}},"/api/mcp/connections/consent-info":{"get":{"operationId":"McpConnectionsController_consentInfo","parameters":[{"name":"client_id","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"What the OAuth consent screen names","tags":["Assistant"]}},"/api/mcp/connections/{clientId}":{"delete":{"operationId":"McpConnectionsController_revoke","parameters":[{"name":"clientId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Revoke one connected app (my tokens only)","tags":["Assistant"]}},"/api/dashboard/ops-signals":{"get":{"operationId":"DashboardController_opsSignals","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardOpsSignalsResponseDto"}}}}},"summary":"Staff chrome badge counts: approvals, urgent repairs, inspections overdue (0 without inspections.read), arrears, under-rented","tags":["Dashboard"]}},"/api/dashboard/overview":{"get":{"operationId":"DashboardController_overview","parameters":[{"name":"managerScope","required":false,"in":"query","description":"Portfolio toggle. `mine` scopes to the session user, `all` to the whole organisation (permission permitting).","schema":{"type":"string","enum":["mine","all"]}},{"name":"managerUserId","required":false,"in":"query","description":"Scope to one property manager. Rejected with 403 when the caller may only see their own portfolio and this is someone else.","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardOverviewResponseDto"}}}}},"summary":"Portfolio snapshot, the three workflow cards, approvals and weekly reporting status","tags":["Dashboard"]}},"/api/dashboard/attention":{"get":{"operationId":"DashboardController_needsAttention","parameters":[{"name":"managerScope","required":false,"in":"query","description":"Portfolio toggle. `mine` scopes to the session user, `all` to the whole organisation (permission permitting).","schema":{"type":"string","enum":["mine","all"]}},{"name":"managerUserId","required":false,"in":"query","description":"Scope to one property manager. Rejected with 403 when the caller may only see their own portfolio and this is someone else.","schema":{"type":"string"}},{"name":"module","required":false,"in":"query","schema":{"type":"string","enum":["maintenance","inspections","rent_reviews","lease_renewals","arrears","approvals","notices"]}},{"name":"kind","required":false,"in":"query","schema":{"type":"string","enum":["action","waiting","data"]}},{"name":"backlog","required":false,"in":"query","description":"Include unresolved work dated before the current month. Off by default; the count is always returned.","schema":{"type":"boolean"}},{"name":"page","required":false,"in":"query","schema":{"default":1,"type":"number"}},{"name":"pageSize","required":false,"in":"query","schema":{"maximum":50,"default":6,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardAttentionResponseDto"}}}}},"summary":"Needs attention: one ranked list across maintenance, inspections, rent reviews, lease renewals, arrears and approvals","tags":["Dashboard"]}},"/api/dashboard/agenda":{"get":{"operationId":"DashboardController_agendaView","parameters":[{"name":"managerScope","required":false,"in":"query","description":"Portfolio toggle. `mine` scopes to the session user, `all` to the whole organisation (permission permitting).","schema":{"type":"string","enum":["mine","all"]}},{"name":"managerUserId","required":false,"in":"query","description":"Scope to one property manager. Rejected with 403 when the caller may only see their own portfolio and this is someone else.","schema":{"type":"string"}},{"name":"window","required":false,"in":"query","schema":{"default":"today","type":"string","enum":["today","week"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardAgendaResponseDto"}}}}},"summary":"Today / next 7 days: recorded appointments with times, and deadlines","tags":["Dashboard"]}},"/api/dashboard/updates":{"get":{"operationId":"DashboardController_recentUpdates","parameters":[{"name":"managerScope","required":false,"in":"query","description":"Portfolio toggle. `mine` scopes to the session user, `all` to the whole organisation (permission permitting).","schema":{"type":"string","enum":["mine","all"]}},{"name":"managerUserId","required":false,"in":"query","description":"Scope to one property manager. Rejected with 403 when the caller may only see their own portfolio and this is someone else.","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"maximum":30,"default":8,"type":"number"}},{"name":"view","required":false,"in":"query","description":"bell: notification feed. Leaves out your own actions and collapses bursts (one PropertyMe sync, one job worked in one sitting) into a single row.","schema":{"type":"string","enum":["bell"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardUpdatesResponseDto"}}}}},"summary":"Recent business events: owner responses, evidence received, finalisations, completed reviews","tags":["Dashboard"]}},"/api/dashboard/trends":{"get":{"operationId":"DashboardController_trends","parameters":[{"name":"managerScope","required":false,"in":"query","description":"Portfolio toggle. `mine` scopes to the session user, `all` to the whole organisation (permission permitting).","schema":{"type":"string","enum":["mine","all"]}},{"name":"managerUserId","required":false,"in":"query","description":"Scope to one property manager. Rejected with 403 when the caller may only see their own portfolio and this is someone else.","schema":{"type":"string"}},{"name":"range","required":false,"in":"query","description":"Chart window","schema":{"default":"90d","type":"string","enum":["7d","30d","90d","6m","12m"]}},{"name":"granularity","required":false,"in":"query","description":"Bucket size. Omit to let the range pick: 7d/30d → day, 90d → week, 6m/12m → month.","schema":{"type":"string","enum":["day","week","month"]}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardTrendsResponseDto"}}}}},"summary":"Rent due vs collected, arrears and occupancy over the selected period — bucketed in the database","tags":["Dashboard"]}},"/api/rent-reviews/workspace/properties/{propertyId}/next-review":{"get":{"operationId":"RentReviewWorkspaceController_propertyNextReview","parameters":[{"name":"propertyId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"The property's last rent increase date and next rent review date, resolved the same way as the workspace (PropertyMe's date unless stale, else 12 months after the last increase), with its source.","tags":["Rent reviews"]}},"/api/rent-reviews/workspace/properties/{propertyId}/last-increase":{"patch":{"operationId":"RentReviewWorkspaceController_setPropertyLastIncrease","parameters":[{"name":"propertyId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPropertyLastIncreaseDto"}}}},"responses":{"200":{"description":""}},"summary":"Set the property last rent increase date. Returns the resolved next review date and its source.","tags":["Rent reviews"]}},"/api/rent-reviews/workspace":{"get":{"operationId":"RentReviewWorkspaceController_workspaceList","parameters":[{"name":"q","required":false,"in":"query","schema":{"type":"string"}},{"name":"kind","required":false,"in":"query","schema":{"type":"string","enum":["RENT_REVIEW","LEASE_RENEWAL"]}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["NEEDS_REVIEW","IN_REVIEW","RECOMMENDATION_READY","AWAITING_OWNER","OWNER_APPROVED","OWNER_DECLINED","NO_INCREASE","ACTION_REQUIRED_IN_PROPERTYME","WAITING_FOR_PROPERTYME","COMPLETED"]}},{"name":"managerUserId","required":false,"in":"query","schema":{"type":"string"}},{"name":"ownerDecision","required":false,"in":"query","schema":{"type":"string","enum":["awaiting","approved","declined","no_increase","none"]}},{"name":"propertyMeState","required":false,"in":"query","schema":{"type":"string","enum":["NOT_APPLICABLE","PENDING","CONFIRMED","SOURCE_CHANGED","INCOMPLETE"]}},{"name":"focus","required":false,"in":"query","schema":{"type":"string","enum":["overdue","due_now","due_soon","date_required","awaiting_owner","waiting_propertyme","lease_renewals","rent_reviews","completed"]}},{"name":"month","required":false,"in":"query","schema":{"example":"2026-09","type":"string"}},{"name":"page","required":false,"in":"query","schema":{"type":"number"}},{"name":"pageSize","required":false,"in":"query","schema":{"type":"number"}},{"name":"showCompleted","required":false,"in":"query","schema":{"type":"boolean"}},{"name":"colFilters","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Rent review and lease renewal work queue. Counts and rows share one filtered set.","tags":["Rent reviews"]}},"/api/rent-reviews/workspace/weekly-report/status":{"get":{"operationId":"RentReviewWorkspaceController_weeklyStatus","parameters":[],"responses":{"200":{"description":""}},"summary":"Weekly summary schedule, recipients, next send, recent sends and configuration warnings.","tags":["Rent reviews"]}},"/api/rent-reviews/workspace/weekly-report/preview":{"get":{"operationId":"RentReviewWorkspaceController_preview","parameters":[{"name":"managerUserId","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Render the weekly summary email without sending it or writing a report. ?managerUserId= renders that manager’s own copy.","tags":["Rent reviews"]}},"/api/rent-reviews/workspace/weekly-report/wording":{"get":{"operationId":"RentReviewWorkspaceController_weeklyWording","parameters":[],"responses":{"200":{"description":""}},"summary":"The editable wording of the weekly summary email (subject, greeting, opening, closing) and the defaults.","tags":["Rent reviews"]},"put":{"operationId":"RentReviewWorkspaceController_saveWeeklyWording","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RentReviewWeeklyWordingDto"}}}},"responses":{"200":{"description":""}},"summary":"Save the weekly summary email wording. Blank fields use the default. Figures and lists stay generated.","tags":["Rent reviews"]}},"/api/rent-reviews/workspace/weekly-report/pdf":{"get":{"operationId":"RentReviewWorkspaceController_pdf","parameters":[{"name":"inline","required":true,"in":"query","schema":{"type":"string"}},{"name":"managerUserId","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"The current weekly PDF, the same file the email attaches. Does not send email. ?inline=1 previews instead of downloading.","tags":["Rent reviews"]}},"/api/rent-reviews/workspace/weekly-report/send":{"post":{"operationId":"RentReviewWorkspaceController_send","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RentReviewWeeklySendDto"}}}},"responses":{"201":{"description":""}},"summary":"Send the weekly summary now to the configured recipients, or a test copy to yourself. Flags a cycle that was already sent unless confirmResend is set.","tags":["Rent reviews"]}},"/api/rent-reviews/workspace/weekly-report/reports/{id}/retry":{"post":{"operationId":"RentReviewWorkspaceController_retry","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"summary":"Re-send one report to the recipients the mail server did not accept. Accepted recipients are not sent again.","tags":["Rent reviews"]}},"/api/rent-reviews/workspace/settings":{"put":{"operationId":"RentReviewWorkspaceController_saveSettings","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RentReviewWeeklySettingsDto"}}}},"responses":{"200":{"description":""}},"summary":"Save the weekly summary switch, send day, Sydney hour and recipients. Turning it on requires all three.","tags":["Rent reviews"]}},"/api/rent-reviews/workspace/items/{id}":{"get":{"operationId":"RentReviewWorkspaceController_detail","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Review detail, recommendation and activity.","tags":["Rent reviews"]}},"/api/rent-reviews/workspace/items/{id}/emails/{kind}/preview":{"post":{"operationId":"RentReviewWorkspaceController_emailPreview","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"kind","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RentReviewEmailFieldsDto"}}}},"responses":{"201":{"description":""}},"summary":"Render the owner proposal or tenant rent increase notice for a review. Sends nothing.","tags":["Rent reviews"]}},"/api/rent-reviews/workspace/items/{id}/emails/{kind}/send":{"post":{"operationId":"RentReviewWorkspaceController_emailSend","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"kind","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RentReviewEmailSendDto"}}}},"responses":{"201":{"description":""}},"summary":"Email the owner proposal or the tenant rent increase notice, file it on the comms record and note it on the review. Does not write to PropertyMe.","tags":["Rent reviews"]}},"/api/rent-reviews/workspace/items/{id}/actions":{"post":{"operationId":"RentReviewWorkspaceController_act","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RentReviewActionDto"}}}},"responses":{"201":{"description":""}},"summary":"Record a staff action. Does not email owners or tenants and does not write to PropertyMe.","tags":["Rent reviews"]}},"/api/integrations/propertyme/sync":{"post":{"description":"Imports up to `limit` (default 10, hard cap 25) lots from PropertyMe into the domain model via ExternalLink upserts — Property/Owner/Ownership/Tenant/Tenancy/Lease/Bond/RentSchedule/RentLedgerAccount (Slice A0), plus contact-enriched owner/tenant details and batch-scoped related data (Slice A1): RentReview, updated Lease dates from agreement history, Inspection, ComplianceItem, and MaintenanceJob (+Supplier stubs). Only `mode=bootstrap` is implemented.","operationId":"PropertyMeSyncController_sync","parameters":[{"name":"mode","required":false,"in":"query","description":"Sync mode. Only \"bootstrap\" is implemented in Slice A0.","schema":{"default":"bootstrap","type":"string","enum":["bootstrap","delta","full"]}},{"name":"limit","required":false,"in":"query","description":"Number of lots to import (default 10, hard cap 25)","schema":{"minimum":1,"maximum":25,"type":"number"}}],"responses":{"200":{"description":"Sync run started/finished"}},"summary":"Manually trigger a PropertyMe bootstrap sync (Slice A1)","tags":["Integrations / PropertyMe"]}},"/api/integrations/propertyme/sync/runs/{id}":{"get":{"operationId":"PropertyMeSyncController_getRun","parameters":[{"name":"id","required":true,"in":"path","description":"Sync run ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Sync run fetched successfully"}},"summary":"Get a PropertyMe sync run by ID","tags":["Integrations / PropertyMe"]}},"/api/integrations/propertyme/partner/oauth/authorize-url":{"post":{"description":"Returns the login.propertyme.com authorisation URL to redirect the operator to. A single-use CSRF state is stored against the organisation and expires in 10 minutes.","operationId":"PropertyMePartnerController_authorizeUrl","parameters":[],"responses":{"201":{"description":"Authorisation URL built"}},"summary":"Build the PropertyMe OAuth consent URL","tags":["Integrations / PropertyMe (Partner API)"]}},"/api/integrations/propertyme/partner/oauth/callback":{"get":{"operationId":"PropertyMePartnerController_callback","parameters":[{"name":"state","required":false,"in":"query","schema":{}},{"name":"code","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"PropertyMe connected"}},"summary":"OAuth redirect target — exchanges the authorisation code for tokens","tags":["Integrations / PropertyMe (Partner API)"]}},"/api/integrations/propertyme/partner/connection":{"get":{"description":"Never returns tokens — only whether the connection is live, which scopes were granted, and when it last refreshed.","operationId":"PropertyMePartnerController_connection","parameters":[],"responses":{"200":{"description":"Connection status"}},"summary":"PropertyMe connection status","tags":["Integrations / PropertyMe (Partner API)"]},"delete":{"description":"Revokes the refresh token at the identity server (best effort) and clears the stored credentials. Synced domain data is left untouched.","operationId":"PropertyMePartnerController_disconnect","parameters":[],"responses":{"200":{"description":"Disconnected"}},"summary":"Disconnect PropertyMe","tags":["Integrations / PropertyMe (Partner API)"]}},"/api/integrations/propertyme/partner/sync":{"post":{"description":"mode=full performs the one-off portfolio bootstrap (every delta cursor restarts at zero); mode=delta resumes from the stored Timestamp watermarks and is what the hourly cron runs. Imports properties, owners, ownerships, tenants, tenancies, leases, bonds, rent schedules, arrears balances, suppliers, maintenance jobs, inspections and compliance-shaped tasks.","operationId":"PropertyMePartnerController_sync","parameters":[{"name":"mode","required":false,"in":"query","description":"Sync mode. \"full\" restarts every delta cursor at zero and pulls the entire portfolio (the one-off bootstrap). \"delta\" resumes from the stored watermarks.","schema":{"default":"delta","type":"string","enum":["full","delta"]}},{"name":"only","required":false,"in":"query","description":"\"inspections\": re-pull only the inspection catalogue for known properties (read-only; no other stage or cursor is touched). Used by the Inspections workspace so staff can refresh inspection data without a portfolio sync.","schema":{"type":"string","enum":["inspections"]}}],"responses":{"201":{"description":"Sync run finished"}},"summary":"Trigger a PropertyMe partner-API sync","tags":["Integrations / PropertyMe (Partner API)"]}},"/api/integrations/propertyme/partner/sync/runs":{"get":{"operationId":"PropertyMePartnerController_runs","parameters":[{"name":"limit","required":false,"in":"query","description":"Maximum number of runs to return (default 20, max 100).","schema":{"minimum":1,"maximum":100,"type":"number"}}],"responses":{"200":{"description":"Sync runs"}},"summary":"List recent PropertyMe sync runs","tags":["Integrations / PropertyMe (Partner API)"]}},"/api/integrations/propertyme/partner/sync/run/{id}":{"get":{"operationId":"PropertyMePartnerController_run","parameters":[{"name":"id","required":true,"in":"path","description":"Sync run ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Sync run"}},"summary":"Get one PropertyMe sync run","tags":["Integrations / PropertyMe (Partner API)"]}},"/api/realtime/updates":{"get":{"operationId":"RealtimeController_updates","parameters":[],"responses":{"200":{"description":""}},"tags":["Realtime"]}}},"info":{"title":"OneAgency API","description":"OneAgency API documentation.\n\n## Authentication\n\nSession-based auth with Bearer token. Sessions: 30 days, auto-refresh on activity. **Headers:** `x-org-id` (required for auth and most routes). For new user registration (e.g. phone OTP verify), send `accountType` in the request body (STAFF, ADMIN, etc.).\n\n### Getting Started\n1. Call `GET /api/organizations` to get an organization ID\n2. Sign up or sign in using one of the methods below\n3. Use `Authorization: Bearer <session-token>` on requests\n\n---\n\n### Email/Password\n\n**POST /api/auth/sign-up/email** — Register\n- Headers: `Content-Type: application/json`, `x-org-id`\n- Request body: `{ \"email\": \"user@example.com\", \"password\": \"securePassword123\", \"name\": \"Jane Doe\" }`\n- Response (200/201): `{ \"token\": \"...\", \"user\": { \"id\", \"email\", \"name\", \"orgId\", \"accountType\", \"onboardingStatus\", ... } }`\n\n**POST /api/auth/sign-in/email** — Login\n- Headers: `Content-Type: application/json`, `x-org-id`\n- Request body: `{ \"email\": \"user@example.com\", \"password\": \"securePassword123\" }`\n- Response (200): `{ \"token\": \"...\", \"user\": { ... } }`\n\n---\n\n### Email OTP (Passwordless)\n\n**POST /api/auth/email-otp/send-verification-otp** — Send OTP\n- Headers: `Content-Type: application/json`, `x-org-id`\n- Request body: `{ \"email\": \"user@example.com\", \"type\": \"sign-in\" }` (`type`: sign-in | email-verification | forget-password)\n- Response (200): Success, OTP sent\n\n**POST /api/auth/sign-in/email-otp** — Sign in with OTP\n- Headers: `Content-Type: application/json`, `x-org-id`\n- Request body: `{ \"email\": \"user@example.com\", \"otp\": \"123456\" }`\n- Response (200): `{ \"token\": \"...\", \"user\": { ... } }`\n\n**POST /api/auth/email-otp/verify-email** — Verify email with OTP (body: email + otp)\n\n---\n\n### Phone/SMS OTP (Passwordless) — primary for mobile\n\n**POST /api/auth/phone-number/send-otp** — Send OTP to phone\n- Headers: `Content-Type: application/json`, `x-org-id`\n- Request body: `{ \"phoneNumber\": \"+61412345678\" }` (E.164). Optional `intent: \"login\"` — if set and user not registered, returns 400 \"User not found with this phone number. Please register first.\"\n- Response (200): Success, OTP sent via SMS\n\n**POST /api/auth/phone-number/verify** — Verify OTP, sign in or register\n- Headers: `Content-Type: application/json`, `x-org-id`\n- Request body:\n  - Required: `{ \"phoneNumber\": \"+61412345678\", \"code\": \"123456\" }`\n  - Optional `intent: \"login\"` — if set and user not registered, returns 400 \"User not found with this phone number. Please register first.\"\n  - For **new users** (recommended): also send `name`, `email`, `accountType` so the created user has correct profile, e.g. `{ \"phoneNumber\": \"+61412345678\", \"code\": \"123456\", \"name\": \"Jane Support\", \"email\": \"jane@example.com\", \"accountType\": \"STAFF\" }`\n- Response (200): `{ \"status\": true, \"token\": \"session-token\", \"user\": { \"id\", \"username\", \"name\", \"email\", \"orgId\", \"phoneNumber\", \"phoneNumberVerified\", \"accountType\", \"onboardingStatus\", ... } }`\n- Error (400): `{ \"message\": \"Invalid code\" }`, `{ \"message\": \"User not found with this phone number. Please register first.\" }` (when intent=login and user not registered), or similar\n\n---\n\n### Session Management\n\n**GET /api/auth/get-session** — Current session and user (headers: `Authorization: Bearer <token>`, `x-org-id`)\n- Response (200): `{ \"user\", \"session\", \"roles\", \"permissions\", \"effectiveScope\", \"participantAccess\", \"staffProfile\" }`\n\n**POST /api/auth/sign-out** — Logout (header: `Authorization: Bearer <token>`)\n- Response (200): Session invalidated\n\n**GET /api/auth/list-sessions** — List active sessions\n\n**POST /api/auth/revoke-session** — Revoke a session (body: session id as required by Better Auth)\n\n---\n\n### JWT (service-to-service)\n\n**GET /api/auth/token** — Short-lived JWT (15 min) from current session (header: `Authorization: Bearer <session-token>`)\n\n**GET /api/auth/jwks** — Public keys for JWT verification\n\n---\n\n### Mobile notes\n- Store token in Keychain (iOS) / Keystore (Android); use `Authorization: Bearer <token>` on API calls\n- Check session on launch with `GET /api/auth/get-session`\n- If session expires (30+ days inactive), use phone or email OTP to sign in again\n","version":"1.0","contact":{}},"tags":[],"servers":[],"components":{"securitySchemes":{"bearer-auth":{"scheme":"bearer","bearerFormat":"JWT","type":"http","name":"Authorization","description":"Enter your Bearer token","in":"header"},"x-org-id":{"type":"apiKey","in":"header","name":"x-org-id","description":"Organization ID (required for most endpoints)"}},"schemas":{"CustomCategoryResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"The id of the custom category","example":"123e4567-e89b-12d3-a456-426614174000"},"orgId":{"type":"string","description":"The organization ID of the custom category","example":"123e4567-e89b-12d3-a456-426614174000"},"code":{"type":"string","description":"The code of the custom category","example":"lead_status"},"name":{"type":"string","description":"The name of the custom category","example":"Lead Status"},"description":{"type":"object","description":"The description of the custom category","example":"Status of lead in the pipeline","nullable":true},"isSystem":{"type":"boolean","description":"Whether this is a system category","example":false},"createdAt":{"format":"date-time","type":"string","description":"The created at timestamp of the custom category","example":"2025-11-19T10:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","description":"The updated at timestamp of the custom category","example":"2025-11-19T10:00:00.000Z"},"icon":{"type":"object","description":"The icon for the custom category","example":"user","nullable":true}},"required":["id","orgId","code","name","description","isSystem","createdAt","updatedAt","icon"]},"PaginationMeta":{"type":"object","properties":{}},"GetAllCustomCategoryDto":{"type":"object","properties":{"success":{"type":"boolean","example":true,"description":"Indicates if the request was successful"},"statusCode":{"type":"number","example":200,"description":"HTTP status code"},"message":{"type":"string","example":"Operation completed successfully","description":"Response message"},"timestamp":{"type":"string","example":"2025-11-19T10:00:00.000Z","description":"Response timestamp"},"data":{"type":"array","items":{"$ref":"#/components/schemas/CustomCategoryResponseDto"}},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"required":["success","statusCode","message","timestamp","data","meta"]},"CreateCustomCategoryDto":{"type":"object","properties":{"code":{"type":"string","description":"The code of the custom category","example":"lead_status"},"name":{"type":"string","description":"The name of the custom category","example":"Lead Status"},"description":{"type":"string","description":"The description of the custom category","example":"Status of lead in the pipeline"},"isSystem":{"type":"boolean","description":"Whether this is a system category (cannot be deleted)","example":false,"default":false},"icon":{"type":"string","description":"The icon for the custom category","example":"user"}},"required":["code","name"]},"CustomCategoryOptionResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"The id of the custom category option","example":"123e4567-e89b-12d3-a456-426614174000"},"categoryId":{"type":"string","description":"The id of the custom category","example":"123e4567-e89b-12d3-a456-426614174000"},"optionName":{"type":"string","description":"The name of the custom category option","example":"Lead"},"optionValue":{"type":"string","description":"The value of the custom category option","example":"lead"},"sortOrder":{"type":"number","description":"The sort order of the custom category option","example":1},"isActive":{"type":"boolean","description":"Whether this option is active","example":true},"colorHex":{"type":"object","description":"The color hex code for this option","example":"#FF5733","nullable":true},"icon":{"type":"object","description":"The icon for this option","example":"user","nullable":true},"createdAt":{"format":"date-time","type":"string","description":"The created at timestamp","example":"2025-11-19T10:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","description":"The updated at timestamp","example":"2025-11-19T10:00:00.000Z"}},"required":["id","categoryId","optionName","optionValue","sortOrder","isActive","colorHex","icon","createdAt","updatedAt"]},"CustomCategoryWithOptionsResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"The id of the custom category","example":"123e4567-e89b-12d3-a456-426614174000"},"orgId":{"type":"string","description":"The organization ID of the custom category","example":"123e4567-e89b-12d3-a456-426614174000"},"code":{"type":"string","description":"The code of the custom category","example":"lead_status"},"name":{"type":"string","description":"The name of the custom category","example":"Lead Status"},"description":{"type":"object","description":"The description of the custom category","example":"Status of lead in the pipeline","nullable":true},"isSystem":{"type":"boolean","description":"Whether this is a system category","example":false},"createdAt":{"format":"date-time","type":"string","description":"The created at timestamp of the custom category","example":"2025-11-19T10:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","description":"The updated at timestamp of the custom category","example":"2025-11-19T10:00:00.000Z"},"icon":{"type":"object","description":"The icon for the custom category","example":"user","nullable":true},"options":{"description":"The options of the custom category","type":"array","items":{"$ref":"#/components/schemas/CustomCategoryOptionResponseDto"}}},"required":["id","orgId","code","name","description","isSystem","createdAt","updatedAt","icon","options"]},"GetSingleCustomCategoryDto":{"type":"object","properties":{"success":{"type":"boolean","example":true,"description":"Indicates if the request was successful"},"statusCode":{"type":"number","example":200,"description":"HTTP status code"},"message":{"type":"string","example":"Operation completed successfully","description":"Response message"},"timestamp":{"type":"string","example":"2025-11-19T10:00:00.000Z","description":"Response timestamp"},"data":{"$ref":"#/components/schemas/CustomCategoryWithOptionsResponseDto"}},"required":["success","statusCode","message","timestamp","data"]},"UpdateCustomCategoryDto":{"type":"object","properties":{"code":{"type":"string","description":"The code of the custom category","example":"lead_status"},"name":{"type":"string","description":"The name of the custom category","example":"Lead Status"},"description":{"type":"string","description":"The description of the custom category","example":"Status of lead in the pipeline"},"isSystem":{"type":"boolean","description":"Whether this is a system category (cannot be deleted)","example":false}}},"CreateCustomCategoryOptionDto":{"type":"object","properties":{"optionName":{"type":"string","description":"The name of the option","example":"Lead"},"optionValue":{"type":"string","description":"The value of the option","example":"lead"},"sortOrder":{"type":"number","description":"The sort order of the option","example":1},"isActive":{"type":"boolean","description":"Whether this option is active","example":true,"default":true},"colorHex":{"type":"string","description":"The color hex code for this option","example":"#FF5733"},"icon":{"type":"string","description":"The icon for this option","example":"user"}},"required":["optionName","optionValue","sortOrder"]},"UpdateCustomCategoryOptionDto":{"type":"object","properties":{"optionName":{"type":"string","description":"The name of the option","example":"Lead"},"optionValue":{"type":"string","description":"The value of the option","example":"lead"},"sortOrder":{"type":"number","description":"The sort order of the option","example":1},"isActive":{"type":"boolean","description":"Whether this option is active","example":true},"colorHex":{"type":"string","description":"The color hex code for this option","example":"#FF5733"},"icon":{"type":"string","description":"The icon for this option","example":"user"}}},"CreateOrganizationDto":{"type":"object","properties":{"name":{"type":"string","description":"Organization name","example":"Acme Corporation"},"slug":{"type":"string","description":"Unique URL-friendly slug","example":"acme-corp","pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"description":{"type":"string","description":"Organization description","example":"A leading tech company"}},"required":["name","slug"]},"UpdateOrganizationDto":{"type":"object","properties":{"name":{"type":"string","description":"Organization name","example":"Acme Corporation"},"description":{"type":"string","description":"Organization description","example":"A leading tech company"},"isActive":{"type":"boolean","description":"Whether the organization is active","example":true}}},"UpdateOrganizationSettingsDto":{"type":"object","properties":{"defaultShiftDuration":{"type":"number","description":"Default shift duration in minutes","example":480},"minShiftDuration":{"type":"number","description":"Minimum shift duration in minutes","example":60},"maxShiftDuration":{"type":"number","description":"Maximum shift duration in minutes","example":720},"defaultBreakDuration":{"type":"number","description":"Default break duration in minutes","example":30},"autoApproveTimesheets":{"type":"boolean","description":"Auto-approve timesheets","example":false},"requireTimesheetApproval":{"type":"boolean","description":"Require timesheet approval","example":true},"defaultPayGroup":{"type":"string","description":"Default pay group identifier"},"timesheetReminderDays":{"type":"number","description":"Timesheet reminder days before due","example":1},"autoActivateParticipants":{"type":"boolean","description":"Auto-activate participants on onboarding","example":false},"companyLegalName":{"type":"string","description":"Company legal name","example":"Sydney Disability Support Pty Ltd"},"companyAbn":{"type":"string","description":"Company ABN (distinct from NDIS claims ABN)"},"signatoryName":{"type":"string","description":"Default employer signatory name"},"signatoryTitle":{"type":"string","description":"Employer signatory title, e.g. \"Operations Manager\""},"signatoryEmail":{"type":"string","description":"Employer signatory email (receives co-signed agreements)"},"signatoryPhone":{"type":"string","description":"Employer signatory contact phone"},"requireNoteBeforeClockOut":{"type":"boolean","description":"Require progress note before staff can clock out","example":false},"ndisRegistrationNumber":{"type":"string","description":"NDIS Provider Registration Number","example":"12345"},"ndisAbn":{"type":"string","description":"Australian Business Number for NDIS claims","example":"12345678901"},"minSupportedAndroidVersion":{"type":"string","description":"Minimum supported Android app version. Users below this are hard-blocked on launch. Empty disables the gate on Android.","example":"4.1.0"},"minSupportedIosVersion":{"type":"string","description":"Minimum supported iOS app version. Users below this are hard-blocked on launch. Empty disables the gate on iOS.","example":"4.1.0"},"androidStoreUrl":{"type":"string","description":"Play Store listing URL. Required for the Android gate to activate.","example":"https://play.google.com/store/apps/details?id=com.cuebites.sds"},"iosStoreUrl":{"type":"string","description":"App Store listing URL. Required for the iOS gate to activate.","example":"https://apps.apple.com/app/id123456789"},"appUpdateMessage":{"type":"string","description":"Custom message shown in the force-update dialog. Falls back to default copy when empty.","example":"This version is no longer supported. Please update to continue."}}},"UploadLimitsResponseDto":{"type":"object","properties":{"inlineMaxBytes":{"type":"number","description":"Largest file size (bytes) the simple single-request upload accepts.","example":5242880},"directPutMaxBytes":{"type":"number","description":"Largest file size (bytes) accepted at all, via presigned direct upload.","example":104857600}},"required":["inlineMaxBytes","directPutMaxBytes"]},"CreateUploadSessionDto":{"type":"object","properties":{"entityType":{"type":"string","description":"The type of entity to link the document to","example":"participant"},"entityId":{"type":"string","description":"The ID of the entity to link the document to","example":"clxyz123456789"},"fileName":{"type":"string","description":"Original file name","example":"passport_scan.pdf"},"contentType":{"type":"string","description":"MIME type of the file","example":"application/pdf"},"sizeBytes":{"type":"number","description":"Size of the file in bytes","example":1024000},"documentTypeId":{"type":"string","description":"ID of the document type (CustomCategoryOption)","example":"clxyz123456789"},"restricted":{"type":"boolean","description":"Whether the document is restricted (requires elevated permissions)","example":false,"default":false},"sharedWithParticipant":{"type":"boolean","description":"Whether the document is shared with the participant","example":false,"default":false},"displayName":{"type":"string","description":"User-friendly display name for the document","example":"John Doe - Passport"},"tags":{"description":"Tags for categorizing the document","example":["identity","verification"],"type":"array","items":{"type":"string"}},"notes":{"type":"string","description":"Notes or description for the document","example":"Scanned copy of passport for identity verification"},"linkRole":{"type":"string","description":"Role of the document link (e.g., primary, evidence, supporting)","example":"primary"}},"required":["entityType","entityId","fileName","contentType","sizeBytes","restricted"]},"InlineUploadInstructions":{"type":"object","properties":{"endpoint":{"type":"string","description":"Endpoint for inline file upload","example":"/dms/upload-sessions/clxyz123/file"},"method":{"type":"string","description":"HTTP method to use","example":"POST"},"contentType":{"type":"string","description":"Content type for the request","example":"multipart/form-data"},"fieldName":{"type":"string","description":"Form field name for the file","example":"file"}},"required":["endpoint","method","contentType","fieldName"]},"DirectPutUploadInstructions":{"type":"object","properties":{"uploadUrl":{"type":"string","description":"Presigned URL for direct upload","example":"https://storage.example.com/bucket/key?signature=..."},"method":{"type":"string","description":"HTTP method to use","example":"PUT"},"headers":{"type":"object","description":"Required headers for the upload request","example":{"Content-Type":"application/pdf"}},"confirmEndpoint":{"type":"string","description":"Endpoint to confirm upload completion","example":"/dms/upload-sessions/clxyz123/confirm-upload"}},"required":["uploadUrl","method","headers","confirmEndpoint"]},"MultipartUploadInstructions":{"type":"object","properties":{"partSizeBytes":{"type":"number","description":"Size of each part in bytes","example":8388608},"totalParts":{"type":"number","description":"Total number of parts","example":5},"partUrlEndpoint":{"type":"string","description":"Endpoint to get presigned URL for each part","example":"/dms/upload-sessions/clxyz123/parts/:partNumber"},"completeEndpoint":{"type":"string","description":"Endpoint to complete the multipart upload","example":"/dms/upload-sessions/clxyz123/complete"}},"required":["partSizeBytes","totalParts","partUrlEndpoint","completeEndpoint"]},"UploadSessionResponseDto":{"type":"object","properties":{"uploadSessionId":{"type":"string","description":"Upload session ID","example":"clxyz123456789"},"documentId":{"type":"string","description":"Document ID (created immediately)","example":"cldoc123456789"},"uploadMode":{"type":"string","description":"Upload mode selected by the backend","enum":["INLINE","DIRECT_PUT","MULTIPART"],"example":"INLINE"},"status":{"type":"string","description":"Current status of the upload session","enum":["INITIATED","UPLOADING","UPLOADED","VERIFYING","AVAILABLE","FAILED","ABORTED","EXPIRED"],"example":"INITIATED"},"inlineInstructions":{"description":"Instructions for inline upload (if mode is INLINE)","allOf":[{"$ref":"#/components/schemas/InlineUploadInstructions"}]},"directPutInstructions":{"description":"Instructions for direct PUT upload (if mode is DIRECT_PUT)","allOf":[{"$ref":"#/components/schemas/DirectPutUploadInstructions"}]},"multipartInstructions":{"description":"Instructions for multipart upload (if mode is MULTIPART)","allOf":[{"$ref":"#/components/schemas/MultipartUploadInstructions"}]},"expiresAt":{"format":"date-time","type":"string","description":"When the upload session expires","example":"2024-01-15T12:00:00.000Z"},"nextAction":{"type":"string","description":"Next action the client should take","example":"upload_file"}},"required":["uploadSessionId","documentId","uploadMode","status","expiresAt","nextAction"]},"UploadSessionStatusResponseDto":{"type":"object","properties":{"uploadSessionId":{"type":"string","description":"Upload session ID","example":"clxyz123456789"},"documentId":{"type":"string","description":"Document ID","example":"cldoc123456789"},"status":{"type":"string","description":"Current status of the upload session","enum":["INITIATED","UPLOADING","UPLOADED","VERIFYING","AVAILABLE","FAILED","ABORTED","EXPIRED"],"example":"INITIATED"},"uploadMode":{"type":"string","description":"Upload mode","enum":["INLINE","DIRECT_PUT","MULTIPART"],"example":"INLINE"},"errorCode":{"type":"string","description":"Error code if status is FAILED","example":"STORAGE_HEAD_MISMATCH"},"errorMessage":{"type":"string","description":"Error message if status is FAILED","example":"File size does not match expected size"},"expiresAt":{"format":"date-time","type":"string","description":"When the upload session expires","example":"2024-01-15T12:00:00.000Z"},"retryable":{"type":"boolean","description":"Whether the session can be retried","example":true},"nextAction":{"type":"string","description":"Next action the client should take","example":"upload_file"}},"required":["uploadSessionId","documentId","status","uploadMode","expiresAt","retryable"]},"DocumentTypeDto":{"type":"object","properties":{"id":{"type":"string","example":"cltype123456789"},"optionName":{"type":"string","example":"ID Proof"},"optionValue":{"type":"string","example":"id_proof"},"colorHex":{"type":"string","example":"#FF5722"},"icon":{"type":"string","example":"document-text"}},"required":["id","optionName","optionValue"]},"UserBriefDto":{"type":"object","properties":{"id":{"type":"string","example":"cluser123456789"},"name":{"type":"string","example":"John Doe"}},"required":["id"]},"DocumentLinkDto":{"type":"object","properties":{"id":{"type":"string","example":"cllink123456789"},"entityType":{"type":"string","example":"participant"},"entityId":{"type":"string","example":"clpart123456789"},"linkRole":{"type":"string","example":"primary"},"createdAt":{"format":"date-time","type":"string","example":"2024-01-15T10:00:00.000Z"},"createdByUser":{"$ref":"#/components/schemas/UserBriefDto"}},"required":["id","entityType","entityId","createdAt"]},"DocumentResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"cldoc123456789"},"orgId":{"type":"string","example":"clorg123456789"},"originalFileName":{"type":"string","example":"passport_scan.pdf"},"displayName":{"type":"string","example":"John Doe - Passport"},"contentType":{"type":"string","example":"application/pdf"},"sizeBytes":{"type":"number","example":1024000},"documentType":{"$ref":"#/components/schemas/DocumentTypeDto"},"tags":{"example":["identity","verification"],"type":"array","items":{"type":"string"}},"notes":{"type":"string","example":"Scanned copy of passport"},"restricted":{"type":"boolean","example":false},"sharedWithParticipant":{"type":"boolean","example":false},"status":{"type":"string","enum":["DRAFT","UPLOADING","AVAILABLE","FAILED","QUARANTINED","ARCHIVED","DELETED"],"example":"AVAILABLE"},"storageProvider":{"type":"string","enum":["SUPABASE_S3","AWS_S3","AZURE_BLOB"],"example":"SUPABASE_S3"},"uploadedAt":{"format":"date-time","type":"string","example":"2024-01-15T10:00:00.000Z"},"createdAt":{"format":"date-time","type":"string","example":"2024-01-15T09:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","example":"2024-01-15T10:00:00.000Z"},"deletedAt":{"format":"date-time","type":"string","example":"2024-01-20T10:00:00.000Z"},"archivedAt":{"format":"date-time","type":"string","example":"2024-06-01T10:00:00.000Z"},"supersededByDocumentId":{"type":"string","example":"cldoc987654321"},"uploadedByUser":{"$ref":"#/components/schemas/UserBriefDto"},"archivedByUser":{"$ref":"#/components/schemas/UserBriefDto"},"documentLinks":{"type":"array","items":{"$ref":"#/components/schemas/DocumentLinkDto"}}},"required":["id","orgId","originalFileName","contentType","sizeBytes","tags","restricted","sharedWithParticipant","status","storageProvider","createdAt","updatedAt","documentLinks"]},"PartUrlResponseDto":{"type":"object","properties":{"partNumber":{"type":"number","description":"Part number (1-indexed)","example":1},"url":{"type":"string","description":"Presigned URL for uploading this part","example":"https://storage.example.com/bucket/key?partNumber=1&signature=..."},"expiresAt":{"format":"date-time","type":"string","description":"When the URL expires","example":"2024-01-15T12:30:00.000Z"},"headers":{"type":"object","description":"Headers to include with the upload request","example":{"Content-Type":"application/pdf"}},"method":{"type":"string","description":"HTTP method to use (defaults to PUT)","example":"PUT"}},"required":["partNumber","url","expiresAt"]},"UploadPartDto":{"type":"object","properties":{"partNumber":{"type":"number","description":"Part number (1-indexed)","example":1},"etag":{"type":"string","description":"ETag returned by the storage provider after uploading the part","example":"\"d41d8cd98f00b204e9800998ecf8427e\""}},"required":["partNumber","etag"]},"CompleteMultipartUploadDto":{"type":"object","properties":{"parts":{"description":"Array of completed parts with their ETags","example":[{"partNumber":1,"etag":"\"abc123\""},{"partNumber":2,"etag":"\"def456\""}],"type":"array","items":{"$ref":"#/components/schemas/UploadPartDto"}}},"required":["parts"]},"UpdateDocumentDto":{"type":"object","properties":{"displayName":{"type":"string","description":"User-friendly display name for the document","example":"John Doe - Updated Passport"},"documentTypeId":{"type":"string","description":"ID of the document type (CustomCategoryOption)","example":"clxyz123456789"},"tags":{"description":"Tags for categorizing the document","example":["signed","contract"],"type":"array","items":{"type":"string"}},"restricted":{"type":"boolean","description":"Whether the document is restricted","example":true},"sharedWithParticipant":{"type":"boolean","description":"Whether the document is shared with the participant","example":false},"notes":{"type":"string","description":"Notes or description for the document","example":"Updated notes for the document"}}},"ArchiveDocumentDto":{"type":"object","properties":{"supersededByDocumentId":{"type":"string","description":"ID of the newer document that supersedes this one (e.g. an updated care plan)","example":"cldoc987654321"}}},"DownloadUrlResponseDto":{"type":"object","properties":{"url":{"type":"string","description":"Presigned download URL","example":"https://storage.example.com/bucket/key?signature=..."},"expiresAt":{"format":"date-time","type":"string","description":"When the URL expires","example":"2024-01-15T12:05:00.000Z"},"headers":{"type":"object","description":"Optional headers to include in the request","example":{}}},"required":["url","expiresAt"]},"AddDocumentLinkDto":{"type":"object","properties":{"entityType":{"type":"string","description":"The type of entity to link the document to","example":"lead"},"entityId":{"type":"string","description":"The ID of the entity to link the document to","example":"cllead123456789"},"linkRole":{"type":"string","description":"Role of the document link (e.g., primary, evidence, supporting)","example":"supporting"}},"required":["entityType","entityId"]},"RoleResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"The id of the role","example":"123e4567-e89b-12d3-a456-426614174000"},"orgId":{"type":"string","description":"The organization ID of the role","example":"123e4567-e89b-12d3-a456-426614174000"},"name":{"type":"string","description":"The name of the role","example":"Admin"},"description":{"type":"object","description":"The description of the role","example":"Administrator role with full access","nullable":true},"code":{"type":"object","description":"Machine code for platform roles","nullable":true},"isSystem":{"type":"boolean","description":"Built-in Administrator — locked, always full access"},"userCount":{"type":"number","description":"Active team members holding this role"},"permissionCount":{"type":"number","description":"Visible permissions ticked on this role"},"totalPermissionCount":{"type":"number","description":"Visible permissions in the catalogue"},"createdAt":{"format":"date-time","type":"string","description":"The created at date of the role","example":"2021-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","description":"The updated at date of the role","example":"2021-01-01T00:00:00.000Z"}},"required":["id","orgId","name","description","code","isSystem","userCount","permissionCount","totalPermissionCount","createdAt","updatedAt"]},"GetAllRoleDto":{"type":"object","properties":{"success":{"type":"boolean","example":true,"description":"Indicates if the request was successful"},"statusCode":{"type":"number","example":200,"description":"HTTP status code"},"message":{"type":"string","example":"Operation completed successfully","description":"Response message"},"timestamp":{"type":"string","example":"2025-11-19T10:00:00.000Z","description":"Response timestamp"},"data":{"type":"array","items":{"$ref":"#/components/schemas/RoleResponseDto"}},"meta":{"type":"object","properties":{"page":{"type":"number","example":1},"limit":{"type":"number","example":10},"total":{"type":"number","example":100},"totalPages":{"type":"number","example":10},"hasNext":{"type":"boolean","example":true},"hasPrev":{"type":"boolean","example":false}}}},"required":["success","statusCode","message","timestamp","data","meta"]},"CreateRoleDto":{"type":"object","properties":{"name":{"type":"string","description":"The name of the role","example":"Admin"},"description":{"type":"string","description":"The description of the role","example":"Administrator role with full access"},"permissionIds":{"description":"Permission ids the new role starts with","type":"array","items":{"type":"string"}},"copyFromRoleId":{"type":"string","description":"Start as a copy of this role (Duplicate)"}},"required":["name"]},"PermissionResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"The id of the permission","example":"123e4567-e89b-12d3-a456-426614174000"},"orgId":{"type":"string","description":"The organization ID of the permission","example":"123e4567-e89b-12d3-a456-426614174000"},"name":{"type":"string","description":"The name of the permission","example":"leads.read"},"description":{"type":"object","description":"The description of the permission","example":"Permission to read leads","nullable":true}},"required":["id","orgId","name","description"]},"RoleWithPermissionsResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"The id of the role","example":"123e4567-e89b-12d3-a456-426614174000"},"orgId":{"type":"string","description":"The organization ID of the role","example":"123e4567-e89b-12d3-a456-426614174000"},"name":{"type":"string","description":"The name of the role","example":"Admin"},"description":{"type":"object","description":"The description of the role","example":"Administrator role with full access","nullable":true},"code":{"type":"object","description":"Machine code for platform roles","nullable":true},"isSystem":{"type":"boolean","description":"Built-in Administrator — locked, always full access"},"userCount":{"type":"number","description":"Active team members holding this role"},"permissionCount":{"type":"number","description":"Visible permissions ticked on this role"},"totalPermissionCount":{"type":"number","description":"Visible permissions in the catalogue"},"createdAt":{"format":"date-time","type":"string","description":"The created at date of the role","example":"2021-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","description":"The updated at date of the role","example":"2021-01-01T00:00:00.000Z"},"permissions":{"description":"The permissions associated with this role","example":[{"id":"123e4567-e89b-12d3-a456-426614174000","orgId":"123e4567-e89b-12d3-a456-426614174000","name":"leads.read","description":"Permission to read leads"}],"type":"array","items":{"$ref":"#/components/schemas/PermissionResponseDto"}}},"required":["id","orgId","name","description","code","isSystem","userCount","permissionCount","totalPermissionCount","createdAt","updatedAt","permissions"]},"GetSingleRoleDto":{"type":"object","properties":{"success":{"type":"boolean","example":true,"description":"Indicates if the request was successful"},"statusCode":{"type":"number","example":200,"description":"HTTP status code"},"message":{"type":"string","example":"Operation completed successfully","description":"Response message"},"timestamp":{"type":"string","example":"2025-11-19T10:00:00.000Z","description":"Response timestamp"},"data":{"$ref":"#/components/schemas/RoleWithPermissionsResponseDto"}},"required":["success","statusCode","message","timestamp","data"]},"UpdateRoleDto":{"type":"object","properties":{"name":{"type":"string","description":"The name of the role","example":"Admin"},"description":{"type":"string","description":"The description of the role","example":"Administrator role with full access"}}},"ManageRolePermissionsDto":{"type":"object","properties":{"permissionIds":{"description":"Array of permission IDs to add or remove from the role","example":["123e4567-e89b-12d3-a456-426614174000","223e4567-e89b-12d3-a456-426614174001"],"type":"array","items":{"type":"string"}},"scope":{"type":"string","description":"Data scope for the permission assignment. Determines what data the permission grants access to.","enum":["ALL","ME","ORG","ASSIGNED","PARTICIPANT_SET"],"example":"ALL","default":"ALL"}},"required":["permissionIds"]},"GetAllPermissionDto":{"type":"object","properties":{"success":{"type":"boolean","example":true,"description":"Indicates if the request was successful"},"statusCode":{"type":"number","example":200,"description":"HTTP status code"},"message":{"type":"string","example":"Operation completed successfully","description":"Response message"},"timestamp":{"type":"string","example":"2025-11-19T10:00:00.000Z","description":"Response timestamp"},"data":{"type":"array","items":{"$ref":"#/components/schemas/PermissionResponseDto"}},"meta":{"type":"object","properties":{"page":{"type":"number","example":1},"limit":{"type":"number","example":10},"total":{"type":"number","example":100},"totalPages":{"type":"number","example":10},"hasNext":{"type":"boolean","example":true},"hasPrev":{"type":"boolean","example":false}}}},"required":["success","statusCode","message","timestamp","data","meta"]},"GetSinglePermissionDto":{"type":"object","properties":{"success":{"type":"boolean","example":true,"description":"Indicates if the request was successful"},"statusCode":{"type":"number","example":200,"description":"HTTP status code"},"message":{"type":"string","example":"Operation completed successfully","description":"Response message"},"timestamp":{"type":"string","example":"2025-11-19T10:00:00.000Z","description":"Response timestamp"},"data":{"$ref":"#/components/schemas/PermissionResponseDto"}},"required":["success","statusCode","message","timestamp","data"]},"AddressSuggestionResponseDto":{"type":"object","properties":{"placeId":{"type":"string","description":"Google Place ID","example":"ChIJN1t_tDeuEmsRUsoyG83frY4"},"description":{"type":"string","description":"Full description of the address suggestion","example":"123 Collins Street, Melbourne VIC 3000, Australia"},"mainText":{"type":"string","description":"Primary text (usually the street address)","example":"123 Collins Street"},"secondaryText":{"type":"string","description":"Secondary text (usually city, state, country)","example":"Melbourne VIC 3000, Australia"}},"required":["placeId","description","mainText","secondaryText"]},"ViewportCoordinateDto":{"type":"object","properties":{"latitude":{"type":"number","description":"Latitude","example":-37.8136},"longitude":{"type":"number","description":"Longitude","example":144.9631}},"required":["latitude","longitude"]},"ViewportDto":{"type":"object","properties":{"low":{"description":"South-west corner","allOf":[{"$ref":"#/components/schemas/ViewportCoordinateDto"}]},"high":{"description":"North-east corner","allOf":[{"$ref":"#/components/schemas/ViewportCoordinateDto"}]}},"required":["low","high"]},"AddressDetailsResponseDto":{"type":"object","properties":{"placeId":{"type":"string","description":"Google Place ID","example":"ChIJN1t_tDeuEmsRUsoyG83frY4"},"formattedAddress":{"type":"string","description":"Full formatted address","example":"123 Collins Street, Melbourne VIC 3000, Australia"},"line1":{"type":"string","description":"Address line 1 (street number and name)","example":"123 Collins Street"},"line2":{"type":"string","description":"Address line 2 (unit, suite, floor, etc.)","example":"Suite 100"},"suburb":{"type":"string","description":"Suburb / locality","example":"Thornbury"},"city":{"type":"string","description":"City / suburb / locality (alias of suburb)","example":"Thornbury"},"lga":{"type":"string","description":"Local Government Area (LGA)","example":"Darebin City"},"state":{"type":"string","description":"State / territory / province","example":"VIC"},"postCode":{"type":"string","description":"Postal / ZIP code","example":"3000"},"country":{"type":"string","description":"Country name","example":"Australia"},"countryCode":{"type":"string","description":"ISO 3166-1 alpha-2 country code","example":"AU"},"latitude":{"type":"number","description":"Latitude coordinate","example":-37.8136},"longitude":{"type":"number","description":"Longitude coordinate","example":144.9631},"timeZone":{"type":"string","description":"IANA timezone identifier","example":"Australia/Melbourne"},"utcOffsetMinutes":{"type":"number","description":"UTC offset in minutes","example":660},"viewport":{"description":"Map viewport bounding box","allOf":[{"$ref":"#/components/schemas/ViewportDto"}]},"iconMaskBaseUri":{"type":"string","description":"Google Maps icon mask base URI","example":"https://maps.gstatic.com/mapfiles/place_api/icons/v2/generic_pinlet"},"iconBackgroundColor":{"type":"string","description":"Icon background color hex code","example":"#7B9EB0"}},"required":["placeId","formattedAddress","line1","suburb","city","state","postCode","country","countryCode","latitude","longitude"]},"TemplateDocumentElement":{"type":"object","properties":{}},"CreateContractTemplateDto":{"type":"object","properties":{"providerTemplateId":{"type":"string","description":"Existing provider template ID to register. If not provided, a new template will be created.","example":"abc123-template-id"},"documentElements":{"description":"Document body elements to author the new template content (eSignatures document_elements). Only used when creating a new template (no providerTemplateId).","type":"array","items":{"$ref":"#/components/schemas/TemplateDocumentElement"}},"title":{"type":"string","description":"Title for the template. Required if creating a new template.","example":"Room Rental Agreement"},"labels":{"description":"Labels/tags for the template","example":["rental","agreement"],"type":"array","items":{"type":"string"}}}},"TemplateCollaboratorResponseDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"editorUrl":{"type":"string"},"status":{"type":"string"},"createdAt":{"format":"date-time","type":"string"}},"required":["id","editorUrl","status","createdAt"]},"ContractTemplateResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Template ID"},"orgId":{"type":"string","description":"Organization ID"},"provider":{"type":"string","description":"Provider name"},"providerTemplateId":{"type":"string","description":"Provider template ID"},"title":{"type":"string","description":"Template title"},"labels":{"description":"Template labels","type":"array","items":{"type":"string"}},"status":{"type":"string","description":"Template status","enum":["ACTIVE","ARCHIVED","DELETED"]},"lastSyncedAt":{"format":"date-time","type":"string","description":"Last sync timestamp"},"createdAt":{"format":"date-time","type":"string","description":"Created timestamp"},"updatedAt":{"format":"date-time","type":"string","description":"Updated timestamp"},"collaborators":{"description":"Collaborators","type":"array","items":{"$ref":"#/components/schemas/TemplateCollaboratorResponseDto"}},"_count":{"type":"object","description":"Contract count"}},"required":["id","orgId","provider","providerTemplateId","title","labels","status","createdAt","updatedAt"]},"UpdateContractTemplateDto":{"type":"object","properties":{"title":{"type":"string","description":"Title for the template","example":"Updated Room Rental Agreement"},"labels":{"description":"Labels/tags for the template","example":["rental","agreement","updated"],"type":"array","items":{"type":"string"}},"status":{"type":"string","description":"Template status","enum":["ACTIVE","ARCHIVED"],"example":"ACTIVE"}}},"SaveConfigDto":{"type":"object","properties":{"provider":{"type":"string","description":"Provider name (defaults to esignatures)","example":"esignatures"},"apiKey":{"type":"string","description":"eSignatures.com API key","example":"your-api-key"},"webhookSecret":{"type":"string","description":"Webhook secret for signature verification","example":"your-webhook-secret"},"baseUrl":{"type":"string","description":"Custom base URL for eSignatures API","example":"https://esignatures.com"},"testMode":{"type":"boolean","description":"When true, all contracts created by this organization are sent to eSignatures.com as test contracts. Signers can sign without OTP verification and documents carry a Demo watermark — use for staging/QA only.","default":false}},"required":["apiKey","webhookSecret"]},"SignerInputDto":{"type":"object","properties":{"name":{"type":"string","description":"Name of the signer","example":"Jane Smith"},"email":{"type":"string","description":"Email address of the signer","example":"jane@example.com"},"mobile":{"type":"string","description":"Mobile phone number of the signer","example":"+1234567890"},"companyName":{"type":"string","description":"Company name of the signer","example":"Acme Corp"},"signingOrder":{"type":"number","description":"Signing order (1 = first, 2 = second, etc.)","example":1},"redirectUrl":{"type":"string","description":"Redirect URL after signing","example":"https://example.com/success"},"redirectUrlDeclined":{"type":"string","description":"Redirect URL if signer declines","example":"https://example.com/declined"},"embeddedSigningEnabled":{"type":"boolean","description":"Enable embedded signing (iframe)","example":true}},"required":["name"]},"PlaceholderFieldDto":{"type":"object","properties":{"apiKey":{"type":"string","description":"API key of the placeholder field","example":"tenant_name"},"value":{"type":"string","description":"Value for the placeholder field","example":"John Doe"}},"required":["apiKey","value"]},"SignerFieldDefaultDto":{"type":"object","properties":{"signerFieldId":{"type":"string","description":"ID of a signer-fillable field defined in the template (eSignatures.com `signer_field_id`).","example":"client_name"},"defaultValue":{"type":"string","description":"Default value used to pre-fill the signer-fillable field. Empty string is allowed to render the input as blank rather than leaving template defaults.","example":"Jane Smith"}},"required":["signerFieldId","defaultValue"]},"CreateContractDto":{"type":"object","properties":{"templateId":{"type":"string","description":"ID of the template to create the contract from","example":"clx1234567890"},"title":{"type":"string","description":"Title for the contract","example":"Rental Agreement - 123 Main St"},"metadata":{"type":"string","description":"Metadata to store with the contract (e.g., internal reference)","example":"lead:abc123"},"isTest":{"type":"boolean","description":"Create as test contract (not legally binding)","example":false},"saveAsDraft":{"type":"boolean","description":"Save as draft without sending to signers","example":false},"signers":{"description":"List of signers for the contract","type":"array","items":{"$ref":"#/components/schemas/SignerInputDto"}},"placeholderFields":{"description":"Placeholder field values to merge into the contract","type":"array","items":{"$ref":"#/components/schemas/PlaceholderFieldDto"}},"signerFields":{"description":"Default values for signer-fillable input fields defined in the template. Pre-fills the input rectangles signers see (e.g. \"Client’s Name\", \"Date of Birth\"). Distinct from placeholderFields, which substitutes {{...}} text in the document body.","type":"array","items":{"$ref":"#/components/schemas/SignerFieldDefaultDto"}}},"required":["templateId","signers"]},"ContractTemplateInfoDto":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"providerTemplateId":{"type":"string"}},"required":["id","title"]},"SignerResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Signer ID"},"contractId":{"type":"string","description":"Contract ID"},"providerSignerId":{"type":"string","description":"Provider signer ID"},"name":{"type":"string","description":"Signer name"},"email":{"type":"string","description":"Signer email"},"mobile":{"type":"string","description":"Signer mobile"},"companyName":{"type":"string","description":"Signer company name"},"signingOrder":{"type":"number","description":"Signing order"},"signPageUrl":{"type":"string","description":"Sign page URL"},"status":{"type":"string","description":"Signer status","enum":["PENDING","NOTIFIED","VIEWED","SIGNED","DECLINED"]},"signerFieldValues":{"type":"object","description":"Signer field values captured during signing"},"lastEventAt":{"format":"date-time","type":"string","description":"Last event timestamp"},"createdAt":{"format":"date-time","type":"string","description":"Created timestamp"},"updatedAt":{"format":"date-time","type":"string","description":"Updated timestamp"}},"required":["id","contractId","providerSignerId","name","signingOrder","status","createdAt","updatedAt"]},"ContractResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Contract ID"},"orgId":{"type":"string","description":"Organization ID"},"templateId":{"type":"string","description":"Template ID"},"providerContractId":{"type":"string","description":"Provider contract ID"},"title":{"type":"string","description":"Contract title"},"metadata":{"type":"string","description":"Contract metadata"},"status":{"type":"string","description":"Contract status","enum":["DRAFT","SENT","VIEWED","SIGNED","DECLINED","WITHDRAWN"]},"isTest":{"type":"boolean","description":"Is test contract"},"isSavedAsDraft":{"type":"boolean","description":"Is saved as draft"},"signedPdfUrl":{"type":"string","description":"Signed PDF URL (expires after 3 days)"},"signedPdfUrlFetchedAt":{"format":"date-time","type":"string","description":"Signed PDF URL fetched timestamp"},"previewPdfUrl":{"type":"string","description":"Preview PDF URL"},"previewPdfUrlFetchedAt":{"format":"date-time","type":"string","description":"Preview PDF URL fetched timestamp"},"lastWebhookAt":{"format":"date-time","type":"string","description":"Last webhook received timestamp"},"lastStatusAt":{"format":"date-time","type":"string","description":"Last status change timestamp"},"createdAt":{"format":"date-time","type":"string","description":"Created timestamp"},"updatedAt":{"format":"date-time","type":"string","description":"Updated timestamp"},"template":{"description":"Template info","allOf":[{"$ref":"#/components/schemas/ContractTemplateInfoDto"}]},"signers":{"description":"Signers","type":"array","items":{"$ref":"#/components/schemas/SignerResponseDto"}}},"required":["id","orgId","templateId","providerContractId","status","isTest","isSavedAsDraft","createdAt","updatedAt"]},"ResendContractResponseDto":{"type":"object","properties":{"message":{"type":"string","description":"Success message","example":"Contract resent successfully"},"contractId":{"type":"string","description":"Contract ID","example":"cmieqoaba0000iymt4fab0345"},"signerId":{"type":"string","description":"Signer ID","example":"clxsigner123"}},"required":["message","contractId","signerId"]},"NoteLinkResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"The id of the note link","example":"123e4567-e89b-12d3-a456-426614174000"},"noteId":{"type":"string","description":"The note ID","example":"123e4567-e89b-12d3-a456-426614174000"},"linkedEntityType":{"type":"string","description":"The linked entity type","example":"LEAD","enum":["LEAD"]},"linkedEntityId":{"type":"string","description":"The linked entity ID","example":"123e4567-e89b-12d3-a456-426614174000"},"isPrimaryFlag":{"type":"boolean","description":"Whether this is the primary context","example":true},"pinnedInContext":{"type":"boolean","description":"Whether the note is pinned in this specific context","example":false},"createdAt":{"format":"date-time","type":"string","description":"The created at timestamp","example":"2025-11-19T10:00:00.000Z"}},"required":["id","noteId","linkedEntityType","linkedEntityId","isPrimaryFlag","pinnedInContext","createdAt"]},"UserBriefResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"User ID","example":"123e4567-e89b-12d3-a456-426614174000"},"name":{"type":"string","description":"User name","example":"John Doe"}},"required":["id","name"]},"NoteResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"The id of the note","example":"123e4567-e89b-12d3-a456-426614174000"},"orgId":{"type":"string","description":"The organization ID of the note","example":"123e4567-e89b-12d3-a456-426614174000"},"createdByUserId":{"type":"object","description":"The ID of the user who created the note","example":"123e4567-e89b-12d3-a456-426614174000","nullable":true},"updatedByUserId":{"type":"object","description":"The ID of the user who last updated the note","example":"123e4567-e89b-12d3-a456-426614174000","nullable":true},"title":{"type":"object","description":"The title of the note","example":"Customer inquiry about maintenance","nullable":true},"bodyText":{"type":"object","description":"The body text of the note (plain text)","example":"Customer called regarding maintenance issue in room 101","nullable":true},"bodyRich":{"type":"object","description":"The rich text body of the note (HTML/JSON)","example":{"content":"<p>Customer called regarding maintenance issue</p>"},"nullable":true},"internalOnlyFlag":{"type":"boolean","description":"Whether this note is internal only","example":false},"clientVisibleFlag":{"type":"boolean","description":"Whether this note is visible to clients","example":true},"pinnedFlag":{"type":"boolean","description":"Whether this note is pinned (globally)","example":false},"noteTypeOption":{"description":"The note type option of the note","example":{"id":"123e4567-e89b-12d3-a456-426614174000","categoryId":"123e4567-e89b-12d3-a456-426614174000","optionName":"General","optionValue":"general"},"allOf":[{"$ref":"#/components/schemas/CustomCategoryOptionResponseDto"}]},"sourceOption":{"description":"The source option of the note","example":{"id":"123e4567-e89b-12d3-a456-426614174000","categoryId":"123e4567-e89b-12d3-a456-426614174000","optionName":"Manual","optionValue":"manual"},"allOf":[{"$ref":"#/components/schemas/CustomCategoryOptionResponseDto"}]},"noteLinks":{"type":"array","items":{"description":"The links associated with this note","type":"array","items":{"$ref":"#/components/schemas/NoteLinkResponseDto"}}},"createdByUser":{"description":"The user who created the note","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/UserBriefResponseDto"}]},"updatedByUser":{"description":"The user who last updated the note","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/UserBriefResponseDto"}]},"createdAt":{"format":"date-time","type":"string","description":"The created at timestamp of the note","example":"2025-11-19T10:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","description":"The updated at timestamp of the note","example":"2025-11-19T10:00:00.000Z"},"deletedAt":{"type":"object","description":"The deleted at timestamp of the note","example":"2025-11-19T10:00:00.000Z","nullable":true}},"required":["id","orgId","createdByUserId","title","bodyText","bodyRich","internalOnlyFlag","clientVisibleFlag","pinnedFlag","noteTypeOption","sourceOption","noteLinks","createdAt","updatedAt","deletedAt"]},"GetAllNoteDto":{"type":"object","properties":{"success":{"type":"boolean","example":true,"description":"Indicates if the request was successful"},"statusCode":{"type":"number","example":200,"description":"HTTP status code"},"message":{"type":"string","example":"Operation completed successfully","description":"Response message"},"timestamp":{"type":"string","example":"2025-11-19T10:00:00.000Z","description":"Response timestamp"},"data":{"type":"array","items":{"$ref":"#/components/schemas/NoteResponseDto"}},"meta":{"type":"object","properties":{"page":{"type":"number","example":1},"limit":{"type":"number","example":10},"total":{"type":"number","example":100},"totalPages":{"type":"number","example":10},"hasNext":{"type":"boolean","example":true},"hasPrev":{"type":"boolean","example":false}}}},"required":["success","statusCode","message","timestamp","data","meta"]},"CreateNoteLinkDto":{"type":"object","properties":{"linkedEntityType":{"type":"string","description":"The type of entity to link to","example":"LEAD","enum":["LEAD","PARTICIPANT","PARTNER","STAFF","PROVIDER"]},"linkedEntityId":{"type":"string","description":"The ID of the entity to link to","example":"123e4567-e89b-12d3-a456-426614174000"},"isPrimaryFlag":{"type":"boolean","description":"Whether this is the primary link (main context for the note)","example":false,"default":false}},"required":["linkedEntityType","linkedEntityId"]},"CreateNoteDto":{"type":"object","properties":{"noteTypeOptionId":{"type":"string","description":"The note type option ID. (General/Site/Finance/Housekeeping/Follow-up)","example":"cmieqoaba0000iymt4fab0345"},"title":{"type":"string","description":"The title of the note","example":"Customer inquiry about maintenance"},"bodyText":{"type":"string","description":"The body text of the note (plain text). Auto-derived from bodyRich if not provided.","example":"Customer called regarding maintenance issue in room 101"},"bodyRich":{"type":"string","description":"The rich text body of the note (HTML string)","example":"<p>Customer called regarding maintenance issue</p>"},"internalOnlyFlag":{"type":"boolean","description":"Whether this note is internal only (never shown in portal)","example":false,"default":false},"clientVisibleFlag":{"type":"boolean","description":"Whether this note is visible to clients (can appear in guest portal)","example":true,"default":false},"pinnedFlag":{"type":"boolean","description":"Whether this note is pinned globally (always show at top everywhere)","example":false,"default":false},"sourceOptionId":{"type":"string","description":"The source option ID. (Manual/System/Imported)","example":"cmieqoaba0000iymt4fab0345"},"links":{"description":"Array of entity links for this note (e.g., link to a lead). At least one link is required.","example":[{"linkedEntityType":"LEAD","linkedEntityId":"123e4567-e89b-12d3-a456-426614174000","isPrimaryFlag":true}],"type":"array","items":{"$ref":"#/components/schemas/CreateNoteLinkDto"}}},"required":["noteTypeOptionId","sourceOptionId","links"]},"CreateNoteResponseDto":{"type":"object","properties":{"note":{"description":"The created note","allOf":[{"$ref":"#/components/schemas/NoteResponseDto"}]}},"required":["note"]},"GetSingleNoteDto":{"type":"object","properties":{"success":{"type":"boolean","example":true,"description":"Indicates if the request was successful"},"statusCode":{"type":"number","example":200,"description":"HTTP status code"},"message":{"type":"string","example":"Operation completed successfully","description":"Response message"},"timestamp":{"type":"string","example":"2025-11-19T10:00:00.000Z","description":"Response timestamp"},"data":{"$ref":"#/components/schemas/NoteResponseDto"}},"required":["success","statusCode","message","timestamp","data"]},"UpdateNoteDto":{"type":"object","properties":{"noteTypeOptionId":{"type":"string","description":"The note type option ID. (General/Site/Finance/Housekeeping/Follow-up)","example":"cmieqoaba0000iymt4fab0345"},"title":{"type":"string","description":"The title of the note","example":"Customer inquiry about maintenance"},"bodyText":{"type":"string","description":"The body text of the note (plain text)","example":"Customer called regarding maintenance issue in room 101"},"bodyRich":{"type":"string","description":"The rich text body of the note (HTML string)","example":"<p>Customer called regarding maintenance issue</p>"},"internalOnlyFlag":{"type":"boolean","description":"Whether this note is internal only (never shown in portal)","example":false},"clientVisibleFlag":{"type":"boolean","description":"Whether this note is visible to clients (can appear in guest portal)","example":true},"pinnedFlag":{"type":"boolean","description":"Whether this note is pinned (always show at top for that context)","example":false},"sourceOptionId":{"type":"string","description":"The source option ID. (Manual/System/Imported)","example":"cmieqoaba0000iymt4fab0345"}}},"AddNoteLinksDto":{"type":"object","properties":{"links":{"description":"Array of entity links to add to the note","example":[{"linkedEntityType":"LEAD","linkedEntityId":"123e4567-e89b-12d3-a456-426614174000","isPrimaryFlag":false}],"type":"array","items":{"$ref":"#/components/schemas/CreateNoteLinkDto"}}},"required":["links"]},"TogglePinInContextDto":{"type":"object","properties":{"pinnedInContext":{"type":"boolean","description":"Whether the note should be pinned in this context","example":true}},"required":["pinnedInContext"]},"CreateEntityNoteDto":{"type":"object","properties":{"noteTypeOptionId":{"type":"string","description":"The note type option ID. (General/Site/Finance/Housekeeping/Follow-up)","example":"cmieqoaba0000iymt4fab0345"},"title":{"type":"string","description":"The title of the note","example":"Customer inquiry about maintenance"},"bodyText":{"type":"string","description":"The body text of the note (plain text). Auto-derived from bodyRich if not provided.","example":"Customer called regarding maintenance issue in room 101"},"bodyRich":{"type":"string","description":"The rich text body of the note (HTML string)","example":"<p>Customer called regarding maintenance issue</p>"},"internalOnlyFlag":{"type":"boolean","description":"Whether this note is internal only (never shown in portal)","example":false,"default":false},"clientVisibleFlag":{"type":"boolean","description":"Whether this note is visible to clients (can appear in guest portal)","example":true,"default":false},"pinnedFlag":{"type":"boolean","description":"Whether this note is pinned globally (always show at top everywhere)","example":false,"default":false},"sourceOptionId":{"type":"string","description":"The source option ID. (Manual/System/Imported)","example":"cmieqoaba0000iymt4fab0345"}},"required":["noteTypeOptionId","sourceOptionId"]},"EntityInfoDto":{"type":"object","properties":{"type":{"type":"string","description":"The entity type","example":"LEAD","enum":["LEAD"]},"id":{"type":"string","description":"The entity ID","example":"123e4567-e89b-12d3-a456-426614174000"}},"required":["type","id"]},"NoteWithContextResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"The id of the note","example":"123e4567-e89b-12d3-a456-426614174000"},"orgId":{"type":"string","description":"The organization ID of the note","example":"123e4567-e89b-12d3-a456-426614174000"},"createdByUserId":{"type":"object","description":"The ID of the user who created the note","example":"123e4567-e89b-12d3-a456-426614174000","nullable":true},"updatedByUserId":{"type":"object","description":"The ID of the user who last updated the note","example":"123e4567-e89b-12d3-a456-426614174000","nullable":true},"title":{"type":"object","description":"The title of the note","example":"Customer inquiry about maintenance","nullable":true},"bodyText":{"type":"object","description":"The body text of the note (plain text)","example":"Customer called regarding maintenance issue in room 101","nullable":true},"bodyRich":{"type":"object","description":"The rich text body of the note (HTML/JSON)","example":{"content":"<p>Customer called regarding maintenance issue</p>"},"nullable":true},"internalOnlyFlag":{"type":"boolean","description":"Whether this note is internal only","example":false},"clientVisibleFlag":{"type":"boolean","description":"Whether this note is visible to clients","example":true},"pinnedFlag":{"type":"boolean","description":"Whether this note is pinned (globally)","example":false},"noteTypeOption":{"description":"The note type option of the note","example":{"id":"123e4567-e89b-12d3-a456-426614174000","categoryId":"123e4567-e89b-12d3-a456-426614174000","optionName":"General","optionValue":"general"},"allOf":[{"$ref":"#/components/schemas/CustomCategoryOptionResponseDto"}]},"sourceOption":{"description":"The source option of the note","example":{"id":"123e4567-e89b-12d3-a456-426614174000","categoryId":"123e4567-e89b-12d3-a456-426614174000","optionName":"Manual","optionValue":"manual"},"allOf":[{"$ref":"#/components/schemas/CustomCategoryOptionResponseDto"}]},"noteLinks":{"type":"array","items":{"description":"The links associated with this note","type":"array","items":{"$ref":"#/components/schemas/NoteLinkResponseDto"}}},"createdByUser":{"description":"The user who created the note","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/UserBriefResponseDto"}]},"updatedByUser":{"description":"The user who last updated the note","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/UserBriefResponseDto"}]},"createdAt":{"format":"date-time","type":"string","description":"The created at timestamp of the note","example":"2025-11-19T10:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","description":"The updated at timestamp of the note","example":"2025-11-19T10:00:00.000Z"},"deletedAt":{"type":"object","description":"The deleted at timestamp of the note","example":"2025-11-19T10:00:00.000Z","nullable":true},"pinnedInContext":{"type":"boolean","description":"Whether the note is pinned in this specific context","example":true}},"required":["id","orgId","createdByUserId","title","bodyText","bodyRich","internalOnlyFlag","clientVisibleFlag","pinnedFlag","noteTypeOption","sourceOption","noteLinks","createdAt","updatedAt","deletedAt","pinnedInContext"]},"EntityNotesResponseDto":{"type":"object","properties":{"entity":{"description":"The entity information","allOf":[{"$ref":"#/components/schemas/EntityInfoDto"}]},"notes":{"description":"The notes associated with this entity","type":"array","items":{"$ref":"#/components/schemas/NoteWithContextResponseDto"}},"pagination":{"type":"object","description":"Pagination metadata","properties":{"page":{"type":"number","example":1},"limit":{"type":"number","example":20},"total":{"type":"number","example":45},"totalPages":{"type":"number","example":3},"hasNext":{"type":"boolean","example":true},"hasPrev":{"type":"boolean","example":false}}}},"required":["entity","notes","pagination"]},"NoteTemplateQuestionDto":{"type":"object","properties":{"id":{"type":"string","description":"Unique question id within the template (e.g. q1, q2)","example":"q1"},"text":{"type":"string","description":"Question text / label","example":"What tasks and events took place during your shift today?"},"inputType":{"type":"string","description":"Input type for the answer","enum":["TEXT","TEXTAREA","NUMBER","SMILE_RATING","DATE","DATETIME"],"example":"TEXTAREA"},"required":{"type":"boolean","description":"Whether the question is required","example":false,"default":false},"options":{"description":"Options for select/rating types (e.g. scale 1-5)","example":[1,2,3,4,5],"type":"array","items":{"type":"string"}}},"required":["id","text","inputType"]},"CreateNoteTemplateDto":{"type":"object","properties":{"name":{"type":"string","description":"The name of the template","example":"Standard Shift Note"},"description":{"type":"string","description":"Description of the template","example":"Standard template for shift progress notes"},"noteType":{"type":"string","description":"The note type this template is for","enum":["SHIFT","SOAP","GENERAL"],"example":"SHIFT"},"scope":{"type":"string","description":"The scope of the template","enum":["SYSTEM","ORG","PARTICIPANT"],"example":"ORG","default":"ORG"},"participantId":{"type":"string","description":"The participant ID if scope is PARTICIPANT","example":"cmieqoaba0000iymt4fab0345"},"isActive":{"type":"boolean","description":"Whether the template is active","example":true,"default":true},"questionsSchema":{"description":"Questions schema (form-driven template)","example":[{"id":"q1","text":"What tasks took place?","inputType":"TEXTAREA","required":true},{"id":"q2","text":"Blood Pressure","inputType":"NUMBER","required":false}],"type":"array","items":{"$ref":"#/components/schemas/NoteTemplateQuestionDto"}}},"required":["name","noteType","questionsSchema"]},"ParticipantBriefResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Participant ID","example":"cmieqoaba0000iymt4fab0345"},"fullLegalName":{"type":"string","description":"Full legal name","example":"John Smith"},"preferredName":{"type":"object","description":"Preferred name","example":"Johnny","nullable":true},"ndisNumber":{"type":"string","description":"NDIS number","example":"430123456"}},"required":["id","fullLegalName","ndisNumber"]},"NoteTemplateQuestionResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Unique question id","example":"q1"},"text":{"type":"string","description":"Question text / label","example":"What tasks took place?"},"inputType":{"type":"string","description":"Input type","example":"TEXTAREA"},"required":{"type":"boolean","description":"Whether the question is required","example":false},"options":{"description":"Options for select/rating types","example":[1,2,3,4,5],"type":"array","items":{"type":"string"}}},"required":["id","text","inputType"]},"NoteTemplateVersionResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"The version ID","example":"cmieqoaba0000iymt4fab0345"},"templateId":{"type":"string","description":"The template ID","example":"cmieqoaba0000iymt4fab0345"},"version":{"type":"number","description":"The version number","example":1},"questionsSchema":{"description":"Questions schema (form-driven template)","example":[{"id":"q1","text":"What tasks took place?","inputType":"TEXTAREA","required":true},{"id":"q2","text":"Blood Pressure","inputType":"NUMBER","required":false}],"type":"array","items":{"$ref":"#/components/schemas/NoteTemplateQuestionResponseDto"}},"createdByUserId":{"type":"object","description":"Who created this version","example":"cmieqoaba0000iymt4fab0345","nullable":true},"createdByUser":{"description":"The user who created this version","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/UserBriefResponseDto"}]},"createdAt":{"format":"date-time","type":"string","description":"When this version was created","example":"2024-01-15T09:00:00.000Z"}},"required":["id","templateId","version","questionsSchema","createdAt"]},"NoteTemplateResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"The template ID","example":"cmieqoaba0000iymt4fab0345"},"orgId":{"type":"string","description":"The organization ID","example":"cmieqoaba0000iymt4fab0345"},"name":{"type":"string","description":"The template name","example":"Standard Shift Note"},"description":{"type":"object","description":"The template description","example":"Standard template for shift progress notes","nullable":true},"noteType":{"type":"string","description":"The note type this template is for","enum":["SHIFT","SOAP","GENERAL"],"example":"SHIFT"},"scope":{"type":"string","description":"The scope of the template","enum":["SYSTEM","ORG","PARTICIPANT"],"example":"ORG"},"participantId":{"type":"object","description":"The participant ID (if participant-specific)","example":"cmieqoaba0000iymt4fab0345","nullable":true},"participant":{"description":"The participant (if participant-specific)","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/ParticipantBriefResponseDto"}]},"isActive":{"type":"boolean","description":"Whether the template is active","example":true},"createdByUserId":{"type":"object","description":"Who created the template","example":"cmieqoaba0000iymt4fab0345","nullable":true},"createdByUser":{"description":"The user who created the template","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/UserBriefResponseDto"}]},"createdAt":{"format":"date-time","type":"string","description":"When the template was created","example":"2024-01-15T09:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","description":"When the template was last updated","example":"2024-01-15T09:00:00.000Z"},"versions":{"type":"array","items":{"description":"The versions of this template","required":false,"type":"array","items":{"$ref":"#/components/schemas/NoteTemplateVersionResponseDto"}}}},"required":["id","orgId","name","noteType","scope","isActive","createdAt","updatedAt","versions"]},"AssignTemplateDto":{"type":"object","properties":{"noteType":{"type":"string","description":"The note type for this assignment","enum":["SHIFT","SOAP","GENERAL"],"example":"SHIFT"},"templateId":{"type":"string","description":"The template ID to assign","example":"cmieqoaba0000iymt4fab0345"},"priority":{"type":"number","description":"Priority of this assignment (higher takes precedence). Default: 0","example":10,"default":0},"effectiveFrom":{"type":"string","description":"When this assignment becomes effective (ISO 8601)","example":"2024-01-01T00:00:00.000Z"},"effectiveTo":{"type":"string","description":"When this assignment expires (ISO 8601)","example":"2024-12-31T23:59:59.000Z"},"isActive":{"type":"boolean","description":"Whether this assignment is active","example":true,"default":true}},"required":["noteType","templateId"]},"NoteTemplateAssignmentResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"The assignment ID","example":"cmieqoaba0000iymt4fab0345"},"orgId":{"type":"string","description":"The organization ID","example":"cmieqoaba0000iymt4fab0345"},"participantId":{"type":"object","description":"The participant ID (null for org-wide)","example":"cmieqoaba0000iymt4fab0345","nullable":true},"participant":{"description":"The participant (null for org-wide)","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/ParticipantBriefResponseDto"}]},"noteType":{"type":"string","description":"The note type for this assignment","enum":["SHIFT","SOAP","GENERAL"],"example":"SHIFT"},"templateId":{"type":"string","description":"The template ID","example":"cmieqoaba0000iymt4fab0345"},"template":{"description":"The template","allOf":[{"$ref":"#/components/schemas/NoteTemplateResponseDto"}]},"priority":{"type":"number","description":"Priority (higher takes precedence)","example":0},"effectiveFrom":{"type":"object","description":"When this assignment becomes effective","example":"2024-01-01T00:00:00.000Z","nullable":true},"effectiveTo":{"type":"object","description":"When this assignment expires","example":"2024-12-31T23:59:59.000Z","nullable":true},"isActive":{"type":"boolean","description":"Whether this assignment is active","example":true},"createdAt":{"format":"date-time","type":"string","description":"When the assignment was created","example":"2024-01-15T09:00:00.000Z"}},"required":["id","orgId","noteType","templateId","priority","isActive","createdAt"]},"CreateTemplateVersionDto":{"type":"object","properties":{"questionsSchema":{"description":"Questions schema (form-driven template)","example":[{"id":"q1","text":"What tasks took place?","inputType":"TEXTAREA","required":true},{"id":"q2","text":"Blood Pressure","inputType":"NUMBER","required":false}],"type":"array","items":{"$ref":"#/components/schemas/NoteTemplateQuestionDto"}}},"required":["questionsSchema"]},"CreateTeamMemberDto":{"type":"object","properties":{"name":{"type":"string","example":"Jane Citizen"},"email":{"type":"string","example":"jane@agency.com.au"},"password":{"type":"string","description":"Their sign-in password (8+ characters)"},"roleId":{"type":"string","description":"The staff role they start with"}},"required":["name","email","password","roleId"]},"SetMemberPasswordDto":{"type":"object","properties":{"password":{"type":"string","description":"The new password (8+ characters)"}},"required":["password"]},"SetUserRoleDto":{"type":"object","properties":{"roleId":{"type":"string","description":"The staff role this user should hold"}},"required":["roleId"]},"UpdateMyUserDto":{"type":"object","properties":{"name":{"type":"string","description":"Display name","example":"Jordan Lee"},"image":{"type":"string","description":"Direct profile image URL (typically set via avatarDocumentId instead)","example":"https://example.com/avatar.jpg"},"avatarDocumentId":{"type":"string","description":"Avatar document ID from DMS — resolves to image URL and propagates to linked staff/participant profile","example":"cmieqoaba0000iymt4fab0345"}}},"UserWithRoleResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"The id of the user","example":"123e4567-e89b-12d3-a456-426614174000"},"orgId":{"type":"string","description":"The organization ID of the user","example":"123e4567-e89b-12d3-a456-426614174000"},"username":{"type":"object","description":"The username of the user","example":"johndoe","nullable":true},"name":{"type":"object","description":"The name of the user","example":"John Doe","nullable":true},"email":{"type":"string","description":"The email of the user","example":"john@example.com"},"emailVerified":{"type":"boolean","description":"Email verification status","example":true},"image":{"type":"object","description":"User profile image","example":"https://example.com/image.jpg","nullable":true},"createdAt":{"format":"date-time","type":"string","description":"User creation date","example":"2024-01-01T00:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","description":"User last update date","example":"2024-01-01T00:00:00.000Z"},"accountType":{"type":"string","description":"Account type of the user","enum":["ADMIN","STAFF","PARTICIPANT","SUPPORT_COORDINATOR","GUARDIAN","PARTNER","OWNER","TENANT"],"example":"STAFF"},"onboardingStatus":{"type":"string","description":"Onboarding status of the user","enum":["PENDING","ACTIVE","SUSPENDED"],"example":"PENDING"},"phoneNumber":{"type":"object","description":"Phone number (if registered via phone OTP)","example":"+61410100101","nullable":true},"phoneNumberVerified":{"type":"boolean","description":"Whether the phone number is verified","example":false},"lastSignInAt":{"type":"object","description":"Last successful sign-in (null = never signed in)","nullable":true},"roles":{"description":"The roles associated with this user","example":[{"id":"123e4567-e89b-12d3-a456-426614174000","orgId":"123e4567-e89b-12d3-a456-426614174000","name":"Admin","description":"Administrator role with full access"}],"type":"array","items":{"$ref":"#/components/schemas/RoleResponseDto"}}},"required":["id","orgId","username","name","email","emailVerified","image","createdAt","updatedAt","accountType","onboardingStatus","phoneNumber","phoneNumberVerified","lastSignInAt","roles"]},"GetAllUserDto":{"type":"object","properties":{"success":{"type":"boolean","example":true,"description":"Indicates if the request was successful"},"statusCode":{"type":"number","example":200,"description":"HTTP status code"},"message":{"type":"string","example":"Operation completed successfully","description":"Response message"},"timestamp":{"type":"string","example":"2025-11-19T10:00:00.000Z","description":"Response timestamp"},"data":{"type":"array","items":{"$ref":"#/components/schemas/UserWithRoleResponseDto"}},"meta":{"type":"object","properties":{"page":{"type":"number","example":1},"limit":{"type":"number","example":10},"total":{"type":"number","example":100},"totalPages":{"type":"number","example":10},"hasNext":{"type":"boolean","example":true},"hasPrev":{"type":"boolean","example":false}}}},"required":["success","statusCode","message","timestamp","data","meta"]},"GetSingleUserDto":{"type":"object","properties":{"success":{"type":"boolean","example":true,"description":"Indicates if the request was successful"},"statusCode":{"type":"number","example":200,"description":"HTTP status code"},"message":{"type":"string","example":"Operation completed successfully","description":"Response message"},"timestamp":{"type":"string","example":"2025-11-19T10:00:00.000Z","description":"Response timestamp"},"data":{"$ref":"#/components/schemas/UserWithRoleResponseDto"}},"required":["success","statusCode","message","timestamp","data"]},"InviteUserDto":{"type":"object","properties":{"name":{"type":"string","example":"Jordan Lee"},"email":{"type":"string","example":"jordan@example.com"},"accountType":{"type":"string","enum":["STAFF","OWNER","TENANT"],"example":"STAFF"},"ownerId":{"type":"string","description":"Required when inviting an owner — links Owner.userId."},"tenantId":{"type":"string","description":"Required when inviting a tenant — links Tenant.userId."},"roleId":{"type":"string","description":"Staff invites: the role they start with. Defaults to the Staff role."}},"required":["name","email","accountType"]},"CreateUserDto":{"type":"object","properties":{"name":{"type":"string","description":"The name of the user","example":"John Doe"},"email":{"type":"string","description":"The email of the user","example":"john@example.com"},"password":{"type":"string","description":"The password for the user account","example":"SecurePassword123!","minLength":8},"username":{"type":"string","description":"The username of the user","example":"johndoe"},"image":{"type":"string","description":"User profile image URL","example":"https://example.com/image.jpg"},"accountType":{"type":"string","description":"Account type for the user. Determines default role assignment.","enum":["ADMIN","STAFF","PARTICIPANT","SUPPORT_COORDINATOR","GUARDIAN","PARTNER","OWNER","TENANT"],"example":"STAFF"},"roleIds":{"description":"Explicit role IDs to assign. If provided, these are assigned in addition to default roles for the account type.","example":["cmieqoaba0000iymt4fab0345"],"type":"array","items":{"type":"string"}},"phoneNumber":{"type":"string","description":"Phone number to attach to the user (E.164, e.g. \"+61410100101\"). When set, the user can sign into the mobile app via phone OTP. Will be normalized to E.164 before storing.","example":"+61410100101"},"phoneNumberVerified":{"type":"boolean","description":"Whether the supplied phoneNumber has already been verified by OTP. Defaults to false; first successful phone-OTP login flips it to true.","example":false},"onboardingStatus":{"type":"string","description":"Initial onboarding status. Defaults to PENDING for self-registration. Admin-side provisioning (Partner/Staff/Participant auto-create) should pass ACTIVE so the user-management page matches the entity profile status.","enum":["PENDING","ACTIVE","SUSPENDED"],"example":"ACTIVE"}},"required":["name","email","password"]},"UpdateUserDto":{"type":"object","properties":{"name":{"type":"string","description":"The name of the user","example":"John Doe"},"image":{"type":"string","description":"User profile image URL (direct URL, or set via avatarDocumentId)","example":"https://example.com/image.jpg"},"avatarDocumentId":{"type":"string","description":"Avatar document ID from DMS - resolves to image URL and propagates to linked staff/participant","example":"cmieqoaba0000iymt4fab0345"},"accountType":{"type":"string","description":"Account type for the user","enum":["ADMIN","STAFF","PARTICIPANT","SUPPORT_COORDINATOR","GUARDIAN","PARTNER","OWNER","TENANT"],"example":"STAFF"},"onboardingStatus":{"type":"string","description":"Onboarding status of the user","enum":["PENDING","ACTIVE","SUSPENDED"],"example":"ACTIVE"},"password":{"type":"string","description":"New password for the user (admin reset)","example":"NewSecurePass123!"}}},"ManageUserRolesDto":{"type":"object","properties":{"roleIds":{"description":"Array of role IDs to assign or remove","example":["cmieqoaba0000iymt4fab0345","cmieqoaba0001iymt4fab0346"],"type":"array","items":{"type":"string"}}},"required":["roleIds"]},"EntityLinkDto":{"type":"object","properties":{"id":{"type":"string"},"entityType":{"type":"string"},"entityId":{"type":"string"},"isPrimary":{"type":"boolean"},"createdAt":{"format":"date-time","type":"string"}},"required":["id","entityType","entityId","isPrimary","createdAt"]},"ContactIdentifierDto":{"type":"object","properties":{"id":{"type":"string"},"channel":{"type":"string"},"identifier":{"type":"string"}},"required":["id","channel","identifier"]},"ConversationResponseDto":{"type":"object","properties":{"id":{"type":"string"},"orgId":{"type":"string"},"channel":{"type":"object","nullable":true},"status":{"type":"string"},"contactIdentifier":{"type":"object","nullable":true},"contactName":{"type":"string"},"primaryEntityType":{"type":"string"},"primaryEntityId":{"type":"string"},"assignedToUserId":{"type":"string"},"assignedTo":{"$ref":"#/components/schemas/UserBriefDto"},"lastMessageAt":{"format":"date-time","type":"string"},"unreadCount":{"type":"number"},"tags":{"type":"array","items":{"type":"string"}},"entityLinks":{"type":"array","items":{"$ref":"#/components/schemas/EntityLinkDto"}},"contactIdentifiers":{"type":"array","items":{"$ref":"#/components/schemas/ContactIdentifierDto"}},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"archivedAt":{"type":"object","nullable":true}},"required":["id","orgId","status","unreadCount","tags","entityLinks","contactIdentifiers","createdAt","updatedAt"]},"GetAllConversationsDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ConversationResponseDto"}}},"required":["data"]},"GetSingleConversationDto":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ConversationResponseDto"}},"required":["data"]},"CreateConversationDto":{"type":"object","properties":{"channel":{"type":"string","enum":["SMS","EMAIL","CALL","CHAT"],"description":"Channel (optional for unified conversations created from entity pages)"},"contactIdentifier":{"type":"string","description":"Phone number or email address (optional if primaryEntityType+primaryEntityId provided)"},"contactName":{"type":"string"},"primaryEntityType":{"type":"string","enum":["LEAD","PARTICIPANT","PARTNER","STAFF","PROVIDER","PROPERTY","TENANCY","OWNER","TENANT","SUPPLIER"]},"primaryEntityId":{"type":"string"},"assignedToUserId":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}}}},"UpdateConversationDto":{"type":"object","properties":{"status":{"type":"string","enum":["OPEN","CLOSED"]},"contactName":{"type":"string"},"assignedToUserId":{"type":"object","nullable":true},"tags":{"type":"array","items":{"type":"string"}}}},"LinkEntityDto":{"type":"object","properties":{"entityType":{"type":"string","enum":["LEAD","PARTICIPANT","PARTNER","STAFF","PROVIDER","PROPERTY","TENANCY","OWNER","TENANT","SUPPLIER"]},"entityId":{"type":"string"},"isPrimary":{"type":"boolean"}},"required":["entityType","entityId"]},"AddContactIdentifierDto":{"type":"object","properties":{"channel":{"type":"string","enum":["SMS","EMAIL","CALL","CHAT"]},"identifier":{"type":"string","description":"Phone number or email address"}},"required":["channel","identifier"]},"AddNoteDto":{"type":"object","properties":{"body":{"type":"string"}},"required":["body"]},"SendSmsDto":{"type":"object","properties":{"to":{"type":"string","description":"Recipient phone number"},"body":{"type":"string","description":"Message body"},"templateId":{"type":"string","description":"Template ID to use"},"entityType":{"type":"string","enum":["LEAD","PARTICIPANT","PARTNER","STAFF","PROVIDER","PROPERTY","TENANCY","OWNER","TENANT","SUPPLIER"]},"entityId":{"type":"string"},"conversationId":{"type":"string","description":"Existing conversation ID"}},"required":["to","body"]},"MessageResponseDto":{"type":"object","properties":{"id":{"type":"string"},"conversationId":{"type":"string"},"orgId":{"type":"string"},"channel":{"type":"string"},"direction":{"type":"string"},"fromAddress":{"type":"string"},"toAddress":{"type":"string"},"subject":{"type":"string"},"bodyText":{"type":"string"},"bodyHtml":{"type":"string"},"provider":{"type":"string"},"providerMessageId":{"type":"string"},"status":{"type":"string"},"errorCode":{"type":"string"},"errorMessage":{"type":"string"},"sentAt":{"format":"date-time","type":"string"},"deliveredAt":{"format":"date-time","type":"string"},"templateId":{"type":"string"},"segmentCount":{"type":"number"},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","conversationId","orgId","channel","direction","fromAddress","toAddress","bodyText","status","createdAt","updatedAt"]},"GetSingleMessageDto":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MessageResponseDto"}},"required":["data"]},"SendEmailDto":{"type":"object","properties":{"to":{"type":"string","description":"Recipient email address"},"subject":{"type":"string","description":"Email subject"},"bodyText":{"type":"string","description":"Plain text body"},"bodyHtml":{"type":"string","description":"HTML body"},"templateId":{"type":"string","description":"Template ID to use"},"entityType":{"type":"string","enum":["LEAD","PARTICIPANT","PARTNER","STAFF","PROVIDER","PROPERTY","TENANCY","OWNER","TENANT","SUPPLIER"]},"entityId":{"type":"string"},"conversationId":{"type":"string","description":"Existing conversation ID"},"cc":{"description":"CC recipients","type":"array","items":{"type":"string"}},"bcc":{"description":"BCC recipients","type":"array","items":{"type":"string"}}},"required":["to","subject","bodyText"]},"GetAllMessagesDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MessageResponseDto"}}},"required":["data"]},"LogCallDto":{"type":"object","properties":{"phoneNumber":{"type":"string","description":"Phone number called/received from"},"direction":{"type":"string","enum":["IN","OUT"],"description":"IN for received, OUT for made"},"durationSeconds":{"type":"number","description":"Call duration in seconds"},"callStatus":{"type":"string","description":"Call outcome status","example":"completed"},"notes":{"type":"string","description":"Notes about the call"},"entityType":{"type":"string","enum":["LEAD","PARTICIPANT","PARTNER","STAFF","PROVIDER","PROPERTY","TENANCY","OWNER","TENANT","SUPPLIER"]},"entityId":{"type":"string"},"conversationId":{"type":"string","description":"Existing conversation ID"},"recordingUrl":{"type":"string","description":"URL to call recording"}},"required":["phoneNumber","direction","durationSeconds"]},"CommunicationTemplateResponseDto":{"type":"object","properties":{"id":{"type":"string"},"orgId":{"type":"string"},"type":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"subjectTemplate":{"type":"string"},"bodyTemplate":{"type":"string"},"bodyHtmlTemplate":{"type":"string"},"bodyDesignJson":{"type":"object","description":"Unlayer design JSON (email only). Used by frontend to restore editor state."},"editorType":{"type":"string","description":"Email only: UNLAYER (marketing/password) or WYSIWYG (transactional).","enum":["UNLAYER","WYSIWYG"]},"status":{"type":"string"},"version":{"type":"number"},"placeholders":{"type":"object"},"createdBy":{"$ref":"#/components/schemas/UserBriefDto"},"approvedBy":{"$ref":"#/components/schemas/UserBriefDto"},"approvedAt":{"format":"date-time","type":"string"},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","orgId","type","name","tags","bodyTemplate","status","version","createdAt","updatedAt"]},"GetAllTemplatesDto":{"type":"object","properties":{"data":{"description":"List of communication templates","type":"array","items":{"$ref":"#/components/schemas/CommunicationTemplateResponseDto"}}},"required":["data"]},"GetSingleTemplateDto":{"type":"object","properties":{"data":{"description":"Single communication template","allOf":[{"$ref":"#/components/schemas/CommunicationTemplateResponseDto"}]}},"required":["data"]},"CreateCommunicationTemplateDto":{"type":"object","properties":{"type":{"type":"string","enum":["SMS","EMAIL","CALL","CHAT"]},"name":{"type":"string"},"description":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"subjectTemplate":{"type":"string","description":"Subject template (email only)"},"bodyTemplate":{"type":"string","description":"Body template (Liquid syntax)"},"bodyHtmlTemplate":{"type":"string","description":"HTML body template (email only)"},"bodyDesignJson":{"type":"object","description":"Unlayer design JSON (email only). Pass the editor design object to restore layout in Unlayer."},"editorType":{"type":"string","enum":["HTML","UNLAYER","WYSIWYG"],"description":"Email only: HTML (raw code editor), UNLAYER (drag-drop), or WYSIWYG (rich text). Defaults to HTML."}},"required":["type","name","bodyTemplate"]},"UpdateCommunicationTemplateDto":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"subjectTemplate":{"type":"string"},"bodyTemplate":{"type":"string"},"bodyHtmlTemplate":{"type":"string"},"bodyDesignJson":{"type":"object","description":"Unlayer design JSON (email only). Pass the editor design object to restore layout."},"editorType":{"type":"string","enum":["HTML","UNLAYER","WYSIWYG"],"description":"Email only: HTML, UNLAYER, or WYSIWYG."}}},"PreviewTemplateDto":{"type":"object","properties":{"entityType":{"type":"string","enum":["LEAD","PARTICIPANT","PARTNER","STAFF","PROVIDER","PROPERTY","TENANCY","OWNER","TENANT","SUPPLIER"]},"entityId":{"type":"string"}},"required":["entityType","entityId"]},"TemplatePreviewDto":{"type":"object","properties":{"subject":{"type":"string"},"body":{"type":"string"},"bodyHtml":{"type":"string"}},"required":["body"]},"TelnyxConfigDto":{"type":"object","properties":{"apiKey":{"type":"string","description":"Telnyx V2 API key"},"fromNumber":{"type":"string","description":"Telnyx phone number (E.164 format)"},"messagingProfileId":{"type":"string","description":"Telnyx Messaging Profile ID (for number-pool sends)"}},"required":["apiKey","fromNumber"]},"TestSmsDto":{"type":"object","properties":{}},"SetActiveSmsProviderDto":{"type":"object","properties":{}},"SmtpConfigDto":{"type":"object","properties":{"host":{"type":"string","description":"SMTP host"},"port":{"type":"number","description":"SMTP port"},"secure":{"type":"boolean","description":"Use TLS/SSL"},"user":{"type":"string","description":"SMTP username"},"pass":{"type":"string","description":"SMTP password"},"fromEmail":{"type":"string","description":"From email address"},"fromName":{"type":"string","description":"From display name"},"replyTo":{"type":"string","description":"Reply-to email address"}},"required":["host","port","secure","user","pass","fromEmail","fromName"]},"TestEmailDto":{"type":"object","properties":{}},"SendTenancyMessageDto":{"type":"object","properties":{"channel":{"type":"string","enum":["sms","email"]},"body":{"type":"string"},"subject":{"type":"string"}},"required":["channel","body"]},"CreateDirectChannelDto":{"type":"object","properties":{"targetUserId":{"type":"string","description":"Target user ID for 1:1 chat"}},"required":["targetUserId"]},"CreateGroupChannelDto":{"type":"object","properties":{"name":{"type":"string","description":"Group chat name"},"memberIds":{"description":"Member user IDs","type":"array","items":{"type":"string"}}},"required":["name","memberIds"]},"AddChannelMembersDto":{"type":"object","properties":{"memberIds":{"description":"User IDs to add as members","type":"array","items":{"type":"string"}}},"required":["memberIds"]},"IconResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"The id of the icon","example":"123e4567-e89b-12d3-a456-426614174000"},"orgId":{"type":"string","description":"The organization ID of the icon","example":"123e4567-e89b-12d3-a456-426614174000"},"icon":{"type":"string","description":"The icon identifier from Iconify","example":"mdi:home"},"createdAt":{"format":"date-time","type":"string","description":"The created at timestamp of the icon","example":"2025-12-03T10:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","description":"The updated at timestamp of the icon","example":"2025-12-03T10:00:00.000Z"}},"required":["id","orgId","icon","createdAt","updatedAt"]},"GetAllIconDto":{"type":"object","properties":{"success":{"type":"boolean","example":true,"description":"Indicates if the request was successful"},"statusCode":{"type":"number","example":200,"description":"HTTP status code"},"message":{"type":"string","example":"Operation completed successfully","description":"Response message"},"timestamp":{"type":"string","example":"2025-11-19T10:00:00.000Z","description":"Response timestamp"},"data":{"type":"array","items":{"$ref":"#/components/schemas/IconResponseDto"}},"meta":{"type":"object","properties":{"page":{"type":"number","example":1},"limit":{"type":"number","example":10},"total":{"type":"number","example":100},"totalPages":{"type":"number","example":10},"hasNext":{"type":"boolean","example":true},"hasPrev":{"type":"boolean","example":false}}}},"required":["success","statusCode","message","timestamp","data","meta"]},"CreateIconDto":{"type":"object","properties":{"icon":{"type":"string","description":"The icon identifier from Iconify (e.g., mdi:home, fa:user)","example":"mdi:home"}},"required":["icon"]},"GetSingleIconDto":{"type":"object","properties":{"success":{"type":"boolean","example":true,"description":"Indicates if the request was successful"},"statusCode":{"type":"number","example":200,"description":"HTTP status code"},"message":{"type":"string","example":"Operation completed successfully","description":"Response message"},"timestamp":{"type":"string","example":"2025-11-19T10:00:00.000Z","description":"Response timestamp"},"data":{"$ref":"#/components/schemas/IconResponseDto"}},"required":["success","statusCode","message","timestamp","data"]},"UpdateIconDto":{"type":"object","properties":{"icon":{"type":"string","description":"The icon identifier from Iconify (e.g., mdi:home, fa:user)","example":"mdi:home"}}},"WorkflowEventMetadataDto":{"type":"object","properties":{"name":{"type":"string","description":"Event name in dot notation","example":"shift.created"},"category":{"type":"string","description":"Event category/module","example":"shift"},"label":{"type":"string","description":"Human-readable label","example":"Shift Created"},"description":{"type":"string","description":"Event description","example":"Triggered when a new shift is created"},"contextSchema":{"type":"object","description":"Available context variables","additionalProperties":{"type":"string"},"example":{"shift":"Shift - The created shift object","userId":"string - ID of user who created"}}},"required":["name","category","label","description","contextSchema"]},"WorkflowActionMetadataDto":{"type":"object","properties":{"type":{"type":"string","description":"Action type","example":"email"},"label":{"type":"string","description":"Human-readable label","example":"Send Email"},"description":{"type":"string","description":"Action description","example":"Send a custom email message"},"configSchema":{"type":"object","description":"Configuration schema","additionalProperties":true},"implemented":{"type":"boolean","description":"Whether action is implemented","example":true}},"required":["type","label","description","configSchema","implemented"]},"WorkflowConfigResponseDto":{"type":"object","properties":{"events":{"description":"Available trigger events","type":"array","items":{"$ref":"#/components/schemas/WorkflowEventMetadataDto"}},"actions":{"description":"Available workflow actions","type":"array","items":{"$ref":"#/components/schemas/WorkflowActionMetadataDto"}}},"required":["events","actions"]},"WorkflowBindingResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"cmieqoaba0000iymt4fab0345"},"triggerEvent":{"type":"string","example":"shift.created"},"filtersJson":{"type":"object","description":"Optional filter conditions for event data"},"priority":{"type":"number","description":"Priority for ordering multiple workflows","example":0},"isActive":{"type":"boolean","description":"Whether this binding is active","example":true},"createdAt":{"format":"date-time","type":"string","description":"Binding creation timestamp","example":"2026-02-03T10:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","description":"Binding update timestamp","example":"2026-02-03T10:00:00.000Z"}},"required":["id","triggerEvent","priority","isActive","createdAt","updatedAt"]},"WorkflowExecutionStatsDto":{"type":"object","properties":{"total":{"type":"number","description":"Total execution count","example":42},"byStatus":{"type":"object","description":"Execution counts grouped by status","example":{"SUCCEEDED":40,"FAILED":2}},"lastExecutionAt":{"type":"object","description":"Most recent execution time","example":"2026-02-03T10:00:00.000Z"}},"required":["total","byStatus"]},"WorkflowDefinitionResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"cmieqoaba0000iymt4fab0345"},"name":{"type":"string","description":"Workflow name","example":"Shift Created Email"},"description":{"type":"object","description":"Workflow description","example":"Send an email when a shift is created"},"triggerEvent":{"type":"string","description":"Trigger event name","example":"shift.created"},"status":{"type":"string","description":"Workflow status","enum":["DRAFT","ACTIVE","DISABLED"]},"version":{"type":"number","description":"Workflow version","example":1},"definitionJson":{"type":"object","description":"Workflow definition JSON"},"createdByUserId":{"type":"object","description":"User ID who created the workflow","example":"cmieqoaba0000iymt4fab0345"},"createdAt":{"format":"date-time","type":"string","description":"Workflow creation timestamp","example":"2026-02-03T10:00:00.000Z"},"updatedAt":{"format":"date-time","type":"string","description":"Workflow update timestamp","example":"2026-02-03T10:00:00.000Z"},"bindings":{"description":"Workflow bindings","type":"array","items":{"$ref":"#/components/schemas/WorkflowBindingResponseDto"}},"executionStats":{"description":"Execution statistics for this workflow","allOf":[{"$ref":"#/components/schemas/WorkflowExecutionStatsDto"}]}},"required":["id","name","triggerEvent","status","version","definitionJson","createdAt","updatedAt"]},"WorkflowStepDto":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the step within the workflow","example":"step_1"},"name":{"type":"string","description":"Display name of the step","example":"Send Welcome Email"},"type":{"type":"string","description":"Type of action to execute (email, sms, http, etc.)","example":"templated-email"},"config":{"type":"object","description":"Configuration object for the step action","example":{"templateId":"welcome-email","to":"{{participant.email}}"}}},"required":["id","name","type","config"]},"WorkflowDefinitionJsonDto":{"type":"object","properties":{"steps":{"description":"Array of workflow steps to execute in order","type":"array","items":{"$ref":"#/components/schemas/WorkflowStepDto"}},"meta":{"type":"object","description":"React Flow layout metadata for visual editor","example":{"nodes":[{"id":"trigger","position":{"x":0,"y":0}},{"id":"send_email","position":{"x":250,"y":0}}],"edges":[{"id":"e1","source":"trigger","target":"send_email"}],"viewport":{"x":0,"y":0,"zoom":1}}}},"required":["steps"]},"CreateWorkflowDefinitionDto":{"type":"object","properties":{"name":{"type":"string","description":"Name of the workflow definition","example":"New Participant Onboarding"},"description":{"type":"string","description":"Description of what this workflow does","example":"Sends welcome email and creates initial tasks for new participants"},"triggerEvent":{"type":"string","description":"Event name that triggers this workflow","example":"participant.created"},"definition":{"description":"Workflow definition containing steps to execute","allOf":[{"$ref":"#/components/schemas/WorkflowDefinitionJsonDto"}]}},"required":["name","triggerEvent","definition"]},"UpdateWorkflowDefinitionDto":{"type":"object","properties":{"name":{"type":"string","description":"Name of the workflow definition","example":"New Participant Onboarding"},"description":{"type":"string","description":"Description of what this workflow does","example":"Sends welcome email and creates initial tasks for new participants"},"triggerEvent":{"type":"string","description":"Event name that triggers this workflow","example":"participant.created"},"definition":{"description":"Workflow definition containing steps to execute","allOf":[{"$ref":"#/components/schemas/WorkflowDefinitionJsonDto"}]}}},"ManualRunDto":{"type":"object","properties":{"entityType":{"type":"string","description":"Entity type to associate with this execution","example":"workflow"},"entityId":{"type":"string","description":"Entity ID to associate with this execution","example":"cmieqoaba0000iymt4fab0345"},"contextOverrides":{"type":"object","description":"Overrides for event data to use in templates (Liquid context)","example":{"participant":{"id":"cmieqoaba0000iymt4fab0345","email":"test@example.com"},"reason":"Manual run for QA"}}}},"WorkflowDefinitionSummaryDto":{"type":"object","properties":{"id":{"type":"string","example":"cmieqoaba0000iymt4fab0345"},"name":{"type":"string","example":"Shift Created Email"},"triggerEvent":{"type":"string","example":"shift.created"}},"required":["id","name","triggerEvent"]},"WorkflowExecutionCountDto":{"type":"object","properties":{"steps":{"type":"number","example":2},"logs":{"type":"number","example":4}},"required":["steps","logs"]},"WorkflowExecutionResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"cmieqoaba0000iymt4fab0345"},"workflowDefinitionId":{"type":"string","example":"cmieqoaba0000iymt4fab0345"},"workflowVersion":{"type":"number","example":1},"triggerEventName":{"type":"string","example":"shift.created"},"triggerEventId":{"type":"string","example":"event-uuid-123"},"entityType":{"type":"string","example":"shift"},"entityId":{"type":"string","example":"cmieqoaba0000iymt4fab0345"},"status":{"type":"string","enum":["QUEUED","RUNNING","SUCCEEDED","FAILED","CANCELLED"]},"startedAt":{"type":"object","example":"2026-02-03T10:00:00.000Z"},"finishedAt":{"type":"object","example":"2026-02-03T10:00:05.000Z"},"errorSummary":{"type":"object","example":"Step execution failed"},"correlationId":{"type":"object","example":"corr-123"},"rerunOfExecutionId":{"type":"object","example":"cmieqoaba0000iymt4fab0345"},"contextJson":{"type":"object"},"createdAt":{"format":"date-time","type":"string","description":"Execution creation timestamp","example":"2026-02-03T10:00:00.000Z"},"workflowDefinition":{"$ref":"#/components/schemas/WorkflowDefinitionSummaryDto"},"_count":{"$ref":"#/components/schemas/WorkflowExecutionCountDto"}},"required":["id","workflowDefinitionId","workflowVersion","triggerEventName","triggerEventId","entityType","entityId","status","contextJson","createdAt"]},"WorkflowExecutionListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowExecutionResponseDto"}},"total":{"type":"number","description":"Total matching records","example":120},"limit":{"type":"number","description":"Max results returned","example":50},"offset":{"type":"number","description":"Results skipped","example":0}},"required":["data","total","limit","offset"]},"WorkflowStepExecutionResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"cmieqoaba0000iymt4fab0345"},"stepId":{"type":"string","example":"send_email"},"stepType":{"type":"string","enum":["EMAIL","SMS","TEMPLATED_EMAIL","TEMPLATED_SMS","HTTP","CONDITION","DELAY","NOTIFICATION"]},"stepName":{"type":"object","example":"Send Email"},"status":{"type":"string","enum":["QUEUED","RUNNING","SUCCEEDED","FAILED","SKIPPED"]},"attempt":{"type":"number","example":1},"startedAt":{"type":"object","example":"2026-02-03T10:00:00.000Z"},"finishedAt":{"type":"object","example":"2026-02-03T10:00:05.000Z"},"inputJson":{"type":"object"},"outputJson":{"type":"object"},"errorJson":{"type":"object"},"nextRetryAt":{"type":"object","example":"2026-02-03T10:01:00.000Z"},"maxAttempts":{"type":"number","example":3},"createdAt":{"format":"date-time","type":"string","description":"Step creation timestamp","example":"2026-02-03T10:00:00.000Z"}},"required":["id","stepId","stepType","status","attempt","maxAttempts","createdAt"]},"WorkflowExecutionLogResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"cmieqoaba0000iymt4fab0345"},"level":{"type":"string","example":"info"},"message":{"type":"string","example":"Workflow execution started"},"dataJson":{"type":"object"},"createdAt":{"format":"date-time","type":"string","description":"Log entry timestamp","example":"2026-02-03T10:00:00.000Z"}},"required":["id","level","message","createdAt"]},"WorkflowExecutionDetailResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"cmieqoaba0000iymt4fab0345"},"workflowDefinitionId":{"type":"string","example":"cmieqoaba0000iymt4fab0345"},"workflowVersion":{"type":"number","example":1},"triggerEventName":{"type":"string","example":"shift.created"},"triggerEventId":{"type":"string","example":"event-uuid-123"},"entityType":{"type":"string","example":"shift"},"entityId":{"type":"string","example":"cmieqoaba0000iymt4fab0345"},"status":{"type":"string","enum":["QUEUED","RUNNING","SUCCEEDED","FAILED","CANCELLED"]},"startedAt":{"type":"object","example":"2026-02-03T10:00:00.000Z"},"finishedAt":{"type":"object","example":"2026-02-03T10:00:05.000Z"},"errorSummary":{"type":"object","example":"Step execution failed"},"correlationId":{"type":"object","example":"corr-123"},"rerunOfExecutionId":{"type":"object","example":"cmieqoaba0000iymt4fab0345"},"contextJson":{"type":"object"},"createdAt":{"format":"date-time","type":"string","description":"Execution creation timestamp","example":"2026-02-03T10:00:00.000Z"},"workflowDefinition":{"$ref":"#/components/schemas/WorkflowDefinitionSummaryDto"},"_count":{"$ref":"#/components/schemas/WorkflowExecutionCountDto"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowStepExecutionResponseDto"}},"logs":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowExecutionLogResponseDto"}}},"required":["id","workflowDefinitionId","workflowVersion","triggerEventName","triggerEventId","entityType","entityId","status","contextJson","createdAt"]},"WorkflowStatsResponseDto":{"type":"object","properties":{"definitions":{"type":"number","description":"Total workflow definitions","example":10},"executions":{"type":"number","description":"Total executions","example":150},"executionsByStatus":{"type":"object","description":"Executions grouped by status","example":{"SUCCEEDED":140,"FAILED":5,"RUNNING":2,"QUEUED":3}}},"required":["definitions","executions","executionsByStatus"]},"VerificationResponseDto":{"type":"object","properties":{"status":{"type":"string","description":"Verification outcome","enum":["PASS","FAIL","INCONCLUSIVE"]},"reason":{"type":"string","description":"Human-readable explanation from the AI"},"confidence":{"type":"number","description":"AI confidence percentage (0-100)","example":92},"fieldsChecked":{"type":"object","description":"Per-field verification results. Keys match the field names sent in the request.","example":{"fullName":{"match":true,"detail":"Document: 'Jane E Smith' — match"},"dateOfBirth":{"match":true,"detail":"Document: '15/05/1990' — match"}}}},"required":["status","reason","confidence","fieldsChecked"]},"AuthLogUserDto":{"type":"object","properties":{"id":{"type":"string","description":"User ID","example":"cmieqoaba0000iymt4fab0345"},"name":{"type":"string","description":"User name","example":"John Doe"},"email":{"type":"string","description":"User email","example":"john@example.com"}},"required":["id","email"]},"AuthLogResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Auth log entry ID","example":"cmieqoaba0000iymt4fab0345"},"orgId":{"type":"string","description":"Organization ID","example":"cmieqoaba0000iymt4fab0345"},"userId":{"type":"string","description":"User ID","example":"cmieqoaba0000iymt4fab0345"},"sessionId":{"type":"string","description":"Session ID","example":"session_abc123"},"eventType":{"type":"string","description":"Authentication event type","example":"LOGIN_SUCCESS"},"method":{"type":"string","description":"Authentication method","example":"EMAIL_PASSWORD"},"ipAddress":{"type":"string","description":"Client IP address","example":"203.0.113.42"},"userAgent":{"type":"string","description":"Client user-agent string","example":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)"},"country":{"type":"string","description":"Country code from reverse proxy headers","example":"AU"},"city":{"type":"string","description":"City from reverse proxy headers","example":"Sydney"},"region":{"type":"string","description":"Region from reverse proxy headers","example":"New South Wales"},"metadata":{"type":"object","description":"Additional event metadata","example":{"reason":"EXPIRED"}},"createdAt":{"format":"date-time","type":"string","description":"When the event occurred","example":"2026-02-13T10:30:00.000Z"},"user":{"description":"The user who triggered the event","allOf":[{"$ref":"#/components/schemas/AuthLogUserDto"}]}},"required":["id","eventType","createdAt"]},"CreateMessageCentrePostDto":{"type":"object","properties":{"title":{"type":"string","description":"Title (or internal name for EMAIL/SMS) of the broadcast","example":"Important Policy Update"},"content":{"type":"string","description":"HTML content of the message (IN_APP). For EMAIL/SMS this mirrors the bodyHtml/bodyText so legacy consumers keep working."},"summary":{"type":"string","description":"Plain-text summary for mobile previews"},"channel":{"type":"string","description":"Channel for the broadcast","enum":["IN_APP","EMAIL","SMS"],"default":"IN_APP"},"subject":{"type":"string","description":"Email subject (EMAIL only)"},"bodyHtml":{"type":"string","description":"Email body HTML (EMAIL only)"},"bodyText":{"type":"string","description":"Email plain-text fallback or SMS body"},"bodyDesignJson":{"type":"object","description":"Unlayer design JSON (EMAIL only)"},"sourceTemplateId":{"type":"string","description":"Audit link to a CommunicationTemplate that seeded this broadcast"},"targetAudiences":{"type":"array","description":"Target audience account types. For EMAIL/SMS at least one of targetAudiences or targetGroupIds is required; for IN_APP targetAudiences is required.","example":["ADMIN","STAFF"],"items":{"type":"string","enum":["ADMIN","STAFF","PARTICIPANT","SUPPORT_COORDINATOR","GUARDIAN","PARTNER","OWNER","TENANT"]}},"targetGroupIds":{"description":"Communication group IDs to also target (EMAIL/SMS only). Group members are unioned with account-type audiences and deduped.","type":"array","items":{"type":"string"}},"priority":{"type":"number","description":"Priority for ordering","default":0},"isPinned":{"type":"boolean","description":"Pin to top","default":false},"publish":{"type":"boolean","description":"When true and no scheduling/recurrence is set, publish immediately (IN_APP) or send now (EMAIL/SMS).","default":false},"expiresAt":{"type":"string","description":"Expiry date (ISO 8601). Post hidden after this date."},"scheduledFor":{"type":"object","description":"When to send (one-shot). ISO 8601."},"timezone":{"type":"string","description":"IANA timezone. Defaults to Australia/Sydney.","example":"Australia/Sydney"},"recurrence":{"type":"object","description":"Recurrence configuration. When provided, the broadcast becomes recurring."}},"required":["title"]},"AudienceDto":{"type":"object","properties":{"id":{"type":"string","description":"Audience record ID","example":"cmieqoaba0000iymt4fab0345"},"accountType":{"type":"string","description":"Account type","example":"STAFF","enum":["ADMIN","STAFF","PARTICIPANT","SUPPORT_COORDINATOR","GUARDIAN","PARTNER"]}},"required":["id","accountType"]},"GroupBriefDto":{"type":"object","properties":{"id":{"type":"string","description":"Group ID"},"name":{"type":"string","description":"Group name"},"type":{"type":"object","description":"Group type","nullable":true}},"required":["id","name"]},"GroupTargetDto":{"type":"object","properties":{"id":{"type":"string","description":"Group target record ID"},"groupId":{"type":"string","description":"Group ID"},"group":{"description":"Group","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/GroupBriefDto"}]}},"required":["id","groupId"]},"MessageCentrePostResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Post ID","example":"cmieqoaba0000iymt4fab0345"},"orgId":{"type":"string","description":"Organization ID","example":"cmieqoaba0000iymt4fab0345"},"title":{"type":"string","description":"Title of the announcement","example":"Important Policy Update"},"content":{"type":"string","description":"HTML content from WYSIWYG editor"},"summary":{"type":"object","description":"Plain-text summary","nullable":true},"status":{"type":"string","description":"Post status","example":"PUBLISHED","enum":["DRAFT","SCHEDULED","PUBLISHED","ARCHIVED","COMPLETED","PAUSED"]},"channel":{"type":"string","description":"Channel of the broadcast","example":"IN_APP","enum":["IN_APP","EMAIL","SMS"]},"subject":{"type":"object","description":"Email subject","nullable":true},"bodyHtml":{"type":"object","description":"Email HTML body","nullable":true},"bodyText":{"type":"object","description":"Plain text body (EMAIL fallback / SMS)","nullable":true},"bodyDesignJson":{"type":"object","description":"Unlayer design JSON (EMAIL)","nullable":true},"sourceTemplateId":{"type":"object","description":"Source CommunicationTemplate ID","nullable":true},"scheduledFor":{"type":"object","description":"Scheduled send time","nullable":true},"timezone":{"type":"object","description":"Timezone (IANA)","nullable":true},"recurrence":{"type":"object","description":"Recurrence config (null = one-shot)","nullable":true},"nextRunAt":{"type":"object","description":"Next dispatch time","nullable":true},"lastRunAt":{"type":"object","description":"Last dispatch time","nullable":true},"occurrencesSent":{"type":"number","description":"How many times the post has been dispatched"},"priority":{"type":"number","description":"Priority for ordering","example":0},"isPinned":{"type":"boolean","description":"Whether the post is pinned","example":false},"publishedAt":{"type":"object","description":"When the post was published","nullable":true},"expiresAt":{"type":"object","description":"When the post expires","nullable":true},"createdByUserId":{"type":"object","description":"Created by user ID","nullable":true},"createdAt":{"format":"date-time","type":"string","description":"Created at"},"updatedAt":{"format":"date-time","type":"string","description":"Updated at"},"createdByUser":{"description":"User who created the post","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/UserBriefDto"}]},"targetAudiences":{"description":"Target audiences","type":"array","items":{"$ref":"#/components/schemas/AudienceDto"}},"targetGroups":{"description":"Target communication groups (EMAIL/SMS only)","type":"array","items":{"$ref":"#/components/schemas/GroupTargetDto"}}},"required":["id","orgId","title","content","status","channel","occurrencesSent","priority","isPinned","createdAt","updatedAt","targetAudiences"]},"UpdateMessageCentrePostDto":{"type":"object","properties":{"title":{"type":"string","description":"Title or internal name"},"content":{"type":"string","description":"HTML content (IN_APP)"},"summary":{"type":"string","description":"Plain-text summary"},"subject":{"type":"string","description":"Email subject"},"bodyHtml":{"type":"string","description":"Email body HTML"},"bodyText":{"type":"string","description":"Email plain text / SMS body"},"bodyDesignJson":{"type":"object","description":"Unlayer design JSON"},"sourceTemplateId":{"type":"object","description":"Audit link to source template"},"targetAudiences":{"type":"array","description":"Target audience account types","items":{"type":"string","enum":["ADMIN","STAFF","PARTICIPANT","SUPPORT_COORDINATOR","GUARDIAN","PARTNER","OWNER","TENANT"]}},"targetGroupIds":{"description":"Communication group IDs to target (EMAIL/SMS). Replaces the existing set when provided.","type":"array","items":{"type":"string"}},"priority":{"type":"number","description":"Priority for ordering"},"isPinned":{"type":"boolean","description":"Pin to top"},"expiresAt":{"type":"object","description":"Expiry date (ISO 8601). Pass null to clear.","nullable":true},"scheduledFor":{"type":"object","description":"When to send (one-shot). Pass null to clear.","nullable":true},"timezone":{"type":"string","description":"IANA timezone"},"recurrence":{"type":"object","description":"Recurrence configuration. Pass null to clear.","nullable":true}}},"CreateGroupDto":{"type":"object","properties":{"name":{"type":"string","description":"Group name","example":"Engineering Team"},"description":{"type":"string","description":"Group description","example":"Core engineering team members"},"type":{"type":"string","description":"Group type","enum":["GENERAL","CHAT","VIDEO","DEPARTMENT"],"example":"GENERAL"},"memberIds":{"description":"User IDs to add as members","example":["userId1","userId2"],"type":"array","items":{"type":"string"}}},"required":["name"]},"UpdateGroupDto":{"type":"object","properties":{"name":{"type":"string","description":"Group name","example":"Engineering Team"},"description":{"type":"string","description":"Group description"},"type":{"type":"string","description":"Group type","enum":["GENERAL","CHAT","VIDEO","DEPARTMENT"]},"isActive":{"type":"boolean","description":"Whether group is active"}}},"AddMembersDto":{"type":"object","properties":{"memberIds":{"description":"User IDs to add as members","example":["userId1","userId2"],"type":"array","items":{"type":"string"}}},"required":["memberIds"]},"RecurrenceRuleDto":{"type":"object","properties":{"type":{"type":"string","description":"Recurrence frequency","enum":["daily","weekly","monthly","yearly","custom"],"example":"weekly"},"interval":{"type":"number","description":"Repeat every N periods (e.g., every 2 weeks)","example":1,"minimum":1,"maximum":365},"daysOfWeek":{"description":"Days of week for weekly recurrence (0=Sun..6=Sat)","example":[1,3,5],"type":"array","items":{"type":"number"}},"dayOfMonth":{"type":"number","description":"Day of month for monthly recurrence (1-31)","example":15},"endType":{"type":"string","description":"When recurrence ends","enum":["never","count","until"],"example":"never"},"endCount":{"type":"number","description":"Number of occurrences before ending (when endType=count)","example":10},"endDate":{"type":"string","description":"End date for recurrence (when endType=until), ISO string","example":"2026-12-31"}},"required":["type","interval","endType"]},"CreateReminderRecipientDto":{"type":"object","properties":{"recipientType":{"type":"string","description":"Recipient type (user, staff, participant)","example":"user"},"recipientId":{"type":"string","description":"Recipient entity ID","example":"cm123abc"},"recipientName":{"type":"string","description":"Recipient display name","example":"John Smith"},"recipientEmail":{"type":"string","description":"Recipient email address for EMAIL channel","example":"john@example.com"},"recipientPhone":{"type":"string","description":"Recipient phone number for SMS channel","example":"+61412345678"},"channel":{"type":"string","description":"Notification channel for this recipient","enum":["IN_APP","SMS","EMAIL"],"example":"IN_APP"}},"required":["recipientType","recipientId","channel"]},"CreateReminderDto":{"type":"object","properties":{"title":{"type":"string","description":"Reminder title (auto-filled if templateId provided)","example":"Follow up with John"},"content":{"type":"string","description":"Reminder content/body (auto-filled if templateId provided)","example":"Remember to call John about his NDIS plan review."},"templateId":{"type":"string","description":"Reminder template ID (renders title/content from template)","example":"clm123abc"},"linkedEntityType":{"type":"string","description":"Entity type this reminder is linked to (optional for simple reminders)","enum":["LEAD","PARTICIPANT","PARTNER","STAFF","PROVIDER"],"example":"LEAD"},"linkedEntityId":{"type":"string","description":"Entity ID this reminder is linked to (optional for simple reminders)","example":"clm456def"},"sourceType":{"type":"string","description":"Source that triggered this reminder","enum":["EMAIL","SMS","NOTE","CONVERSATION","MANUAL"],"example":"MANUAL"},"sourceId":{"type":"string","description":"ID of the source entity (message, note, etc.)","example":"msg_abc123"},"remindAt":{"type":"string","description":"When to fire the reminder (ISO datetime)","example":"2026-03-29T09:00:00.000Z"},"recurrenceRule":{"description":"Recurrence rule (null = one-shot)","allOf":[{"$ref":"#/components/schemas/RecurrenceRuleDto"}]},"recipients":{"description":"Recipients with their preferred notification channels","minItems":1,"type":"array","items":{"$ref":"#/components/schemas/CreateReminderRecipientDto"}}},"required":["remindAt","recipients"]},"UpdateReminderDto":{"type":"object","properties":{"title":{"type":"string","description":"Updated reminder title","example":"Follow up with John (updated)"},"content":{"type":"string","description":"Updated reminder content"},"remindAt":{"type":"string","description":"Updated reminder time (ISO datetime)","example":"2026-03-30T14:00:00.000Z"},"recurrenceRule":{"description":"Updated recurrence rule","allOf":[{"$ref":"#/components/schemas/RecurrenceRuleDto"}]},"recipients":{"description":"Updated recipients list (replaces all existing recipients)","type":"array","items":{"$ref":"#/components/schemas/CreateReminderRecipientDto"}}}},"SnoozeReminderDto":{"type":"object","properties":{"snoozeUntil":{"type":"string","description":"Snooze until this time (ISO datetime)","example":"2026-03-29T15:00:00.000Z"}},"required":["snoozeUntil"]},"CreateAccountArchiveRequestDto":{"type":"object","properties":{"reason":{"type":"string","description":"Reason the user wants their account archived","example":"No longer using the service.","minLength":5,"maxLength":2000}},"required":["reason"]},"UserSummaryDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"object","nullable":true},"email":{"type":"string"}},"required":["id","email"]},"AccountArchiveRequestResponseDto":{"type":"object","properties":{"id":{"type":"string"},"orgId":{"type":"string"},"requesterUserId":{"type":"string"},"accountType":{"type":"string","enum":["ADMIN","STAFF","PARTICIPANT","SUPPORT_COORDINATOR","GUARDIAN","PARTNER","OWNER","TENANT"]},"reason":{"type":"string"},"status":{"type":"string","enum":["PENDING","APPROVED","REJECTED","CANCELLED"]},"reviewedByUserId":{"type":"object","nullable":true},"reviewedAt":{"type":"string","nullable":true,"format":"date-time"},"reviewNotes":{"type":"object","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"requester":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/UserSummaryDto"}]},"reviewer":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/UserSummaryDto"}]}},"required":["id","orgId","requesterUserId","accountType","reason","status","createdAt","updatedAt"]},"ReviewAccountArchiveRequestDto":{"type":"object","properties":{"reviewNotes":{"type":"string","description":"Notes from the reviewer (visible to the requester)","maxLength":2000}}},"UpdatePolicyDto":{"type":"object","properties":{"maxOwnerSpendWithoutApprovalCents":{"type":"number","description":"Owner spend ceiling (any agent) before human approval is forced, in integer cents. Cannot exceed the platform hard ceiling ($750 / 75000 cents).","example":50000},"defaultNoticeChannel":{"type":"string","description":"Default channel for statutory notices","enum":["email","sms","post","portal"],"example":"email"},"businessHoursStart":{"type":"string","description":"Business hours start, 24h HH:mm","example":"08:30"},"businessHoursEnd":{"type":"string","description":"Business hours end, 24h HH:mm","example":"17:30"},"businessDays":{"description":"Business days, 1 = Monday … 7 = Sunday","example":[1,2,3,4,5],"type":"array","items":{"type":"number"}},"afterHoursRouting":{"type":"string","description":"After-hours emergency routing target","enum":["on-call-manager","preferred-vendor","principal"],"example":"preferred-vendor"},"rentPaymentBsb":{"type":"object","description":"Fee-free rent payment BSB shown in the tenant portal","example":"062-000"},"rentPaymentAccountNumber":{"type":"object","description":"Fee-free rent payment account number shown in the tenant portal"},"rentPaymentBpayBiller":{"type":"object","description":"BPAY biller code shown in the tenant portal"}}},"CreatePropertyDto":{"type":"object","properties":{"line1":{"type":"string","description":"Address line 1","example":"12 Smith Street"},"line2":{"type":"string","description":"Address line 2","example":"Unit 4"},"suburb":{"type":"string","description":"Suburb","example":"Parramatta"},"state":{"type":"string","description":"State","example":"NSW","default":"NSW"},"postcode":{"type":"string","description":"Postcode","example":"2150"},"latitude":{"type":"number","description":"Latitude","example":-33.815},"longitude":{"type":"number","description":"Longitude","example":151},"type":{"type":"string","description":"Property type","enum":["HOUSE","APARTMENT","TOWNHOUSE","DUPLEX","VILLA","STUDIO","COMMERCIAL"],"example":"HOUSE"},"status":{"type":"string","description":"Property status","enum":["PROSPECTIVE","OCCUPIED","VACANT","VACATING","ARCHIVED"],"default":"PROSPECTIVE"},"beds":{"type":"number","description":"Number of bedrooms","example":3},"baths":{"type":"number","description":"Number of bathrooms","example":2},"carSpaces":{"type":"number","description":"Number of car spaces","example":1,"default":0},"landSizeSqm":{"type":"number","description":"Land size in square metres","example":450},"features":{"description":"Feature tags","example":["pool","air-conditioning"],"type":"array","items":{"type":"string"}},"managerUserId":{"type":"string","description":"Assigned property manager user ID"},"hasPool":{"type":"boolean","description":"Whether the property has a pool or spa. Omit if unknown."},"hasGas":{"type":"boolean","description":"Whether the property has gas. Omit if unknown."}},"required":["line1","suburb","postcode","type","beds","baths"]},"UpdatePropertyDto":{"type":"object","properties":{"line1":{"type":"string","description":"Address line 1"},"line2":{"type":"string","description":"Address line 2"},"suburb":{"type":"string","description":"Suburb"},"state":{"type":"string","description":"State"},"postcode":{"type":"string","description":"Postcode"},"latitude":{"type":"number","description":"Latitude"},"longitude":{"type":"number","description":"Longitude"},"type":{"type":"string","description":"Property type","enum":["HOUSE","APARTMENT","TOWNHOUSE","DUPLEX","VILLA","STUDIO","COMMERCIAL"]},"status":{"type":"string","description":"Property status","enum":["PROSPECTIVE","OCCUPIED","VACANT","VACATING","ARCHIVED"]},"beds":{"type":"number","description":"Number of bedrooms"},"baths":{"type":"number","description":"Number of bathrooms"},"carSpaces":{"type":"number","description":"Number of car spaces"},"landSizeSqm":{"type":"number","description":"Land size in square metres"},"features":{"description":"Feature tags","type":"array","items":{"type":"string"}},"managerUserId":{"type":"object","description":"Assigned property manager user ID (null to unassign)","nullable":true},"hasPool":{"type":"object","description":"Whether the property has a pool or spa. Null = unknown.","nullable":true},"hasGas":{"type":"object","description":"Whether the property has gas. Null = unknown.","nullable":true},"followPropertyMeManager":{"type":"boolean","description":"Clear a manual manager override and re-derive managerUserId from the property's stored PropertyMe manager email."}}},"AddOwnershipDto":{"type":"object","properties":{"ownerId":{"type":"string","description":"Owner ID to attach to the property"},"sharePercent":{"type":"number","description":"Ownership share (0-100)","example":100},"isPrimary":{"type":"boolean","description":"Whether this owner is the primary contact for the property","default":false},"startDate":{"type":"string","description":"Ownership start date (ISO), defaults to now"}},"required":["ownerId"]},"UpdateOwnershipDto":{"type":"object","properties":{"sharePercent":{"type":"number","description":"Ownership share (0-100)"},"isPrimary":{"type":"boolean","description":"Whether this owner is the primary contact for the property"},"endDate":{"type":"string","description":"Ownership end date (ISO)"}}},"UpsertManagementAgreementDto":{"type":"object","properties":{"ownerId":{"type":"string","description":"Owner ID this agreement is with"},"signedDate":{"type":"string","description":"Date the agreement was signed (ISO)"},"managementFeeBps":{"type":"number","description":"Management fee in basis points (550 = 5.50%)","example":550},"lettingFeeWeeks":{"type":"number","description":"Letting fee in weeks of rent","default":1,"example":1},"adminFeeMonthlyCents":{"type":"number","description":"Fixed monthly admin fee, integer cents","default":0},"inspectionsPerYear":{"type":"number","description":"Contracted routine inspections per year","default":2},"spendCapCents":{"type":"object","description":"Owner spend cap without approval, integer cents. Null clears the override and falls back to the platform default (config may only tighten the platform hard ceiling, never raise it — enforced by PolicyService at decision time, not here).","nullable":true},"documentId":{"type":"string","description":"DMS document ID for the signed agreement"}},"required":["ownerId","managementFeeBps"]},"CreateOwnerDto":{"type":"object","properties":{"type":{"type":"string","description":"Owner type","enum":["INDIVIDUAL","COMPANY","TRUST","SMSF"],"default":"INDIVIDUAL"},"name":{"type":"string","description":"Owner display name","example":"Jane Citizen"},"email":{"type":"string","description":"Owner email","example":"jane@example.com"},"phone":{"type":"string","description":"Owner phone","example":"+61412345678"},"statementDelivery":{"type":"string","description":"Preferred statement delivery method","default":"portal","example":"portal"}},"required":["name"]},"UpdateOwnerDto":{"type":"object","properties":{"type":{"type":"string","description":"Owner type","enum":["INDIVIDUAL","COMPANY","TRUST","SMSF"]},"name":{"type":"string","description":"Owner display name"},"email":{"type":"string","description":"Owner email"},"phone":{"type":"string","description":"Owner phone"},"statementDelivery":{"type":"string","description":"Preferred statement delivery method"}}},"DecideOwnerDirectionDto":{"type":"object","properties":{"choice":{"type":"string","enum":["QUOTES","DIRECT"],"description":"QUOTES = arrange quotes; DIRECT = proceed without quoting first"},"requestId":{"type":"string","description":"The pending request this decision answers. Required to block stale clicks."},"note":{"type":"string","description":"Optional owner note"}},"required":["choice","requestId"]},"DecideOwnerQuoteDto":{"type":"object","properties":{"action":{"type":"string","enum":["APPROVED","REJECTED","HOLD","MORE"],"default":"APPROVED","description":"What the owner decided about the forwarded quotes"},"quoteId":{"type":"string","description":"The forwarded supplier quote. Required to approve; optional when rejecting or holding."},"note":{"type":"string","description":"Optional owner note"}}},"PortalDecideApprovalDto":{"type":"object","properties":{"note":{"type":"string","description":"Optional note from the owner"}}},"ReportRepairDto":{"type":"object","properties":{"tenancyId":{"type":"string","description":"Tenancy the repair is for (must be your own)"},"title":{"type":"string","description":"Short title","example":"No hot water"},"description":{"type":"string","description":"Full description of the issue","example":"No hot water since last night, storage unit not firing."},"photoDocumentIds":{"description":"Optional DMS document ids for photos of the issue","type":"array","items":{"type":"string"}}},"required":["tenancyId","title","description"]},"CreatePortalPetRequestDto":{"type":"object","properties":{"tenancyId":{"type":"string","description":"Tenancy the request is for (must be your own)"},"petType":{"type":"string","description":"Type of pet","example":"Dog — Cavoodle"},"description":{"type":"string","description":"Free-text detail about the pet"}},"required":["tenancyId","petType"]},"CreateAgentRunDto":{"type":"object","properties":{"agentKey":{"type":"string","enum":["valuation","rent-review","maintenance-triage","arrears","inspection-scheduler"],"description":"Which agent to run"},"triggerType":{"type":"string","description":"What kicked off the run, e.g. \"cron\" | \"manual\" | \"event\"","example":"manual"},"triggerBy":{"type":"string","description":"User id that triggered the run, if any"},"subjectLabel":{"type":"string","description":"What the run is about, e.g. \"12 Crane Street · rent review\""},"propertyId":{"type":"string","description":"Subject property"},"tenancyId":{"type":"string","description":"Subject tenancy"},"ownerId":{"type":"string","description":"Subject owner"},"correlationId":{"type":"string","description":"Correlation id for grouping runs"},"sandbox":{"type":"boolean","description":"Sandbox run — never written to live state, never dispatches","default":false}},"required":["agentKey","triggerType","subjectLabel"]},"CancelAgentRunsDto":{"type":"object","properties":{"agentKey":{"type":"string","enum":["valuation","rent-review","maintenance-triage","arrears","inspection-scheduler"],"description":"Limit the cancellation to one agent’s sweep"}}},"AgentRunStepInputDto":{"type":"object","properties":{"sequence":{"type":"number","description":"Monotonic per-run sequence number"},"kind":{"type":"string","enum":["THOUGHT","TOOL_CALL","TOOL_RESULT","DECISION","ARTIFACT","ACTION","APPROVAL","ERROR"]},"title":{"type":"string","description":"Short step title"},"detail":{"type":"string","description":"Long detail / body"},"tool":{"type":"string","description":"Tool id, for TOOL_CALL/TOOL_RESULT"},"toolSource":{"type":"string","description":"Provenance chip source"},"dataJson":{"type":"object","description":"Structured payload rendered by timeline"},"atMs":{"type":"number","description":"Milliseconds offset from run start"},"status":{"type":"string","description":"Optional per-step status"}},"required":["sequence","kind","title","atMs"]},"AppendRunStepsDto":{"type":"object","properties":{"steps":{"type":"array","items":{"$ref":"#/components/schemas/AgentRunStepInputDto"}}},"required":["steps"]},"ApprovalPolicyDto":{"type":"object","properties":{"mode":{"type":"string","enum":["AUTO","THRESHOLD","HUMAN"],"description":"When the agent self-acts"},"threshold":{"type":"number","description":"Ceiling under which the agent auto-acts (mode THRESHOLD). Cents when unit is \"$\", basis points when \"%\"."},"thresholdUnit":{"type":"string","enum":["$","%","days"]},"approverRole":{"type":"string","enum":["OWNER","STAFF","MANAGER","PRINCIPAL"],"description":"Inbox the approval routes to"},"escalation":{"type":"array","description":"Ordered escalation chain if the approver does not respond","items":{"type":"string","enum":["OWNER","STAFF","MANAGER","PRINCIPAL"]}},"escalateAfterHours":{"type":"number","description":"Hours before an unactioned approval escalates"}},"required":["mode","approverRole","escalation"]},"UpdateAgentConfigDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Master on/off switch for the agent"},"triggersJson":{"type":"object","description":"triggerId -> { enabled, cron? }"},"toolsJson":{"type":"object","description":"toolId -> enabled"},"knobsJson":{"type":"object","description":"agent-specific knobs (radius, weights, caps, …)"},"approvalJson":{"$ref":"#/components/schemas/ApprovalPolicyDto"},"promptOverride":{"type":"object","description":"Prompt override text, or null to clear"}}},"DecideApprovalDto":{"type":"object","properties":{"note":{"type":"string","description":"Optional note from the approver"}}},"SplitMaintenanceJobDto":{"type":"object","properties":{"trades":{"description":"Trades to split into, the job's own trade included. At least two.","example":["Plumber","Painter"],"type":"array","items":{"type":"string"}}},"required":["trades"]},"CreatePetRequestDto":{"type":"object","properties":{"tenancyId":{"type":"string","description":"Tenancy requesting the pet","example":"cmieqoaba0000iymt4fab0345"},"propertyId":{"type":"string","description":"Property the tenancy is at","example":"cmieqoaba0000iymt4fab0346"},"petType":{"type":"string","description":"Type of pet","example":"Dog (Labrador)"},"description":{"type":"string","description":"Additional detail about the pet","example":"4 year old, desexed, indoor only"},"requestedDate":{"type":"string","description":"Date the request was made (ISO date). Defaults to now — respondByDate is always requestedDate + 21 days (NSW).","example":"2026-07-16"}},"required":["tenancyId","propertyId","petType"]},"UpdatePetRequestDto":{"type":"object","properties":{"petType":{"type":"string","description":"Type of pet"},"description":{"type":"string","description":"Additional detail about the pet"}}},"RefusePetRequestDto":{"type":"object","properties":{"refusalGround":{"type":"string","description":"Statutory ground for refusing the pet request (NSW)","example":"Property is a strata scheme with a by-law prohibiting animals of this kind."}},"required":["refusalGround"]},"CreateNoticeDto":{"type":"object","properties":{"type":{"type":"string","description":"Statutory notice type","enum":["RENT_INCREASE_S41","ENTRY_7DAY","TERMINATION_NONPAYMENT_14DAY","TERMINATION_OTHER"],"example":"ENTRY_7DAY"},"tenancyId":{"type":"string","description":"Tenancy this notice relates to","example":"cmieqoaba0000iymt4fab0345"},"propertyId":{"type":"string","description":"Property this notice relates to","example":"cmieqoaba0000iymt4fab0346"},"effectiveDate":{"type":"string","description":"Date the notice is to take effect (ISO date). Required for RENT_INCREASE_S41 (>= today+60d) and ENTRY_7DAY (>= today+7d) — notices that fail the statutory minimum are still created but as BLOCKED.","example":"2026-10-01"},"scheduledSendAt":{"type":"string","description":"When to auto-serve this DRAFT if staff do not cancel it (ISO). Only ENTRY_7DAY inspection notices use this; terminations must omit it.","example":"2026-09-24T23:00:00.000Z"},"groundCode":{"type":"string","description":"Ground/reason code for the notice (e.g. termination ground)","example":"non-payment"},"evidenceJson":{"type":"object","description":"Free-form evidence bundle backing this notice"},"documentId":{"type":"string","description":"DMS document ID for the generated notice PDF"}},"required":["type"]},"ServeNoticeDto":{"type":"object","properties":{"servedDate":{"type":"string","description":"Date the notice was served (ISO date). Defaults to now.","example":"2026-07-16"},"deliverByEmail":{"type":"boolean","description":"Email the notice PDF to the tenants. Defaults to true. Set false when the notice is being served by post or in person — the notice is still marked SERVED and still appears in the tenant portal.","example":true}}},"CreateTenancyDto":{"type":"object","properties":{"propertyId":{"type":"string","description":"The property this tenancy is for","example":"cmieqoaba0000iymt4fab0345"},"ref":{"type":"string","description":"Org-unique human reference. Auto-generated (TCY-0001, ...) when omitted.","example":"TCY-0001"},"status":{"type":"string","description":"Initial lifecycle status. Defaults to PROSPECTIVE. Use PATCH /tenancies/:id for lifecycle transitions.","enum":["PROSPECTIVE","ACTIVE","VACATING","VACATED","ARCHIVED"],"example":"PROSPECTIVE"},"managerUserId":{"type":"string","description":"Staff user managing this tenancy","example":"cmieqoaba0000iymt4fab0345"},"moveInDate":{"type":"string","description":"Move-in date (ISO date)","example":"2026-02-01"},"moveOutDate":{"type":"string","description":"Move-out date (ISO date)","example":"2027-02-01"},"vacateNoticeDate":{"type":"string","description":"Date the tenant gave vacate notice (ISO date)","example":"2027-01-01"},"occupants":{"type":"number","description":"Number of occupants","example":2,"default":1}},"required":["propertyId"]},"UpdateTenancyDto":{"type":"object","properties":{"status":{"type":"string","description":"Lifecycle status. Must be the next status in PROSPECTIVE → ACTIVE → VACATING → VACATED → ARCHIVED — no skipping or reverting.","enum":["PROSPECTIVE","ACTIVE","VACATING","VACATED","ARCHIVED"],"example":"ACTIVE"},"managerUserId":{"type":"object","description":"Staff user managing this tenancy. Pass null to unassign.","example":"cmieqoaba0000iymt4fab0345","nullable":true},"moveInDate":{"type":"string","description":"Move-in date (ISO date)","example":"2026-02-01"},"moveOutDate":{"type":"string","description":"Move-out date (ISO date)","example":"2027-02-01"},"vacateNoticeDate":{"type":"string","description":"Date the tenant gave vacate notice (ISO date)","example":"2027-01-01"},"occupants":{"type":"number","description":"Number of occupants","example":2}}},"AddTenancyTenantDto":{"type":"object","properties":{"tenantId":{"type":"string","description":"Tenant ID to link to this tenancy","example":"cmieqoaba0000iymt4fab0345"},"isPrimary":{"type":"boolean","description":"Whether this tenant is the primary tenant on the tenancy. Setting true unsets isPrimary on all other linked tenants.","example":false,"default":false}},"required":["tenantId"]},"UpdateTenancyTenantDto":{"type":"object","properties":{"isPrimary":{"type":"boolean","description":"Whether this tenant is the primary tenant on the tenancy. Setting true unsets isPrimary on all other linked tenants.","example":true}},"required":["isPrimary"]},"UpsertLeaseDto":{"type":"object","properties":{"type":{"type":"string","description":"Lease type","enum":["FIXED","PERIODIC"],"example":"FIXED"},"startDate":{"type":"string","description":"Lease start date (ISO date)","example":"2026-02-01"},"endDate":{"type":"string","description":"Lease end date (ISO date). Omit/null for periodic leases.","example":"2027-02-01"},"termMonths":{"type":"number","description":"Fixed-term length in months","example":12},"signedByTenant":{"type":"boolean","description":"Signed by tenant","default":false},"signedByAgent":{"type":"boolean","description":"Signed by agent","default":false},"signedDate":{"type":"string","description":"Date the lease was signed (ISO date)","example":"2026-01-15"},"documentId":{"type":"string","description":"DMS document ID for the signed lease","example":"cmieqoaba0000iymt4fab0345"}},"required":["type","startDate"]},"UpsertBondDto":{"type":"object","properties":{"amountCents":{"type":"number","description":"Bond amount in integer cents","example":320000},"weeksOfRent":{"type":"number","description":"Bond amount expressed as weeks of rent","example":4},"status":{"type":"string","description":"Bond lifecycle status. Defaults to PENDING_LODGEMENT on first creation.","enum":["PENDING_LODGEMENT","LODGED","CLAIM_IN_PROGRESS","RELEASED","DISPUTED"],"example":"PENDING_LODGEMENT"},"collectedDate":{"type":"string","description":"Date the bond was collected from the tenant (ISO date). Setting/changing this recomputes lodgementDueDate.","example":"2026-02-01"},"lodgedDate":{"type":"string","description":"Date the bond was lodged with the scheme (ISO date)","example":"2026-02-10"},"rboReference":{"type":"string","description":"Rental Bonds Online (or scheme) reference number","example":"RBO-1234567"},"scheme":{"type":"string","description":"Bond scheme identifier","example":"rbo","default":"rbo"}},"required":["amountCents","weeksOfRent"]},"UpsertRentScheduleDto":{"type":"object","properties":{"amountCents":{"type":"number","description":"Rent amount in integer cents","example":65000},"frequency":{"type":"string","description":"Rent charge frequency","enum":["WEEKLY","FORTNIGHTLY","MONTHLY"],"example":"WEEKLY"},"anchorDate":{"type":"string","description":"Anchor date the charge cycle is calculated from (ISO date)","example":"2026-02-01"},"nextChargeDate":{"type":"string","description":"Next date rent is due to be charged (ISO date)","example":"2026-02-08"},"nextReviewDate":{"type":"string","description":"Next scheduled rent review date (ISO date)","example":"2026-08-01"},"lastReviewDate":{"type":"string","description":"Date of the last rent review (ISO date)","example":"2025-08-01"},"lastIncreaseDate":{"type":"string","description":"Date rent was last increased (ISO date) — anchors the 12-month rent-increase gate.","example":"2025-08-01"}},"required":["amountCents","frequency","anchorDate","nextChargeDate"]},"CreateRentReviewDto":{"type":"object","properties":{"currentRentCents":{"type":"number","description":"Current rent in integer cents at the time of review","example":65000},"proposedRentCents":{"type":"number","description":"Proposed new rent in integer cents","example":68000},"blendJson":{"type":"object","description":"Snapshot of blend inputs used to derive the proposal (market gap, CPI, tenant history, etc.)","example":{"marketGapBps":450,"cpiBps":380}}},"required":["currentRentCents","proposedRentCents"]},"CreateTenantDto":{"type":"object","properties":{"name":{"type":"string","description":"Tenant full name","example":"Jane Smith"},"email":{"type":"string","description":"Tenant email","example":"jane.smith@example.com"},"phone":{"type":"string","description":"Tenant phone","example":"0400111222"},"emergencyContact":{"type":"string","description":"Emergency contact details (free text)","example":"John Smith — 0400333444"}},"required":["name"]},"UpdateTenantDto":{"type":"object","properties":{"name":{"type":"string","description":"Tenant full name","example":"Jane Smith"},"email":{"type":"string","description":"Tenant email","example":"jane.smith@example.com"},"phone":{"type":"string","description":"Tenant phone","example":"0400111222"},"emergencyContact":{"type":"string","description":"Emergency contact details (free text)","example":"John Smith — 0400333444"}}},"CreateMaintenanceJobDto":{"type":"object","properties":{"title":{"type":"string","description":"Short job title","example":"Leaking tap in kitchen"},"description":{"type":"string","description":"Full description of the issue","example":"Tenant reports a slow drip from the kitchen mixer tap."},"propertyId":{"type":"string","description":"Property this job is for","example":"cm123property"},"tenancyId":{"type":"string","description":"Tenancy this job relates to, if the property is tenanted","example":"cm123tenancy"},"reportedOwnerId":{"type":"string","description":"Which owner reported this, when raisedBy is OWNER and the property has more than one owner on file","example":"cm123owner"},"priority":{"type":"string","description":"Priority (P1 = urgent .. P4 = low)","enum":["P1","P2","P3","P4"],"default":"P3"},"tradeCategory":{"type":"string","description":"Trade category","example":"plumbing"},"raisedBy":{"type":"string","description":"Who raised this job","enum":["TENANT","MANAGER","INSPECTION","OWNER","AGENT","OTHER"],"example":"TENANT"},"isUrgentRepair":{"type":"boolean","description":"Statutory urgent-repair path (NSW): dispatch immediately, never queued behind approval","default":false},"responsibility":{"type":"string","description":"Who is responsible for the cost of this repair","enum":["OWNER","TENANT","UNDETERMINED"],"default":"UNDETERMINED"},"warrantyChecked":{"type":"boolean","description":"Whether a warranty check has been done for this item","default":false},"scheduledDate":{"type":"string","description":"Scheduled date for the work, ISO date/datetime","example":"2026-08-01"},"assignedToUserId":{"type":"string","description":"Managing staff member to assign at creation. Omit or send an empty string for Unassigned. Not validated against org membership here — the same trust boundary as the update path, since the id comes from the org-scoped /user directory."},"notifyTenant":{"type":"boolean","description":"Email the linked tenant that this job was logged. Defaults to true when a tenancy is set. Not a Prisma field — stripped before create.","default":true}},"required":["title","description","propertyId","tradeCategory","raisedBy"]},"UpdateMaintenanceJobDto":{"type":"object","properties":{"title":{"type":"string","description":"Short job title"},"description":{"type":"string","description":"Full description of the issue"},"priority":{"type":"string","description":"Priority (P1 = urgent .. P4 = low)","enum":["P1","P2","P3","P4"]},"tradeCategory":{"type":"string","description":"Trade category","example":"plumbing"},"isUrgentRepair":{"type":"boolean","description":"Statutory urgent-repair path (NSW): dispatch immediately, never queued behind approval"},"responsibility":{"type":"string","description":"Who is responsible for the cost of this repair","enum":["OWNER","TENANT","UNDETERMINED"]},"warrantyChecked":{"type":"boolean","description":"Whether a warranty check has been done for this item"},"notes":{"type":"object","description":"Staff work-order notes (local to OneAgency)"},"tenancyId":{"type":"object","description":"Active tenancy on this job's property. Used when the job was logged without a tenant."},"assignedToUserId":{"type":"object","description":"Staff user assigned to this job"},"scheduledDate":{"type":"object","description":"Scheduled date for the work, ISO date/datetime","example":"2026-08-01"},"completedDate":{"type":"string","description":"Completed date, ISO date/datetime","example":"2026-08-03"},"overrideReason":{"type":"string","description":"Required when changing priority, trade, responsibility, or urgent-repair flag"},"tenantUpdateDraft":{"type":"object","description":"Staff-editable tenant update draft. Not sent until explicitly sent."},"tenantPortalVisible":{"type":"boolean","description":"Whether the linked tenant can see this job in the Tenant Portal. Does not send mail."}}},"UpdateMaintenanceJobStatusDto":{"type":"object","properties":{"status":{"type":"string","description":"New status — validated against the allowed lifecycle transitions","enum":["NEW","TRIAGE","AWAITING_OWNER","QUOTING","APPROVED","SCHEDULED","IN_PROGRESS","COMPLETION_REVIEW","COMPLETED","INVOICED","ON_HOLD","CANCELLED"],"example":"TRIAGE"}},"required":["status"]},"OwnerPathwayDto":{"type":"object","properties":{"action":{"type":"string","enum":["ask","quotes","direct"],"description":"ask = send the owner quotes-vs-direct; quotes/direct = record their reply"},"note":{"type":"string","description":"Optional staff note included in the owner email / audit log"},"subject":{"type":"string","description":"ask only: replaces the email subject (plain text)"},"message":{"type":"string","description":"ask only: replaces the opening message (plain text)"},"details":{"type":"string","description":"ask only: replaces the \"Details\" shown to the owner"}},"required":["action"]},"OwnerQuoteActionDto":{"type":"object","properties":{"action":{"type":"string","enum":["APPROVED","REJECTED","HOLD","MORE"],"description":"Owner action on the quotes staff recorded"},"quoteId":{"type":"string","description":"Quote the owner approved. Required when action is APPROVED."},"note":{"type":"string"}},"required":["action"]},"ReopenQuoteReviewDto":{"type":"object","properties":{"reason":{"type":"string","description":"Why quote review is being reopened. Required because this voids the owner’s previous selection until they choose again."}},"required":["reason"]},"RecordEvidenceUploadedDto":{"type":"object","properties":{"documentIds":{"description":"Document ids returned by the upload-session endpoint for files just uploaded against this job with the reported-photo role","type":"array","items":{"type":"string"}}},"required":["documentIds"]},"EmergencyBypassDto":{"type":"object","properties":{"supplierId":{"type":"string","description":"Tradesperson to assign immediately"},"reason":{"type":"string","description":"Why this is an emergency. Mandatory — it is the only record justifying skipping the owner."},"instructions":{"type":"string","description":"Instructions for the tradesperson"}},"required":["supplierId","reason"]},"JobReasonDto":{"type":"object","properties":{"reason":{"type":"string"}},"required":["reason"]},"ReviewCompletionDto":{"type":"object","properties":{"accept":{"type":"boolean","description":"True to accept the package, false to send it back"},"note":{"type":"string"}},"required":["accept"]},"SendCompletionLinkDto":{"type":"object","properties":{"reminder":{"type":"boolean","description":"Send the shorter chase-up wording rather than the full work order"}}},"RevokeLinksDto":{"type":"object","properties":{"reason":{"type":"string"}}},"MaintenanceEmailEditsDto":{"type":"object","properties":{"subject":{"type":"string","description":"Replaces the subject line"},"intro":{"type":"string","description":"Replaces the opening paragraph. The \"not an authorisation\" sentence is re-attached if an edit drops it."},"issue":{"type":"string","description":"Replaces the Issue section — what is being priced"}}},"MaintenanceQuoteRecipientOverrideDto":{"type":"object","properties":{"supplierId":{"type":"string","description":"The tradesperson this wording is for"},"subject":{"type":"string","description":"Replaces the subject for this tradesperson"},"issue":{"type":"string","description":"Replaces \"What we need priced\" for this tradesperson"},"note":{"type":"string","description":"Note for this tradesperson only - replaces the shared note"}},"required":["supplierId"]},"RequestQuotesDto":{"type":"object","properties":{"supplierIds":{"description":"Suppliers to ask. Staff choose how many — up to four per request.","type":"array","items":{"type":"string"}},"note":{"type":"string","description":"Extra detail included on the request email to each tradesperson"},"edits":{"description":"Staff rewrites of the wording, exactly as approved in the preview","allOf":[{"$ref":"#/components/schemas/MaintenanceEmailEditsDto"}]},"recipientOverrides":{"description":"quote-request only: per-tradesperson wording, applied over the shared note/edits. Blank fields fall back to the shared ones.","type":"array","items":{"$ref":"#/components/schemas/MaintenanceQuoteRecipientOverrideDto"}}},"required":["supplierIds"]},"MaintenanceCommsPreviewDto":{"type":"object","properties":{"action":{"type":"string","description":"Which maintenance email to render","enum":["owner-direction","quote-request","quote-forward","work-order","owner-complete","emergency-notice","tenant-update"]},"note":{"type":"string","description":"Manager note, exactly as it will appear in the email"},"quoteId":{"type":"string","description":"Quote being forwarded — required for quote-forward"},"supplierIds":{"description":"Tradespeople to ask — required for quote-request","type":"array","items":{"type":"string"}},"supplierId":{"type":"string","description":"Tradesperson the work order goes to — required for work-order when the job has none assigned"},"edits":{"description":"Staff rewrites of the wording, applied when rendering","allOf":[{"$ref":"#/components/schemas/MaintenanceEmailEditsDto"}]},"recipientOverrides":{"description":"quote-request only: per-tradesperson wording, applied over the shared note/edits. Blank fields fall back to the shared ones.","type":"array","items":{"$ref":"#/components/schemas/MaintenanceQuoteRecipientOverrideDto"}}},"required":["action"]},"ForwardQuoteDto":{"type":"object","properties":{"note":{"type":"string","description":"Covering note from the property manager"}}},"IssueWorkOrderDto":{"type":"object","properties":{"supplierId":{"type":"string","description":"Supplier to assign if the job does not already have one"},"scheduledDate":{"type":"string","description":"Optional scheduled date, ISO date/datetime"},"message":{"type":"string","description":"Instructions included on the work-order email to the tradesperson"}}},"NotifyCompleteDto":{"type":"object","properties":{"note":{"type":"string","description":"Optional extra note on the owner completion email"}}},"CreateMaintenanceQuoteDto":{"type":"object","properties":{"supplierId":{"type":"string","description":"Supplier providing this quote","example":"cm123supplier"},"amountCents":{"type":"number","description":"Quoted amount, in integer cents","example":45000},"receivedDate":{"type":"string","description":"Date the quote was received, ISO date/datetime (defaults to now)","example":"2026-07-20"},"notes":{"type":"string","description":"Free-text notes about the quote"},"quoteReference":{"type":"string","description":"Supplier quote reference"},"validUntil":{"type":"string","description":"Quote valid until"},"availabilityNotes":{"type":"string","description":"Attendance / availability notes"},"gstInclusive":{"type":"boolean","description":"Whether the amount includes GST"},"documentId":{"type":"string","description":"Linked document id"},"attachmentFileName":{"type":"string","description":"Attached document file name"}},"required":["supplierId","amountCents"]},"UpdateMaintenanceQuoteDto":{"type":"object","properties":{"amountCents":{"type":"number","description":"Quoted amount, in integer cents"},"supplierId":{"type":"string","description":"Supplier providing this quote"},"receivedDate":{"type":"string","description":"Date the quote was received"},"quoteReference":{"type":"object","description":"Supplier quote reference"},"validUntil":{"type":"object","description":"Quote valid until"},"notes":{"type":"object","description":"Scope or notes from the supplier"},"availabilityNotes":{"type":"object","description":"Attendance / availability notes"},"gstInclusive":{"type":"boolean","description":"Whether the amount includes GST"},"documentId":{"type":"object","description":"Linked document id"},"attachmentFileName":{"type":"object","description":"Attached document file name"},"reason":{"type":"string","description":"Reason for a material change (amount, supplier, or withdrawal)"}}},"WithdrawMaintenanceQuoteDto":{"type":"object","properties":{"reason":{"type":"string","description":"Why this quote is withdrawn or expired"},"lifecycle":{"type":"string","description":"Set to expired to mark the quote past its validity date","enum":["WITHDRAWN","EXPIRED"]}}},"SendJobMessageDto":{"type":"object","properties":{"recipient":{"type":"string","enum":["TENANT","OWNER","TRADESPERSON"]},"channel":{"type":"string","enum":["EMAIL","SMS"]},"subject":{"type":"string","description":"Required for email"},"body":{"type":"string"}},"required":["recipient","channel","body"]},"SendTenantUpdateDto":{"type":"object","properties":{"subject":{"type":"string","description":"Replaces the subject line"},"message":{"type":"string","description":"Replaces the message paragraph"}}},"AcceptMaintenanceQuoteDto":{"type":"object","properties":{"scheduledDate":{"type":"string","description":"Scheduled date for the work, ISO date/datetime — supplying this flips status to SCHEDULED instead of APPROVED","example":"2026-08-01"},"replaceReason":{"type":"string","description":"Required only when a different quote is already accepted on this job. Replacing an accepted quote supersedes the previous commercial record, so the reason is kept on the file and the spend approval is re-evaluated.","example":"Supplier withdrew availability; owner agreed to the alternative quote by phone."}}},"RecordMaintenanceInvoiceDto":{"type":"object","properties":{"invoiceReceivedCents":{"type":"number","description":"Invoice amount actually received/billed, in integer cents","example":46500},"tolerancePercent":{"type":"number","description":"Variance tolerance as a whole percentage of the agreed quote cost (default 10)","example":10,"minimum":0,"maximum":100,"default":10}},"required":["invoiceReceivedCents"]},"SupplierTradeCountDto":{"type":"object","properties":{"trade":{"type":"string"},"count":{"type":"number"}},"required":["trade","count"]},"SupplierPortfolioSummaryResponseDto":{"type":"object","properties":{"totalCount":{"type":"number"},"preferredCount":{"type":"number"},"emergencyCount":{"type":"number"},"withOpenJobsCount":{"type":"number"},"complianceDueCount":{"type":"number"},"trades":{"type":"array","items":{"$ref":"#/components/schemas/SupplierTradeCountDto"}}},"required":["totalCount","preferredCount","emergencyCount","withOpenJobsCount","complianceDueCount","trades"]},"CreateSupplierDto":{"type":"object","properties":{"name":{"type":"string","description":"Supplier/business name","example":"ACME Plumbing"},"trade":{"type":"string","description":"Trade","example":"plumbing"},"email":{"type":"string","description":"Contact email","example":"jobs@acmeplumbing.com"},"phone":{"type":"string","description":"Contact phone","example":"+61412345678"},"licenceNumber":{"type":"string","description":"Trade licence number"},"licenceExpiry":{"type":"string","description":"Trade licence expiry, ISO date (watched by Compliance)","example":"2027-06-30"},"insuranceExpiry":{"type":"string","description":"Public liability insurance expiry, ISO date (watched by Compliance)","example":"2027-06-30"},"preferred":{"type":"boolean","description":"Preferred supplier","default":false},"emergencyVendor":{"type":"boolean","description":"After-hours/emergency routing target","default":false}},"required":["name","trade"]},"UpdateSupplierDto":{"type":"object","properties":{"name":{"type":"string","description":"Supplier/business name","example":"ACME Plumbing"},"trade":{"type":"string","description":"Trade","example":"plumbing"},"email":{"type":"string","description":"Contact email","example":"jobs@acmeplumbing.com"},"phone":{"type":"string","description":"Contact phone","example":"+61412345678"},"licenceNumber":{"type":"string","description":"Trade licence number"},"licenceExpiry":{"type":"string","description":"Trade licence expiry, ISO date (watched by Compliance)","example":"2027-06-30"},"insuranceExpiry":{"type":"string","description":"Public liability insurance expiry, ISO date (watched by Compliance)","example":"2027-06-30"},"preferred":{"type":"boolean","description":"Preferred supplier","default":false},"emergencyVendor":{"type":"boolean","description":"After-hours/emergency routing target","default":false}}},"CompleteActionQueueItemDto":{"type":"object","properties":{"note":{"type":"string","description":"What was done in the external system, e.g. \"Booked Riverside Plumbing, PropertyMe job updated\""}}},"CreateInspectionDto":{"type":"object","properties":{"propertyId":{"type":"string","description":"Property ID this inspection is for","example":"clm123abc"},"tenancyId":{"type":"string","description":"Tenancy ID (when the property is currently tenanted)","example":"clm456def"},"type":{"type":"string","description":"Inspection type","enum":["ENTRY","ROUTINE","EXIT"],"example":"ROUTINE"},"scheduledDate":{"type":"string","description":"Scheduled date/time (ISO). Must be at least 7 days from today unless a valid noticeServedDate is supplied (NSW entry notice).","example":"2026-08-01T09:00:00.000Z"},"managerUserId":{"type":"string","description":"User ID of the manager conducting the inspection","example":"clm789ghi"},"noticeId":{"type":"string","description":"Linked statutory Notice ID (e.g. the 7-day entry notice for ENTRY inspections)","example":"clmnotice1"},"noticeServedDate":{"type":"string","description":"Date the entry notice was served (ISO date). Must be at least 7 days before scheduledDate when both are present (NSW entry notice period).","example":"2026-07-24"},"summary":{"type":"string","description":"Free-text summary/notes for the inspection","example":"Routine 12-month inspection"},"dueDate":{"type":"string","description":"When the inspection ought to happen (distinct from the booked visit). Stamped on records materialised from a calculated due item.","example":"2026-09-10"},"draftEntryNotice":{"type":"boolean","description":"true: also draft the auto-sending 7-day entry notice. Defaults to false — inspections is a monitoring workspace and creating a record never queues a tenant notice. Only non-inspections callers (the agent-platform book_inspection action) opt in.","default":false}},"required":["propertyId","type","scheduledDate"]},"UpdateInspectionDto":{"type":"object","properties":{"tenancyId":{"type":"string","description":"Tenancy ID (when the property is currently tenanted)","example":"clm456def"},"scheduledDate":{"type":"string","description":"Scheduled date/time for the inspection (ISO datetime)","example":"2026-08-01T09:00:00.000Z"},"status":{"type":"string","description":"Inspection status","enum":["SCHEDULED","IN_PROGRESS","COMPLETED","REPORT_SENT","OVERDUE"],"example":"IN_PROGRESS"},"completedDate":{"type":"string","description":"Date/time the inspection was completed (ISO datetime)","example":"2026-08-01T10:30:00.000Z"},"managerUserId":{"type":"string","description":"User ID of the manager conducting the inspection","example":"clm789ghi"},"overallConditionRating":{"type":"number","description":"Overall condition rating (1-5), feeds Valuation","example":4,"minimum":1,"maximum":5},"noticeId":{"type":"string","description":"Linked statutory Notice ID (e.g. the 7-day entry notice for ENTRY inspections)","example":"clmnotice1"},"noticeServedDate":{"type":"string","description":"Date the entry notice was served (ISO date). Must be at least 7 days before scheduledDate when both are present (NSW entry notice period).","example":"2026-07-24"},"tenantSigned":{"type":"boolean","description":"Whether the tenant has signed the condition report","example":true},"managerSigned":{"type":"boolean","description":"Whether the manager has signed the condition report","example":true},"summary":{"type":"string","description":"Free-text summary/notes for the inspection","example":"Property in good condition, minor wear in kitchen"},"expectedUpdatedAt":{"type":"string","description":"Optimistic lock: the row's updatedAt as last read. When supplied and stale, the update is refused (409) instead of overwriting a concurrent change.","example":"2026-09-21T02:10:00.000Z"}}},"InspectionWorklistItemDto":{"type":"object","properties":{"propertyId":{"type":"string"},"inspectionId":{"type":"object","nullable":true},"propertyAddress":{"type":"string"},"inspectionType":{"type":"string","enum":["ENTRY","ROUTINE","EXIT"]}},"required":["propertyId","propertyAddress","inspectionType"]},"SaveInspectionWorklistDto":{"type":"object","properties":{"supplierId":{"type":"string"},"windowStart":{"type":"string","description":"Inclusive start of the day or window. Not an appointment time."},"windowEnd":{"type":"string","description":"Inclusive end of the day or window. Not an appointment time."},"note":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/InspectionWorklistItemDto"}}},"required":["supplierId","windowStart","windowEnd","items"]},"ConfirmInspectionFinalisedDto":{"type":"object","properties":{"onDate":{"type":"string","description":"When the report was finalised in Inspection Express (defaults to now).","example":"2026-09-19"},"note":{"type":"string","description":"Optional reference or note, e.g. where the report is filed.","example":"Report filed in Inspection Express."}}},"UpsertInspectionItemDto":{"type":"object","properties":{"id":{"type":"string","description":"Existing item ID (omit to create a new item)","example":"clmitem123"},"name":{"type":"string","description":"Item name","example":"Oven"},"clean":{"type":"boolean","description":"Item is clean","default":true},"working":{"type":"boolean","description":"Item is working","default":true},"undamaged":{"type":"boolean","description":"Item is undamaged","default":true},"conditionRating":{"type":"number","description":"Item condition rating (1-5)","example":4,"minimum":1,"maximum":5},"comment":{"type":"string","description":"Comment about this item","example":"Light scratches on the door"}},"required":["name"]},"UpsertInspectionAreaDto":{"type":"object","properties":{"id":{"type":"string","description":"Existing area ID (omit to create a new area)","example":"clmarea123"},"name":{"type":"string","description":"Area name","example":"Kitchen"},"conditionRating":{"type":"number","description":"Area condition rating (1-5)","example":4,"minimum":1,"maximum":5},"notes":{"type":"string","description":"Notes about this area","example":"Bench tops resealed last inspection"},"photoDocumentIds":{"description":"DMS document IDs for photos of this area","example":["doc_abc123","doc_def456"],"type":"array","items":{"type":"string"}},"items":{"description":"Items within this area","type":"array","items":{"$ref":"#/components/schemas/UpsertInspectionItemDto"}}},"required":["name"]},"UpsertInspectionAreasDto":{"type":"object","properties":{"areas":{"description":"Full set of areas for this inspection. Areas/items with an id are updated in place; areas/items without an id are created; existing areas/items not present in this array are removed (bulk-upsert / replace).","type":"array","items":{"$ref":"#/components/schemas/UpsertInspectionAreaDto"}}},"required":["areas"]},"CreateReceiptDto":{"type":"object","properties":{"tenancyId":{"type":"string","description":"The tenancy this receipt is recorded against","example":"cm123tenancy"},"amountCents":{"type":"number","description":"Amount received, in integer cents","example":65000},"method":{"type":"string","description":"Payment method (e.g. bank_transfer, cash, card)","example":"bank_transfer"},"reference":{"type":"string","description":"External reference for this receipt (e.g. bank reference)","example":"REF-20260716-001"},"effectiveDate":{"type":"string","description":"The date the receipt is effective from (ISO date)","example":"2026-07-16"},"description":{"type":"string","description":"Optional description override (defaults to \"Rent receipt\")","example":"Rent receipt — week ending 20 Jul"}},"required":["tenancyId","amountCents","effectiveDate"]},"RentLedgerEntryResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Ledger entry ID"},"orgId":{"type":"string","description":"Organization ID"},"accountId":{"type":"string","description":"Rent ledger account ID this entry belongs to"},"sequence":{"type":"number","description":"Monotonic sequence, unique per account"},"effectiveDate":{"format":"date-time","type":"string","description":"Date this entry is effective from"},"type":{"type":"string","description":"Entry type","enum":["RENT_CHARGE","RENT_RECEIPT","ADJUSTMENT","CREDIT","FEE","WATER"]},"source":{"type":"string","description":"Entry source","enum":["SYSTEM_ACCRUAL","STAFF_RECEIPT","ADJUSTMENT"]},"description":{"type":"string","description":"Human-readable description"},"chargeCents":{"type":"number","description":"Debit — rent/fee owed, in integer cents"},"receiptCents":{"type":"number","description":"Credit — rent/fee received, in integer cents"},"balanceAfterCents":{"type":"number","description":"Running account balance immediately after this entry"},"method":{"type":"object","description":"Payment method, if applicable","nullable":true},"reference":{"type":"object","description":"External reference, if applicable","nullable":true},"createdByUserId":{"type":"object","description":"User who recorded this entry, if staff-entered","nullable":true},"agentRunId":{"type":"object","description":"Agent run that produced this entry, if any","nullable":true},"createdAt":{"format":"date-time","type":"string","description":"Created at"}},"required":["id","orgId","accountId","sequence","effectiveDate","type","source","description","chargeCents","receiptCents","balanceAfterCents","createdAt"]},"RentLedgerAccountResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Rent ledger account ID"},"orgId":{"type":"string","description":"Organization ID"},"tenancyId":{"type":"string","description":"Tenancy ID"},"currentBalanceCents":{"type":"number","description":"Running balance in integer cents (+ = paid ahead, - = arrears)","example":-70000},"paidToDate":{"type":"object","description":"Date the tenancy is paid up to, given the current balance and rent schedule","nullable":true},"lastSequence":{"type":"number","description":"Monotonic sequence of the last entry appended"},"lastEntryAt":{"type":"object","description":"When the last entry was appended","nullable":true},"createdAt":{"format":"date-time","type":"string","description":"Created at"},"updatedAt":{"format":"date-time","type":"string","description":"Updated at"}},"required":["id","orgId","tenancyId","currentBalanceCents","lastSequence","createdAt","updatedAt"]},"LedgerEntryResultResponseDto":{"type":"object","properties":{"entry":{"$ref":"#/components/schemas/RentLedgerEntryResponseDto"},"account":{"$ref":"#/components/schemas/RentLedgerAccountResponseDto"}},"required":["entry","account"]},"CreateAdjustmentDto":{"type":"object","properties":{"tenancyId":{"type":"string","description":"The tenancy this adjustment is recorded against","example":"cm123tenancy"},"amountCents":{"type":"number","description":"Signed adjustment amount in integer cents. Positive credits the account (in the tenant's favour); negative debits it (increases arrears).","example":-5000},"reason":{"type":"string","description":"Reason for the adjustment — required for every correction","example":"Reversing duplicate receipt posted 14 Jul in error"},"effectiveDate":{"type":"string","description":"The date the adjustment is effective from (ISO date). Defaults to today.","example":"2026-07-16"}},"required":["tenancyId","amountCents","reason"]},"ArrearsEntryResponseDto":{"type":"object","properties":{"tenancyId":{"type":"string","description":"Tenancy ID"},"tenancyRef":{"type":"string","description":"Tenancy human ref"},"propertyId":{"type":"string","description":"Property ID"},"propertyRef":{"type":"string","description":"Property human ref"},"propertyLine1":{"type":"string","description":"Property address line 1"},"propertySuburb":{"type":"string","description":"Property suburb"},"currentBalanceCents":{"type":"number","description":"Running balance in integer cents (always negative here)"},"paidToDate":{"type":"object","description":"Date the tenancy is paid up to","nullable":true},"daysBehind":{"type":"number","description":"today - paidToDate, in whole days"},"bucket":{"type":"string","description":"Arrears bucket","enum":["1-7","8-14","15+"]}},"required":["tenancyId","tenancyRef","propertyId","propertyRef","propertyLine1","propertySuburb","currentBalanceCents","daysBehind","bucket"]},"LedgerEntriesPageDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RentLedgerEntryResponseDto"}},"meta":{"type":"object","properties":{"page":{"type":"number","example":1},"limit":{"type":"number","example":20},"total":{"type":"number","example":45},"totalPages":{"type":"number","example":3},"hasNext":{"type":"boolean","example":true},"hasPrev":{"type":"boolean","example":false}}}},"required":["data","meta"]},"TenancyLedgerResponseDto":{"type":"object","properties":{"account":{"description":"Null until the first entry has been appended","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/RentLedgerAccountResponseDto"}]},"entries":{"$ref":"#/components/schemas/LedgerEntriesPageDto"}},"required":["entries"]},"CreateValuationDto":{"type":"object","properties":{"propertyId":{"type":"string","description":"Property this valuation is for","example":"cm123property"},"agentRunId":{"type":"string","description":"Agent run that produced this valuation, if any","example":"cm123agentrun"},"avmMidCents":{"type":"number","description":"AVM (automated valuation model) midpoint sale value, in cents","example":85000000},"rentBandLowCents":{"type":"number","description":"Bottom of the recommended weekly rent band, in cents","example":65000},"rentBandMidCents":{"type":"number","description":"Midpoint of the recommended weekly rent band, in cents","example":70000},"rentBandHighCents":{"type":"number","description":"Top of the recommended weekly rent band, in cents","example":75000},"confidence":{"type":"number","description":"Confidence score for this valuation (0-100)","example":82,"minimum":0,"maximum":100},"conditionRatingUsed":{"type":"number","description":"Condition rating (1-5) used as an input, usually from the latest inspection","example":4,"minimum":1,"maximum":5},"compsJson":{"description":"Comparable sales/lettings evidence pack — stored as given, e.g. [{address,date,priceCents,beds,distanceKm}]","type":"array","items":{"type":"object"}},"suburbSnapshotJson":{"type":"object","description":"Snapshot of the suburb stats used as inputs — stored as given"}},"required":["propertyId","rentBandLowCents","rentBandMidCents","rentBandHighCents","confidence"]},"UpsertSuburbStatsItemDto":{"type":"object","properties":{"suburb":{"type":"string","description":"Suburb name","example":"Parramatta"},"state":{"type":"string","description":"State/territory","example":"NSW","default":"NSW"},"propertyKind":{"type":"string","description":"Property kind — separate markets","enum":["house","unit"],"example":"house"},"asOf":{"type":"string","description":"As-of date for this stats snapshot (ISO date)","example":"2026-07-01"},"medianValueCents":{"type":"number","description":"Median sale value, in cents"},"capitalGrowth12mBps":{"type":"number","description":"12-month capital growth, in basis points"},"medianAskingRentCents":{"type":"number","description":"Median asking weekly rent, in cents — anchor for the benchmark"},"rentGrowth12mBps":{"type":"number","description":"12-month rent growth, in basis points"},"vacancyRateBps":{"type":"number","description":"Vacancy rate, in basis points"},"daysOnMarketRental":{"type":"number","description":"Median days on market for rentals"},"grossYieldBps":{"type":"number","description":"Gross rental yield, in basis points"}},"required":["suburb","propertyKind","asOf"]},"UpsertSuburbStatsDto":{"type":"object","properties":{"items":{"description":"Suburb stats rows to upsert, keyed on [suburb, state, propertyKind, asOf]","minItems":1,"type":"array","items":{"$ref":"#/components/schemas/UpsertSuburbStatsItemDto"}}},"required":["items"]},"CreateAssistantConversationDto":{"type":"object","properties":{"title":{"type":"string"}}},"PatchAssistantConversationDto":{"type":"object","properties":{"pinned":{"type":"boolean"},"title":{"type":"string"}}},"AssistantChatMessageDto":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant"]},"text":{"type":"string"}},"required":["role","text"]},"AppendAssistantMessagesDto":{"type":"object","properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/AssistantChatMessageDto"}}},"required":["messages"]},"AssistantKnobsDto":{"type":"object","properties":{"monthlyTokenBudget":{"type":"number"},"retentionDays":{"type":"number"}}},"PatchAssistantSettingsDto":{"type":"object","properties":{"enabled":{"type":"boolean"},"tools":{"type":"object"},"knobs":{"$ref":"#/components/schemas/AssistantKnobsDto"},"promptOverride":{"type":"object"}}},"DashboardOpsSignalsResponseDto":{"type":"object","properties":{"pendingApprovals":{"type":"number"},"urgentRepairs":{"type":"number"},"inspectionsDue":{"type":"number"},"arrears":{"type":"number"},"underRented":{"type":"number"}},"required":["pendingApprovals","urgentRepairs","inspectionsDue","arrears","underRented"]},"DashboardScopeDto":{"type":"object","properties":{"managerUserId":{"type":"object","nullable":true},"managerName":{"type":"object","nullable":true},"canViewAllManagers":{"type":"boolean"},"generatedAt":{"type":"string"}},"required":["canViewAllManagers","generatedAt"]},"DashboardOverviewResponseDto":{"type":"object","properties":{"scope":{"$ref":"#/components/schemas/DashboardScopeDto"},"today":{"type":"string"},"month":{"type":"string"},"lastSyncAt":{"type":"object","nullable":true},"access":{"type":"object","description":"Which sections the caller may read"},"snapshot":{"type":"object","nullable":true},"approvals":{"type":"object","nullable":true},"maintenance":{"type":"object","nullable":true},"inspections":{"type":"object","nullable":true},"rentReviews":{"type":"object","nullable":true},"reporting":{"type":"object","nullable":true}},"required":["scope","today","month","access"]},"DashboardAttentionResponseDto":{"type":"object","properties":{"scope":{"$ref":"#/components/schemas/DashboardScopeDto"},"items":{"type":"array","items":{"type":"array"}},"page":{"type":"number"},"pageSize":{"type":"number"},"total":{"type":"number"},"counts":{"type":"object"}},"required":["scope","items","page","pageSize","total","counts"]},"DashboardAgendaResponseDto":{"type":"object","properties":{"scope":{"$ref":"#/components/schemas/DashboardScopeDto"},"window":{"type":"string","enum":["today","week"]},"from":{"type":"string"},"to":{"type":"string"},"days":{"type":"array","items":{"type":"array"}},"totals":{"type":"object"},"hrefs":{"type":"object"}},"required":["scope","window","from","to","days","totals","hrefs"]},"DashboardUpdatesResponseDto":{"type":"object","properties":{"scope":{"$ref":"#/components/schemas/DashboardScopeDto"},"items":{"type":"array","items":{"type":"array"}}},"required":["scope","items"]},"DashboardTrendsResponseDto":{"type":"object","properties":{"scope":{"$ref":"#/components/schemas/DashboardScopeDto"},"rangeKey":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"granularity":{"type":"string","enum":["day","week","month"]},"points":{"type":"array","items":{"type":"array"}},"totals":{"type":"object"},"rentSeriesAvailable":{"type":"boolean"},"rentUnavailableReason":{"type":"string"},"occupancySeriesAvailable":{"type":"boolean"},"occupancyUnavailableReason":{"type":"string"}},"required":["scope","rangeKey","from","to","granularity","points","totals","rentSeriesAvailable","occupancySeriesAvailable"]},"SetPropertyLastIncreaseDto":{"type":"object","properties":{"lastIncreaseDate":{"type":"string","example":"2025-09-22"},"reason":{"type":"string"}},"required":["lastIncreaseDate"]},"RentReviewWeeklyWordingDto":{"type":"object","properties":{"subject":{"type":"object","description":"Subject. The week-ending date is always added."},"greeting":{"type":"object","description":"Greeting line, e.g. \"Hello team,\"."},"intro":{"type":"object","description":"Opening text. \"{period}\" becomes the reporting period."},"closing":{"type":"object","description":"Extra paragraph after the lists."}}},"RentReviewWeeklySendDto":{"type":"object","properties":{"mode":{"type":"string","enum":["now","test"],"description":"\"now\" sends to the configured recipients; \"test\" sends only to you and does not count as the weekly send."},"confirmResend":{"type":"boolean","description":"Required to send again when this cycle already has a sent or partly sent report."}},"required":["mode"]},"RentReviewWeeklySettingsDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Automatic weekly sending. Turning it on requires a day, time and at least one recipient."},"dayOfWeek":{"type":"object","description":"0 = Sunday … 6 = Saturday. Null clears it."},"hour":{"type":"object","description":"Hour 0–23 in Australia/Sydney. Null clears it."},"recipients":{"description":"Email addresses. An empty list clears them.","type":"array","items":{"type":"string"}}},"required":["enabled"]},"RentReviewEmailFieldsDto":{"type":"object","properties":{"newRentCents":{"type":"object","description":"New rent in cents. Null clears it."},"effectiveDate":{"type":"object","example":"2026-12-01"},"responseByDate":{"type":"object","example":"2026-10-01"},"includeLease":{"type":"boolean"},"renewalTermMonths":{"type":"object","description":"0 = periodic, otherwise months."},"note":{"type":"object"}}},"RentReviewEmailSendDto":{"type":"object","properties":{"newRentCents":{"type":"object","description":"New rent in cents. Null clears it."},"effectiveDate":{"type":"object","example":"2026-12-01"},"responseByDate":{"type":"object","example":"2026-10-01"},"includeLease":{"type":"boolean"},"renewalTermMonths":{"type":"object","description":"0 = periodic, otherwise months."},"note":{"type":"object"},"version":{"type":"number","description":"Case version the staff member was looking at."}}},"RentReviewActionDto":{"type":"object","properties":{"action":{"type":"string","enum":["assign","setLastIncrease","startReview","acceptRecommendation","adjustRecommendation","rejectRecommendation","markAwaitingOwner","recordOwnerDecision","markPropertyMeAction","markWaitingForPropertyMe","complete","reopen"]},"version":{"type":"number"},"reason":{"type":"string"},"proposedRentCents":{"type":"number"},"approvedRentCents":{"type":"number"},"decision":{"type":"string","enum":["approved","declined","no_increase"]},"assigneeUserId":{"type":"string"},"contactMethod":{"type":"string"},"contactedOn":{"type":"string"},"notes":{"type":"string"},"recommendationShared":{"type":"boolean"},"lastIncreaseDate":{"type":"string"}},"required":["action"]}}},"security":[{"bearer-auth":[],"x-org-id":[]}]}