swagger: "2.0" info: version: 0.4.0 title: "members" description: "Membership Microservice" termsOfService: "https://salesforcedevops.net/terms/" contact: email: "vern@salesforcedevops.net" license: name: "Proprietary - Copyright (c) 2018-2024 by Vernon Keenan" securityDefinitions: ApiKeyAuth: type: "apiKey" in: "header" name: "X-API-Key" kvSessionCookie: name: Cookie in: header type: apiKey description: "JWT session cookie passed as 'Cookie: kvSession='. HttpOnly, Secure, SameSite=None, Domain=.keenanvision.net" schemes: - "https" basePath: "/vk/members/v1" host: "gw.tnxs.net" consumes: - "application/json" produces: - "application/json" parameters: id: name: id in: query type: string format: uuid brandId: name: brandId in: query type: string format: uuid serviceId: name: serviceId in: query type: string format: uuid planId: name: planId in: query type: string format: uuid tenantId: name: tenantId in: query type: string format: uuid description: Requested tenant; Members validates the session user membership. userId: name: userId in: query type: string format: uuid description: Optional user scope; must be the actor or authorized by tenant role. status: name: status in: query type: string effectiveAt: name: effectiveAt in: query type: string format: date-time description: UTC evaluation instant; defaults to the server's current instant. clientType: name: clientType in: query type: string enum: [mcp, api] scope: name: scope in: query type: string includeInactive: name: includeInactive in: query type: boolean default: false description: Includes revoked or expired metadata when authorized. membershipAccessLevel: name: accessLevel in: query type: string enum: [owner, manager, member, read_only] membershipTenantId: name: tenantId in: query type: string minLength: 1 maxLength: 36 description: Tenant identifier; legacy Members tenant IDs are not all UUID formatted. membershipStatus: name: status in: query type: string enum: [active, suspended, revoked] membershipEmail: name: email in: query type: string format: email description: Exact normalized email filter; result scope remains actor-derived. requestId: name: X-Request-ID in: header type: string maxLength: 120 description: Optional bounded correlation identifier stored with membership audit events. limit: name: limit in: query type: integer format: int64 minimum: 1 maximum: 1000 default: 100 offset: name: offset in: query type: integer format: int64 minimum: 0 default: 0 Auth0UserIdHeader: description: Auth0 User Id in: header name: X-Auth0-UserId required: false type: string AttendeeRequest: description: An array of new Attendee records in: body name: attendeeRequest required: true schema: $ref: "#/definitions/AttendeeRequest" CourseLessonRequest: description: An array of new CourseLesson records in: body name: courselessonRequest required: true schema: $ref: "#/definitions/CourseLessonRequest" clusterIdQuery: description: Record Id of a Cluster in: query name: clusterId required: false type: string clusterTenantId: description: Tenant that owns the Cluster. Members verifies the active human membership and never accepts TenantID from the body. in: query name: tenantId required: true type: string minLength: 1 maxLength: 36 transactionIdQuery: description: Record Id of a governed Transaction in: query name: transactionId required: false type: string format: uuid transactionTenantId: description: Tenant that owns the Transaction. Members verifies the active human membership and never accepts TenantID from the body. in: query name: tenantId required: true type: string format: uuid ClusterRequest: description: Exactly one governed Cluster record in: body name: ClusterRequest required: true schema: $ref: "#/definitions/ClusterRequest" CourseRequest: description: An array of new Course records in: body name: courseRequest required: true schema: $ref: "#/definitions/CourseRequest" CourseSectionRequest: description: An array of new CourseSection records in: body name: coursesectionRequest required: true schema: $ref: "#/definitions/CourseSectionRequest" OutgoingEmailMessageRequest: description: An array of new Outgoing Email Message records in: body name: OutgoingEmailMessageRequest required: true schema: $ref: "#/definitions/OutgoingEmailMessageRequest" EnrollmentRequest: description: An array of new Enrollment records in: body name: enrollmentRequest required: true schema: $ref: "#/definitions/EnrollmentRequest" EventRequest: description: An array of new Event records in: body name: eventRequest required: true schema: $ref: "#/definitions/EventRequest" EventCategoryRequest: description: An array of new Event records in: body name: eventCategoryRequest required: true schema: $ref: "#/definitions/EventCategoryRequest" TrackRequest: description: Exactly one governed Track record in: body name: trackRequest required: true schema: $ref: "#/definitions/TrackRequest" TrackEventRequest: description: Exactly one governed Track-to-Event association in: body name: trackEventRequest required: true schema: $ref: "#/definitions/TrackEventRequest" TrackTopicRequest: description: Exactly one governed Track-to-Topic association in: body name: trackTopicRequest required: true schema: $ref: "#/definitions/TrackTopicRequest" TrackUserRequest: description: Exactly one governed Track-to-User association in: body name: trackUserRequest required: true schema: $ref: "#/definitions/TrackUserRequest" FavoriteRequest: description: An array of new Favorite records in: body name: favoriteRequest required: true schema: $ref: "#/definitions/FavoriteRequest" InvoiceRequest: description: An array of new Invoice records in: body name: invoiceRequest required: true schema: $ref: "#/definitions/InvoiceRequest" LessonProgressRequest: description: An array of new LessonProgress records in: body name: lessonprogressRequest required: true schema: $ref: "#/definitions/LessonProgressRequest" OrderRequest: description: An array of new Order records in: body name: orderRequest required: true schema: $ref: "#/definitions/OrderRequest" PaymentMethodRequest: description: An array of new PaymentMethod records in: body name: paymentMethodRequest required: true schema: $ref: "#/definitions/PaymentMethodRequest" PromptRequest: description: An array of new Prompt records in: body name: promptRequest required: true schema: $ref: "#/definitions/PromptRequest" PromptCategoryRequest: description: An array of PromptCategory objects name: promptCategoryRequest required: true in: body schema: $ref: "#/definitions/PromptCategoryRequest" PromptTagRequest: description: An array of PromptTag objects name: promptTagRequest required: true in: body schema: $ref: "#/definitions/PromptTagRequest" PromptAnswerRequest: description: An array of PromptAnswer objects name: promptAnswerRequest required: true in: body schema: $ref: "#/definitions/PromptAnswerRequest" ResearchProjectCompanyRequest: description: An array of new ResearchProjectCompany records in: body name: researchProjectCompanyRequest required: true schema: $ref: "#/definitions/ResearchProjectCompanyRequest" researchProjectProductRequest: description: An array of new ResearchProjectProduct records in: body name: researchProjectProductRequest required: true schema: $ref: "#/definitions/ResearchProjectProductRequest" ResearchProjectServiceRequest: description: An array of new ResearchProjectService records in: body name: researchProjectServiceRequest required: true schema: $ref: "#/definitions/ResearchProjectServiceRequest" ResearchProjectDocumentRequest: description: An array of new ResearchProjectDocument records in: body name: researchProjectDocumentRequest required: true schema: $ref: "#/definitions/ResearchProjectDocumentRequest" ResearchProjectRequest: description: An array of new ResearchProject records in: body name: researchProjectRequest required: true schema: $ref: "#/definitions/ResearchProjectRequest" ResearchProjectTopicRequest: description: An array of new ResearchProjectTopic records in: body name: researchProjectTopicRequest required: true schema: $ref: "#/definitions/ResearchProjectTopicRequest" templateIdQuery: description: Template ID in: query name: templateId type: string TemplateRequest: description: An array of Template records in: body name: TemplateRequest required: true schema: $ref: "#/definitions/TemplateRequest" EmailMessageRequest: description: An array of Email Message records in: body name: EmailMessageRequest required: true schema: $ref: "#/definitions/EmailMessageRequest" TenantRequest: description: An array of Tenant records in: body name: TenantRequest required: true schema: $ref: "#/definitions/TenantRequest" TicketRequest: description: An array of new Ticket records in: body name: ticketRequest required: true schema: $ref: "#/definitions/TicketRequest" TransactionRequest: description: An array of new Transaction records in: body name: transactionRequest required: true schema: $ref: "#/definitions/TransactionRequest" UserRequest: description: An array of User records in: body name: UserRequest required: true schema: $ref: "#/definitions/UserRequest" OnboardRequest: description: Self-service onboarding request (single user) in: body name: onboardRequest required: true schema: $ref: "#/definitions/OnboardRequest" activeQuery: description: Retrieve active records only? in: query name: active required: false type: boolean auth0UserIdQuery: description: Deprecated external identity subject lookup. Password-verifier-shaped values are always rejected. in: query name: auth0UserId required: false type: string identityProviderQuery: description: Normalized external identity provider used together with identitySubject. in: query name: identityProvider required: false type: string minLength: 1 maxLength: 64 recoveryClientIP: description: Original network client IP asserted by the authenticated KV ID server; used only to derive a keyed throttle bucket and never stored raw. in: header name: X-KV-Client-IP required: false type: string maxLength: 64 identitySubjectQuery: description: External provider subject used together with identityProvider. in: query name: identitySubject required: false type: string minLength: 1 maxLength: 255 userIdQuery: description: Internal User ID in: query name: userId required: false type: string userIdQueryRequired: description: Internal User ID in: query name: userId required: true type: string contactIdQuery: description: Internal Contact ID (links to Account) in: query name: contactId required: false type: string databaseIdQuery: description: Record ID of sanitized Database metadata in: query name: databaseId type: string format: uuid required: false databaseTenantId: description: Tenant that owns the Database metadata. Members verifies active human membership and never returns DSN or provisioning credentials. in: query name: tenantId required: true type: string format: uuid databaseRequest: description: An array of Database records in: body name: DatabaseRequest required: true schema: $ref: "#/definitions/DatabaseRequest" documentRequest: description: An array of Document records in: body name: DocumentRequest required: true schema: $ref: "#/definitions/DocumentRequest" folderRequest: description: An array of Folder records in: body name: FolderRequest required: true schema: $ref: "#/definitions/FolderRequest" documentParameterRequest: description: An array of DocumentParameter records in: body name: DocumentParameterRequest required: true schema: $ref: "#/definitions/DocumentParameterRequest" emailMessageIdQuery: description: Email Message ID in: query name: emailMessageId type: string emailQuery: description: Email address in: query name: email required: false type: string idQuery: description: Unique Record ID in: query name: id required: false type: string nameQuery: description: Name of the object in: query name: name required: false type: string objectTypeQuery: description: Object Type Name in: query name: objectType type: string isMasterQuery: description: Is Master Template? in: query name: isMaster type: boolean limitQuery: description: How many objects to return at one time format: int64 in: query name: limit required: false type: integer offsetQuery: description: How many objects to skip? format: int64 in: query name: offset required: false type: integer responses: AccessForbidden: description: Access forbidden, account lacks access headers: Access-Control-Allow-Origin: type: string x-nullable: true schema: $ref: "../../lib/swagger/defs/error.yaml#/Error" AttendeeResponse: description: Attendee Response Object schema: $ref: "#/definitions/AttendeeResponse" ClusterResponse: description: Response with Cluster objects schema: $ref: "#/definitions/ClusterResponse" CourseLessonResponse: description: CourseLesson Response Object schema: $ref: "#/definitions/CourseLessonResponse" CourseResponse: description: Course Response Object schema: $ref: "#/definitions/CourseResponse" CourseSectionResponse: description: CourseSection Response Object schema: $ref: "#/definitions/CourseSectionResponse" Conflict: description: The supplied LastModifiedDate is stale; reload the record before retrying. schema: $ref: "../../lib/swagger/defs/error.yaml#/Error" DatabaseResponse: description: Response with Database objects schema: $ref: "#/definitions/DatabaseResponse" DatabaseMetadataResponse: description: Response with tenant-bound, credential-free Database metadata schema: $ref: "#/definitions/DatabaseMetadataResponse" DocumentResponse: description: Document Response Object schema: $ref: "#/definitions/DocumentResponse" FolderResponse: description: Folder Response Object schema: $ref: "#/definitions/FolderResponse" DocumentParameterResponse: description: DocumentParameter Response Object schema: $ref: "#/definitions/DocumentParameterResponse" EmailMessagesResponse: description: "Array of Email Messages" schema: $ref: "#/definitions/EmailMessagesResponse" OutgoingEmailMessagesResponse: description: "Array of Outgoing Email Messages" schema: $ref: "#/definitions/OutgoingEmailMessagesResponse" EnrollmentResponse: description: Enrollment Response Object schema: $ref: "#/definitions/EnrollmentResponse" EventResponse: description: Event Response Object schema: $ref: "#/definitions/EventResponse" EventCategoryResponse: description: Event Response Object schema: $ref: "#/definitions/EventCategoryResponse" TrackResponse: description: Governed Track response schema: $ref: "#/definitions/TrackResponse" TrackEventResponse: description: Governed Track-to-Event association response schema: $ref: "#/definitions/TrackEventResponse" TrackTopicResponse: description: Governed Track-to-Topic association response schema: $ref: "#/definitions/TrackTopicResponse" TrackUserResponse: description: Governed Track-to-User association response schema: $ref: "#/definitions/TrackUserResponse" FavoriteResponse: description: Favorite Response Object schema: $ref: "#/definitions/FavoriteResponse" InvoiceResponse: description: Invoice Response Object schema: $ref: "#/definitions/InvoiceResponse" IssuedCertificateResponse: description: IssuedCertificate Response Object schema: $ref: "#/definitions/IssuedCertificateResponse" LessonProgressResponse: description: LessonProgress Response Object schema: $ref: "#/definitions/LessonProgressResponse" NotFound: description: Resource was not found schema: $ref: "../../lib/swagger/defs/error.yaml#/Error" OrderResponse: description: Order Response Object schema: $ref: "#/definitions/OrderResponse" PaymentMethodResponse: description: PaymentMethod Response Object schema: $ref: "#/definitions/PaymentMethodResponse" PromptResponse: description: Response with Prompt objects schema: $ref: "#/definitions/PromptResponse" PromptCategoryResponse: description: Response with PromptCategory objects schema: $ref: "#/definitions/PromptCategoryResponse" PromptAnswerResponse: description: Response with PromptAnswer objects schema: $ref: "#/definitions/PromptAnswerResponse" PromptTagResponse: description: Response with PromptTag objects schema: $ref: "#/definitions/PromptTagResponse" ResearchProjectCompanyResponse: description: ResearchProjectCompany Response Object schema: $ref: "#/definitions/ResearchProjectCompanyResponse" ResearchProjectDocumentResponse: description: ResearchProjectDocument Response Object schema: $ref: "#/definitions/ResearchProjectDocumentResponse" ResearchProjectProductResponse: description: ResearchProjectProduct Response Object schema: $ref: "#/definitions/ResearchProjectProductResponse" ResearchProjectServiceResponse: description: ResearchProjectService Response Object schema: $ref: "#/definitions/ResearchProjectServiceResponse" ResearchProjectResponse: description: ResearchProject Response Object schema: $ref: "#/definitions/ResearchProjectResponse" ResearchProjectTopicResponse: description: ResearchProjectTopic Response Object schema: $ref: "#/definitions/ResearchProjectTopicResponse" ServerError: description: Server Internal Error schema: $ref: "../../lib/swagger/defs/error.yaml#/Error" TenantResponse: description: Response with Tenant objects schema: $ref: "#/definitions/TenantResponse" TemplateResponse: description: Response with Template objects schema: $ref: "#/definitions/TemplateResponse" TicketResponse: description: Ticket Response Object schema: $ref: "#/definitions/TicketResponse" TransactionResponse: description: Transaction Response Object schema: $ref: "#/definitions/TransactionResponse" Unauthorized: description: Access Unauthorized, invalid API-KEY was used schema: $ref: "../../lib/swagger/defs/error.yaml#/Error" UnprocessableEntity: description: Unprocessable Entity, likely a bad parameter schema: $ref: "../../lib/swagger/defs/error.yaml#/Error" UserResponse: description: Response with User objects schema: $ref: "#/definitions/UserResponse" paths: /brands: get: operationId: getBrands tags: [PortalCatalog] summary: List customer-facing brands description: Global estate-owned catalog read. Requires members:brand:read and an active human session. parameters: - $ref: "#/parameters/id" - $ref: "#/parameters/status" - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" responses: 200: {description: Brand records, schema: {$ref: "#/definitions/BrandResponse"}} 400: {description: Invalid brand filter} 401: {description: Missing or invalid server or session credential} 403: {description: Actor is not authorized for the requested scope} 500: {description: Server error} security: &portalSecurity - ApiKeyAuth: [] kvSessionCookie: [] post: operationId: postBrands tags: [PortalCatalog] summary: Create brands description: Global estate-owned catalog create. Requires members:brand:create and a tenant-independent Administrator/Admin human role. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/BrandRequest"} responses: 200: {description: Created brands, schema: {$ref: "#/definitions/BrandResponse"}} 400: {description: Invalid lifecycle or catalog data} 401: {description: Missing or invalid server or session credential} 403: {description: Actor lacks catalog-management authority} 500: {description: Server error} security: *portalSecurity put: operationId: putBrands tags: [PortalCatalog] summary: Update brands without deleting history description: Full replacement using id and lastModifiedDate as a compare-and-swap token. Requires members:brand:update and a tenant-independent Administrator/Admin human role. Use retired status instead of deletion. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/BrandRequest"} responses: 200: {description: Updated brands, schema: {$ref: "#/definitions/BrandResponse"}} 400: {description: Invalid lifecycle or catalog data} 401: {description: Missing or invalid server or session credential} 403: {description: Actor lacks catalog-management authority} 409: {description: lastModifiedDate is stale; reload before retrying} 500: {description: Server error} security: *portalSecurity /services: get: operationId: getServices tags: [PortalCatalog] summary: List commercial member-facing capabilities description: Global estate-owned catalog read. Requires members:service:read and an active human session. parameters: - $ref: "#/parameters/id" - $ref: "#/parameters/status" - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" responses: 200: {description: Service records, schema: {$ref: "#/definitions/ServiceResponse"}} 400: {description: Invalid service filter} 401: {description: Missing or invalid server or session credential} 403: {description: Actor is not authorized for the requested scope} 500: {description: Server error} security: *portalSecurity post: operationId: postServices tags: [PortalCatalog] summary: Create commercial services description: Global estate-owned catalog create. Requires members:service:create and a tenant-independent Administrator/Admin human role. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/ServiceRequest"} responses: 200: {description: Created services, schema: {$ref: "#/definitions/ServiceResponse"}} 400: {description: Invalid service data} 401: {description: Missing or invalid server or session credential} 403: {description: Actor lacks catalog-management authority} 500: {description: Server error} security: *portalSecurity put: operationId: putServices tags: [PortalCatalog] summary: Update commercial services without deleting history description: Full replacement using id and lastModifiedDate as a compare-and-swap token. Requires members:service:update and a tenant-independent Administrator/Admin human role. Use retired status instead of deletion. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/ServiceRequest"} responses: 200: {description: Updated services, schema: {$ref: "#/definitions/ServiceResponse"}} 400: {description: Invalid service data} 401: {description: Missing or invalid server or session credential} 403: {description: Actor lacks catalog-management authority} 409: {description: lastModifiedDate is stale; reload before retrying} 500: {description: Server error} security: *portalSecurity /servicescopes: get: operationId: getServiceScopes tags: [PortalCatalog] summary: List controlled client scopes description: Global estate-owned catalog read. Requires members:service-scope:read and an active human session. parameters: - $ref: "#/parameters/id" - $ref: "#/parameters/serviceId" - $ref: "#/parameters/status" - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" responses: 200: {description: Service scope records, schema: {$ref: "#/definitions/ServiceScopeResponse"}} 400: {description: Invalid service-scope filter} 401: {description: Missing or invalid server or session credential} 403: {description: Actor is not authorized for the requested scope} 500: {description: Server error} security: *portalSecurity post: operationId: postServiceScopes tags: [PortalCatalog] summary: Create controlled client scopes description: Global estate-owned catalog create. Requires members:service-scope:create and a tenant-independent Administrator/Admin human role. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/ServiceScopeRequest"} responses: 200: {description: Created service scopes, schema: {$ref: "#/definitions/ServiceScopeResponse"}} 400: {description: Invalid service scope data} 401: {description: Missing or invalid server or session credential} 403: {description: Actor lacks catalog-management authority} 500: {description: Server error} security: *portalSecurity put: operationId: putServiceScopes tags: [PortalCatalog] summary: Update controlled client scopes description: Full replacement using id and lastModifiedDate as a compare-and-swap token. Requires members:service-scope:update and a tenant-independent Administrator/Admin human role. Use retired status instead of deletion. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/ServiceScopeRequest"} responses: 200: {description: Updated service scopes, schema: {$ref: "#/definitions/ServiceScopeResponse"}} 400: {description: Invalid service scope data} 401: {description: Missing or invalid server or session credential} 403: {description: Actor lacks catalog-management authority} 409: {description: lastModifiedDate is stale; reload before retrying} 500: {description: Server error} security: *portalSecurity /brandservices: get: operationId: getBrandServices tags: [PortalCatalog] summary: List brand catalog placements description: Global estate-owned catalog read. Requires members:brand-service:read and an active human session. parameters: - $ref: "#/parameters/id" - $ref: "#/parameters/brandId" - $ref: "#/parameters/serviceId" - $ref: "#/parameters/status" - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" responses: 200: {description: Brand-service records, schema: {$ref: "#/definitions/BrandServiceResponse"}} 400: {description: Invalid brand-service filter} 401: {description: Missing or invalid server or session credential} 403: {description: Actor is not authorized for the requested scope} 500: {description: Server error} security: *portalSecurity post: operationId: postBrandServices tags: [PortalCatalog] summary: Create brand catalog placements description: Global estate-owned catalog create. Requires members:brand-service:create and a tenant-independent Administrator/Admin human role. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/BrandServiceRequest"} responses: 200: {description: Created brand-service records, schema: {$ref: "#/definitions/BrandServiceResponse"}} 400: {description: Invalid catalog placement} 401: {description: Missing or invalid server or session credential} 403: {description: Actor lacks catalog-management authority} 500: {description: Server error} security: *portalSecurity put: operationId: putBrandServices tags: [PortalCatalog] summary: Update brand catalog placements description: Full replacement using id and lastModifiedDate as a compare-and-swap token. Requires members:brand-service:update and a tenant-independent Administrator/Admin human role. Use inactive status instead of deletion. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/BrandServiceRequest"} responses: 200: {description: Updated brand-service records, schema: {$ref: "#/definitions/BrandServiceResponse"}} 400: {description: Invalid catalog placement} 401: {description: Missing or invalid server or session credential} 403: {description: Actor lacks catalog-management authority} 409: {description: lastModifiedDate is stale; reload before retrying} 500: {description: Server error} security: *portalSecurity /plans: get: operationId: getPlans tags: [PortalPlans] summary: List immutable-version commercial plans description: Global estate-owned plan read. Requires members:plan:read and an active human session. parameters: - $ref: "#/parameters/id" - $ref: "#/parameters/status" - $ref: "#/parameters/effectiveAt" - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" responses: 200: {description: Plan records, schema: {$ref: "#/definitions/PlanResponse"}} 400: {description: Invalid plan filter} 401: {description: Missing or invalid server or session credential} 403: {description: Actor is not authorized for the requested scope} 500: {description: Server error} security: *portalSecurity post: operationId: postPlans tags: [PortalPlans] summary: Create plan versions description: Global estate-owned plan create. Requires members:plan:create and a tenant-independent Administrator/Admin human role. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/PlanRequest"} responses: 200: {description: Created plans, schema: {$ref: "#/definitions/PlanResponse"}} 400: {description: Invalid plan data} 401: {description: Missing or invalid server or session credential} 403: {description: Actor lacks plan-management authority} 500: {description: Server error} security: *portalSecurity put: operationId: putPlans tags: [PortalPlans] summary: Update draft or lifecycle state; published versions are immutable description: Full replacement using id and lastModifiedDate as a compare-and-swap token. Requires members:plan:update and a tenant-independent Administrator/Admin human role. Draft plans may be edited; active plans may only transition unchanged to retired. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/PlanRequest"} responses: 200: {description: Updated plans, schema: {$ref: "#/definitions/PlanResponse"}} 400: {description: Invalid or immutable plan update} 401: {description: Missing or invalid server or session credential} 403: {description: Actor lacks plan-management authority} 409: {description: lastModifiedDate is stale; reload before retrying} 500: {description: Server error} security: *portalSecurity /brandplans: get: operationId: getBrandPlans tags: [PortalPlans] summary: List brand plan placements description: Global estate-owned brand-plan read. Requires members:brand-plan:read and an active human session. parameters: - $ref: "#/parameters/id" - $ref: "#/parameters/brandId" - $ref: "#/parameters/planId" - $ref: "#/parameters/status" - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" responses: 200: {description: Brand-plan records, schema: {$ref: "#/definitions/BrandPlanResponse"}} 400: {description: Invalid brand-plan filter} 401: {description: Missing or invalid server or session credential} 403: {description: Actor is not authorized for the requested scope} 500: {description: Server error} security: *portalSecurity post: operationId: postBrandPlans tags: [PortalPlans] summary: Create brand plan placements description: Global estate-owned brand-plan create. Requires members:brand-plan:create and a tenant-independent Administrator/Admin human role. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/BrandPlanRequest"} responses: 200: {description: Created brand-plan records, schema: {$ref: "#/definitions/BrandPlanResponse"}} 400: {description: Invalid plan placement} 401: {description: Missing or invalid server or session credential} 403: {description: Actor lacks plan-management authority} 500: {description: Server error} security: *portalSecurity put: operationId: putBrandPlans tags: [PortalPlans] summary: Update brand plan placements description: Full replacement using id and lastModifiedDate as a compare-and-swap token. Requires members:brand-plan:update and a tenant-independent Administrator/Admin human role. brandId and planId are immutable; use inactive status instead of deletion. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/BrandPlanRequest"} responses: 200: {description: Updated brand-plan records, schema: {$ref: "#/definitions/BrandPlanResponse"}} 400: {description: Invalid plan placement} 401: {description: Missing or invalid server or session credential} 403: {description: Actor lacks plan-management authority} 409: {description: lastModifiedDate is stale; reload before retrying} 500: {description: Server error} security: *portalSecurity /planservices: get: operationId: getPlanServices tags: [PortalPlans] summary: List plan service grants and descriptive limits description: Global estate-owned plan-service read. Requires members:plan-service:read and an active human session. parameters: - $ref: "#/parameters/id" - $ref: "#/parameters/planId" - $ref: "#/parameters/serviceId" - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" responses: 200: {description: Plan-service records, schema: {$ref: "#/definitions/PlanServiceResponse"}} 400: {description: Invalid plan-service filter} 401: {description: Missing or invalid server or session credential} 403: {description: Actor is not authorized for the requested scope} 500: {description: Server error} security: *portalSecurity post: operationId: postPlanServices tags: [PortalPlans] summary: Add service grants and descriptive limits to plans description: Draft-plan grant create. Requires members:plan-service:create and a tenant-independent Administrator/Admin human role. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/PlanServiceRequest"} responses: 200: {description: Created plan-service records, schema: {$ref: "#/definitions/PlanServiceResponse"}} 400: {description: Invalid typed limit or plan grant} 401: {description: Missing or invalid server or session credential} 403: {description: Actor lacks plan-management authority} 500: {description: Server error} security: *portalSecurity put: operationId: putPlanServices tags: [PortalPlans] summary: Update draft plan service grants description: Full replacement using id and lastModifiedDate as a compare-and-swap token. Requires members:plan-service:update and a tenant-independent Administrator/Admin human role. planId and serviceId are immutable and the Plan must remain draft. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/PlanServiceRequest"} responses: 200: {description: Updated plan-service records, schema: {$ref: "#/definitions/PlanServiceResponse"}} 400: {description: Invalid typed limit or immutable plan grant} 401: {description: Missing or invalid server or session credential} 403: {description: Actor lacks plan-management authority} 409: {description: lastModifiedDate is stale; reload before retrying} 500: {description: Server error} security: *portalSecurity /subscriptions: get: operationId: getSubscriptions tags: [PortalAccess] summary: List tenant-scoped subscriptions description: Tenant-scoped subscription read. Requires members:subscription:read and an active human session; tenant membership remains authoritative. parameters: - $ref: "#/parameters/id" - $ref: "#/parameters/tenantId" - $ref: "#/parameters/planId" - $ref: "#/parameters/status" - $ref: "#/parameters/effectiveAt" - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" responses: 200: {description: Authorized subscription records, schema: {$ref: "#/definitions/SubscriptionResponse"}} 400: {description: Invalid subscription filter} 401: {description: Missing or invalid server or session credential} 403: {description: Actor is not a member of or cannot manage the requested tenant} 500: {description: Server error} security: *portalSecurity post: operationId: postSubscriptions tags: [PortalAccess] summary: Create tenant subscriptions description: Tenant-scoped subscription create. Requires members:subscription:create, an active human session, and tenant management authority. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/SubscriptionRequest"} responses: 200: {description: Created subscriptions, schema: {$ref: "#/definitions/SubscriptionResponse"}} 400: {description: Invalid subscription lifecycle data} 401: {description: Missing or invalid server or session credential} 403: {description: Actor cannot manage the requested tenant} 500: {description: Server error} security: *portalSecurity put: operationId: putSubscriptions tags: [PortalAccess] summary: Update, pause, cancel, or expire subscriptions description: Full replacement using id and lastModifiedDate as a compare-and-swap token. Requires members:subscription:update, an active human session, and tenant management authority. tenantId and planId are immutable; canceled and expired states cannot be reopened. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/SubscriptionRequest"} responses: 200: {description: Updated subscriptions, schema: {$ref: "#/definitions/SubscriptionResponse"}} 400: {description: Invalid subscription lifecycle transition} 401: {description: Missing or invalid server or session credential} 403: {description: Actor cannot manage the requested tenant} 409: {description: lastModifiedDate is stale; reload before retrying} 500: {description: Server error} security: *portalSecurity /entitlements: get: operationId: getEntitlements tags: [PortalAccess] summary: List tenant- or user-scoped explicit grants description: Tenant- or user-scoped entitlement read. Requires members:entitlement:read and an active human session; tenant and user visibility remain authoritative. parameters: - $ref: "#/parameters/id" - $ref: "#/parameters/tenantId" - $ref: "#/parameters/userId" - $ref: "#/parameters/serviceId" - $ref: "#/parameters/status" - $ref: "#/parameters/effectiveAt" - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" responses: 200: {description: Authorized entitlement records, schema: {$ref: "#/definitions/EntitlementResponse"}} 400: {description: Invalid entitlement filter} 401: {description: Missing or invalid server or session credential} 403: {description: Actor is not authorized for the tenant or user scope} 500: {description: Server error} security: *portalSecurity post: operationId: postEntitlements tags: [PortalAccess] summary: Create explicit tenant or user grants description: Explicit entitlement create. Requires members:entitlement:create, an active human session, and tenant management authority. revokedAt and revokedById are server-owned. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/EntitlementRequest"} responses: 200: {description: Created entitlements, schema: {$ref: "#/definitions/EntitlementResponse"}} 400: {description: Invalid or overlapping explicit grant} 401: {description: Missing or invalid server or session credential} 403: {description: Actor cannot manage grants for the tenant} 500: {description: Server error} security: *portalSecurity put: operationId: putEntitlements tags: [PortalAccess] summary: Update, revoke, or expire explicit grants description: Full replacement using id and lastModifiedDate as a compare-and-swap token. Requires members:entitlement:update, an active human session, and tenant management authority. tenantId, userId, and serviceId are immutable; revoked and expired states cannot be reopened. parameters: - in: body name: request required: true schema: {$ref: "#/definitions/EntitlementRequest"} responses: 200: {description: Updated entitlements, schema: {$ref: "#/definitions/EntitlementResponse"}} 400: {description: Invalid or overlapping explicit grant} 401: {description: Missing or invalid server or session credential} 403: {description: Actor cannot manage grants for the tenant} 409: {description: lastModifiedDate is stale; reload before retrying} 500: {description: Server error} security: *portalSecurity /effectiveentitlements: get: operationId: getEffectiveEntitlements tags: [PortalAccess] summary: Resolve effective commercial access at a UTC instant description: Derived read-only effective access resolution. Requires members:effective-entitlement:read and an active human session. This is not a raw CRUD resource. parameters: - $ref: "#/parameters/tenantId" - $ref: "#/parameters/userId" - $ref: "#/parameters/serviceId" - $ref: "#/parameters/effectiveAt" - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" responses: 200: {description: Effective grants with typed limits and provenance, schema: {$ref: "#/definitions/EffectiveEntitlementResponse"}} 400: {description: Invalid or ambiguous effective-entitlement context} 401: {description: Missing or invalid server or session credential} 403: {description: Actor is not authorized for the tenant or user scope} 500: {description: Server error} security: *portalSecurity /authorizedclients: get: operationId: getAuthorizedClients tags: [PortalClients] summary: List non-secret authorized-client connection metadata parameters: - $ref: "#/parameters/id" - $ref: "#/parameters/tenantId" - $ref: "#/parameters/userId" - $ref: "#/parameters/status" - $ref: "#/parameters/clientType" - $ref: "#/parameters/scope" - $ref: "#/parameters/includeInactive" - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" responses: 200: {description: Authorized-client metadata without tokens or secrets, schema: {$ref: "#/definitions/AuthorizedClientResponse"}} 400: {description: Invalid authorized-client filter} 401: {description: Missing or invalid server or session credential} 403: {description: Actor is not authorized for the tenant or user scope} 500: {description: Server error} security: *portalSecurity post: operationId: postAuthorizedClients tags: [PortalClients] summary: Register non-secret authorized-client metadata parameters: - in: body name: request required: true schema: {$ref: "#/definitions/AuthorizedClientRequest"} responses: 200: {description: Created client metadata, schema: {$ref: "#/definitions/AuthorizedClientResponse"}} 400: {description: Invalid client metadata or tenant/user scope} 401: {description: Missing or invalid server or session credential} 403: {description: Actor cannot manage clients for the tenant} 500: {description: Server error} security: *portalSecurity put: operationId: putAuthorizedClients tags: [PortalClients] summary: Update or idempotently revoke client metadata parameters: - in: body name: request required: true schema: {$ref: "#/definitions/AuthorizedClientRequest"} responses: 200: {description: Updated client metadata, schema: {$ref: "#/definitions/AuthorizedClientResponse"}} 400: {description: Invalid client lifecycle transition} 401: {description: Missing or invalid server or session credential} 403: {description: Actor cannot manage clients for the tenant} 500: {description: Server error} security: *portalSecurity /authorizedclientscopes: get: operationId: getAuthorizedClientScopes tags: [PortalClients] summary: List approved scopes backed by effective entitlements parameters: - $ref: "#/parameters/id" - name: authorizedClientId in: query type: string format: uuid - $ref: "#/parameters/serviceId" - $ref: "#/parameters/scope" - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" responses: 200: {description: Authorized-client scopes, schema: {$ref: "#/definitions/AuthorizedClientScopeResponse"}} 400: {description: Invalid authorized-client-scope filter} 401: {description: Missing or invalid server or session credential} 403: {description: Actor is not authorized for the client tenant or user scope} 500: {description: Server error} security: *portalSecurity post: operationId: postAuthorizedClientScopes tags: [PortalClients] summary: Approve scopes only when backed by effective entitlements parameters: - in: body name: request required: true schema: {$ref: "#/definitions/AuthorizedClientScopeRequest"} responses: 200: {description: Created authorized-client scopes, schema: {$ref: "#/definitions/AuthorizedClientScopeResponse"}} 400: {description: Scope is not backed by an effective service entitlement} 401: {description: Missing or invalid server or session credential} 403: {description: Actor cannot manage scopes for the client} 500: {description: Server error} security: *portalSecurity put: operationId: putAuthorizedClientScopes tags: [PortalClients] summary: Update approved client scopes parameters: - in: body name: request required: true schema: {$ref: "#/definitions/AuthorizedClientScopeRequest"} responses: 200: {description: Updated authorized-client scopes, schema: {$ref: "#/definitions/AuthorizedClientScopeResponse"}} 400: {description: Scope is not backed by an effective service entitlement} 401: {description: Missing or invalid server or session credential} 403: {description: Actor cannot manage scopes for the client} 500: {description: Server error} security: *portalSecurity /manageabletenants: get: operationId: getManageableTenants tags: [PortalMemberships] summary: List tenant contexts the current actor may administer parameters: - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" responses: 200: {description: Actor-derived manageable tenant contexts, schema: {$ref: "#/definitions/ManageableTenantResponse"}} 400: {description: Invalid pagination} 401: {description: Missing or invalid server or session credential} 500: {description: Server error} security: *portalSecurity /tenantmemberships: get: operationId: getTenantMemberships tags: [PortalMemberships] summary: List actor-visible tenant memberships parameters: - $ref: "#/parameters/membershipTenantId" - $ref: "#/parameters/userId" - $ref: "#/parameters/membershipEmail" - $ref: "#/parameters/membershipAccessLevel" - $ref: "#/parameters/membershipStatus" - $ref: "#/parameters/limit" - $ref: "#/parameters/offset" responses: 200: {description: Actor-scoped tenant memberships, schema: {$ref: "#/definitions/TenantMembershipListResponse"}} 400: {description: Invalid membership filter} 401: {description: Missing or invalid server or session credential} 404: {description: Requested foreign or unavailable scope} 500: {description: Server error} security: *portalSecurity post: operationId: postTenantMembership tags: [PortalMemberships] summary: Create a tenant link or return an exact desired-state match parameters: - $ref: "#/parameters/requestId" - in: body name: request required: true schema: {$ref: "#/definitions/TenantMembershipCreateRequest"} responses: 200: {description: Newly created membership or exact existing desired-state match, schema: {$ref: "#/definitions/TenantMembershipResponse"}} 400: {description: Invalid identity selector or desired state} 401: {description: Missing or invalid server or session credential} 404: {description: "Target tenant, user, or authority is unavailable"} 409: {description: "Self-change, owner, or existing-state conflict; use GET plus optimistic PUT for state changes"} 500: {description: Server error} security: *portalSecurity /tenantmemberships/{membershipId}: parameters: - name: membershipId in: path required: true type: string format: uuid get: operationId: getTenantMembership tags: [PortalMemberships] summary: Get one actor-visible tenant membership responses: 200: {description: Tenant membership, schema: {$ref: "#/definitions/TenantMembershipResponse"}} 401: {description: Missing or invalid server or session credential} 404: {description: "Membership is absent, foreign, or unauthorized"} 500: {description: Server error} security: *portalSecurity put: operationId: putTenantMembership tags: [PortalMemberships] summary: Idempotently change membership access or lifecycle parameters: - $ref: "#/parameters/requestId" - in: body name: request required: true schema: {$ref: "#/definitions/TenantMembershipUpdateRequest"} responses: 200: {description: Current membership desired state, schema: {$ref: "#/definitions/TenantMembershipResponse"}} 400: {description: Invalid desired state} 401: {description: Missing or invalid server or session credential} 404: {description: "Membership is absent, foreign, or unauthorized"} 409: {description: "Optimistic, self-change, owner, or state conflict"} 500: {description: Server error} security: *portalSecurity delete: operationId: deleteTenantMembership tags: [PortalMemberships] summary: Idempotently soft-revoke one membership parameters: - $ref: "#/parameters/requestId" - name: lastModifiedDate in: query required: true type: string format: date-time description: Optimistic concurrency token from the latest representation. responses: 200: {description: Revoked membership, schema: {$ref: "#/definitions/TenantMembershipResponse"}} 401: {description: Missing or invalid server or session credential} 404: {description: "Membership is absent, foreign, or unauthorized"} 409: {description: "Optimistic, self-change, owner, or state conflict"} 500: {description: Server error} security: *portalSecurity /credentials/password/change: post: tags: [credentials] summary: Change the current user's password and revoke every session operationId: changePassword security: - ApiKeyAuth: [] kvSessionCookie: [] parameters: - $ref: "#/parameters/requestId" - name: passwordChangeRequest in: body required: true schema: {$ref: "#/definitions/PasswordChangeRequest"} responses: 204: description: Password changed; all sessions revoked and fresh login required. 401: {$ref: "#/responses/Unauthorized"} 422: {$ref: "#/responses/UnprocessableEntity"} 500: {$ref: "#/responses/ServerError"} /credentials/password/recovery-requests: post: tags: [credentials] summary: Request password recovery without disclosing account state operationId: requestPasswordRecovery security: - ApiKeyAuth: [] parameters: - $ref: "#/parameters/requestId" - $ref: "#/parameters/recoveryClientIP" - name: passwordRecoveryRequest in: body required: true schema: {$ref: "#/definitions/PasswordRecoveryRequest"} responses: 202: description: Uniform accepted response for every account state. schema: {$ref: "#/definitions/PasswordRecoveryAccepted"} 401: {$ref: "#/responses/Unauthorized"} 500: {$ref: "#/responses/ServerError"} /credentials/password/recovery-completions: post: tags: [credentials] summary: Consume a single-use recovery token and revoke every session operationId: completePasswordRecovery security: - ApiKeyAuth: [] parameters: - $ref: "#/parameters/requestId" - name: passwordRecoveryCompletion in: body required: true schema: {$ref: "#/definitions/PasswordRecoveryCompletion"} responses: 204: description: Password reset; all sessions revoked and fresh login required. 401: {$ref: "#/responses/Unauthorized"} 422: description: Invalid, expired, revoked, or consumed token, or invalid password. schema: {$ref: "../../lib/swagger/defs/error.yaml#/Error"} 500: {$ref: "#/responses/ServerError"} /credentials/email-authentication/requests: post: tags: [credentials] summary: Request an initial email-authentication link without disclosing account state operationId: requestEmailAuthentication security: - ApiKeyAuth: [] parameters: - $ref: "#/parameters/requestId" - $ref: "#/parameters/recoveryClientIP" - name: emailAuthenticationRequest in: body required: true schema: {$ref: "#/definitions/EmailAuthenticationRequest"} responses: 202: description: Uniform accepted response for every account state. schema: {$ref: "#/definitions/PasswordRecoveryAccepted"} 401: {$ref: "#/responses/Unauthorized"} 500: {$ref: "#/responses/ServerError"} /credentials/email-authentication/completions: post: tags: [credentials] summary: Consume an initial email-authentication token and create a native session operationId: completeEmailAuthentication security: - ApiKeyAuth: [] parameters: - $ref: "#/parameters/requestId" - name: emailAuthenticationCompletion in: body required: true schema: {$ref: "#/definitions/EmailAuthenticationCompletion"} responses: 200: description: Email verified and native session created. headers: Set-Cookie: type: string description: kvSession cookie for the canonical keenanvision.net domain. schema: $ref: "#/definitions/EmailAuthenticationSession" 401: {$ref: "#/responses/Unauthorized"} 422: description: Invalid, expired, revoked, consumed, or already-completed token. schema: {$ref: "../../lib/swagger/defs/error.yaml#/Error"} 500: {$ref: "#/responses/ServerError"} /sessions: post: tags: [sessions] summary: Create new session (sign-in) operationId: createSession parameters: - in: body name: credentials required: true schema: $ref: "../../lib/swagger/defs/credentials.yaml#/Credentials" responses: 200: description: Successful sign-in headers: Set-Cookie: type: string description: | kvSession=; HttpOnly; Secure; SameSite=None; Domain=.keenanvision.net; Path=/; Max-Age=5400 schema: $ref: "../../lib/swagger/defs/user.yaml#/User" 401: $ref: "#/responses/Unauthorized" 429: $ref: "#/responses/ServerError" /sessions/refresh: post: tags: [sessions] summary: Refresh session cookie operationId: refreshSession security: - kvSessionCookie: [] responses: 200: description: Token refreshed headers: Set-Cookie: type: string description: New kvSession cookie with updated expiry schema: $ref: "../../lib/swagger/defs/user.yaml#/User" 401: $ref: "#/responses/Unauthorized" /sessions/current: delete: responses: "204": description: Logged out; kvSession cookie cleared headers: Set-Cookie: type: string description: "kvSession=; HttpOnly; Secure; SameSite=None; Domain=.keenanvision.net; Path=/; Max-Age=0" "401": description: Access Unauthorized, invalid API-KEY was used schema: $ref: "../../lib/swagger/defs/error.yaml#/Error" security: - kvSessionCookie: [] tags: - sessions summary: Delete current session (log out) operationId: deleteSession /sessions/me: get: tags: [sessions] summary: Get current user operationId: getMe security: - kvSessionCookie: [] responses: 200: description: Current user profile schema: $ref: "../../lib/swagger/defs/user.yaml#/User" 401: $ref: "#/responses/Unauthorized" /sessions/handoff/create: post: tags: [sessions] summary: Create handoff token for cross-domain authentication operationId: createHandoff security: - kvSessionCookie: [] - ApiKeyAuth: [] parameters: - name: handoffRequest in: body required: true schema: type: object required: - target_domain - state properties: target_domain: type: string description: Target domain for handoff example: "salesforcedevops.net" state: type: string description: CSRF state parameter example: "random-csrf-token-123" responses: 200: description: Handoff token created successfully schema: type: object properties: handoff_token: type: string description: One-time handoff token example: "hoff_1234567890abcdef" expires_at: type: string format: date-time description: Token expiration time 400: description: Invalid request parameters schema: $ref: "../../lib/swagger/defs/error.yaml#/Error" 401: $ref: "#/responses/Unauthorized" 403: description: Domain not allowed schema: $ref: "../../lib/swagger/defs/error.yaml#/Error" 500: $ref: "#/responses/ServerError" /sessions/handoff/validate: post: tags: [sessions] summary: Validate and consume handoff token operationId: validateHandoff security: - ApiKeyAuth: [] parameters: - name: handoffValidate in: body required: true schema: type: object required: - handoff_token - domain - state properties: handoff_token: type: string description: Handoff token to validate example: "hoff_1234567890abcdef" domain: type: string description: Requesting domain example: "salesforcedevops.net" state: type: string description: CSRF state parameter example: "random-csrf-token-123" client_ip: type: string description: Client IP address example: "192.168.1.100" responses: 200: description: Token validated successfully schema: type: object properties: user: $ref: "../../lib/swagger/defs/user.yaml#/User" session_ref: type: string description: Reference to central session example: "sess_abcdef1234567890" expires_at: type: string format: date-time description: Session expiration time 400: description: Invalid request parameters schema: $ref: "../../lib/swagger/defs/error.yaml#/Error" 401: description: Invalid or expired token schema: $ref: "../../lib/swagger/defs/error.yaml#/Error" 403: description: Domain not authorized schema: $ref: "../../lib/swagger/defs/error.yaml#/Error" 500: $ref: "#/responses/ServerError" /attendees: get: description: List or get attendees associated with events managed by the configured Keenan Vision tenant. Requires members:attendee:read and compound machine plus native-user authentication. Owners and Managers can read tenant-bounded attendees; Contributors can read only their own attendance. operationId: getAttendees parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/AttendeeResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list Attendees tags: - Attendees post: description: Create one attendee for an event managed by the configured Keenan Vision tenant. Requires members:attendee:create and Keenan Vision Owner or Manager access. ID and timestamps are server-owned; event, user, and optional ticket relationships are validated. operationId: postAttendees parameters: - $ref: "#/parameters/AttendeeRequest" responses: "200": $ref: "#/responses/AttendeeResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new Attendees tags: - Attendees put: description: CAS-update one attendee check-in status. Requires members:attendee:update and Keenan Vision Owner or Manager access. EventID, TicketID, and UserID are immutable; delete is unavailable. operationId: putAttendees parameters: - $ref: "#/parameters/AttendeeRequest" responses: "200": $ref: "#/responses/AttendeeResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "409": $ref: "#/responses/Conflict" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update Attendee tags: - Attendees /clusters: get: description: Return tenant-scoped Cluster records. Requires members:cluster:read and an active human membership in tenantId. operationId: getClusters parameters: - $ref: "#/parameters/clusterIdQuery" - $ref: "#/parameters/clusterTenantId" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/ClusterResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get governed tenant Clusters tags: - Clusters post: description: Create one tenant-scoped Cluster. Requires members:cluster:create and active Owner or Manager access. ID, TenantID, and audit fields are server-owned. operationId: postClusters parameters: - $ref: "#/parameters/ClusterRequest" - $ref: "#/parameters/clusterTenantId" responses: "200": $ref: "#/responses/ClusterResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create a governed Cluster tags: - Clusters put: description: CAS-update one tenant-scoped Cluster. Requires members:cluster:update, active Owner or Manager access, and the current LastModifiedDate. TenantID and audit fields remain server-owned. operationId: putClusters parameters: - $ref: "#/parameters/ClusterRequest" - $ref: "#/parameters/clusterTenantId" responses: "200": $ref: "#/responses/ClusterResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "409": $ref: "#/responses/Conflict" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update a governed Cluster tags: - Clusters /courselessons: get: description: Estate-global learning catalog read. Requires members:course-lesson:read and an active human session. operationId: getCourseLessons security: - ApiKeyAuth: [] kvSessionCookie: [] parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/CourseLessonResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Get a list of CourseLessons tags: - Courses post: description: Estate-global lesson create. Requires members:course-lesson:create, an active human session, and tenant-independent Administrator/Admin authority. IDs and audit fields are server-owned. operationId: postCourseLessons security: - ApiKeyAuth: [] kvSessionCookie: [] parameters: - $ref: "#/parameters/CourseLessonRequest" responses: "200": $ref: "#/responses/CourseLessonResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Create a new CourseLesson tags: - Courses put: security: - ApiKeyAuth: [] kvSessionCookie: [] description: Estate-global lesson CAS update. Requires members:course-lesson:update, an active human session, and tenant-independent Administrator/Admin authority. SectionID is immutable. operationId: updateCourseLessons parameters: - $ref: "#/parameters/CourseLessonRequest" responses: "200": $ref: "#/responses/CourseLessonResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "409": $ref: "#/responses/Conflict" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Update an existing CourseLesson tags: - Courses /courses: get: description: Estate-global learning catalog read. Requires members:course:read and an active human session. security: - ApiKeyAuth: [] kvSessionCookie: [] operationId: getCourses parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/CourseResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Get a list of Courses tags: - Courses post: description: Estate-global course create. Requires members:course:create, an active human session, and tenant-independent Administrator/Admin authority. IDs and audit fields are server-owned. security: - ApiKeyAuth: [] kvSessionCookie: [] operationId: postCourses parameters: - $ref: "#/parameters/CourseRequest" responses: "200": $ref: "#/responses/CourseResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Create a new Course tags: - Courses put: description: Estate-global course CAS update. Requires members:course:update, an active human session, and tenant-independent Administrator/Admin authority. security: - ApiKeyAuth: [] kvSessionCookie: [] operationId: updateCourses parameters: - $ref: "#/parameters/CourseRequest" responses: "200": $ref: "#/responses/CourseResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "409": $ref: "#/responses/Conflict" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Update an existing Course tags: - Courses /coursesections: get: description: Estate-global course-section read. Requires members:course-section:read and an active human session. security: - ApiKeyAuth: [] kvSessionCookie: [] operationId: getCourseSections parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/CourseSectionResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Get a list of CourseSections tags: - Courses post: description: Estate-global course-section create. Requires members:course-section:create, an active human session, and tenant-independent Administrator/Admin authority. CourseID is required and validated. security: - ApiKeyAuth: [] kvSessionCookie: [] operationId: postCourseSections parameters: - $ref: "#/parameters/CourseSectionRequest" responses: "200": $ref: "#/responses/CourseSectionResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Create a new CourseSection tags: - Courses put: description: Estate-global course-section CAS update. Requires members:course-section:update, an active human session, and tenant-independent Administrator/Admin authority. CourseID is immutable. security: - ApiKeyAuth: [] kvSessionCookie: [] operationId: updateCourseSections parameters: - $ref: "#/parameters/CourseSectionRequest" responses: "200": $ref: "#/responses/CourseSectionResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "409": $ref: "#/responses/Conflict" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Update an existing CourseSection tags: - Courses /databases: get: description: Tenant-bound read of sanitized Database metadata. Requires members:database:read and active human membership. DSN, provisioning credentials, and audit identities are absent. Provisioning writes remain unavailable. operationId: getDatabases parameters: - $ref: "#/parameters/databaseIdQuery" - $ref: "#/parameters/databaseTenantId" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/DatabaseMetadataResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get sanitized Database metadata tags: - Databases /documents: get: description: Tenant- and user-scoped Document read. Requires members:document:read and an active human session. operationId: getDocuments parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/DocumentResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list Documents tags: - Documents post: description: Tenant- and user-scoped Document create. Requires members:document:create and an active human session. operationId: postDocuments parameters: - $ref: "#/parameters/documentRequest" responses: "200": $ref: "#/responses/DocumentResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new Documents tags: - Documents put: description: Tenant- and user-scoped Document CAS update. Requires members:document:update and an active human session. operationId: putDocuments parameters: - $ref: "#/parameters/documentRequest" responses: "200": $ref: "#/responses/DocumentResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "409": $ref: "#/responses/Conflict" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update Documents tags: - Documents /folders: get: description: Tenant- and user-scoped Folder read. Requires members:folder:read and an active human session. operationId: getFolders parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/FolderResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get folders tags: - Folders post: description: Tenant- and user-scoped Folder create. Requires members:folder:create and an active human session. operationId: postFolders parameters: - $ref: "#/parameters/folderRequest" responses: "200": $ref: "#/responses/FolderResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create folders tags: - Folders put: description: Tenant- and user-scoped Folder CAS update. Requires members:folder:update and an active human session. operationId: putFolders parameters: - $ref: "#/parameters/folderRequest" responses: "200": $ref: "#/responses/FolderResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update folders tags: - Folders /documentparameters: get: description: Tenant- and user-scoped DocumentParameter read. Requires members:document-parameter:read and an active human session. Contributors can read only their own records; Owners and Managers can read the tenant. operationId: getDocumentParameters parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/DocumentParameterResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get document parameters tags: - Document Parameters post: description: Tenant-scoped DocumentParameter create. Requires members:document-parameter:create, an active human session, and Owner or Manager authority. operationId: postDocumentParameters parameters: - $ref: "#/parameters/documentParameterRequest" responses: "200": $ref: "#/responses/DocumentParameterResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create document parameters tags: - Document Parameters put: description: Tenant-scoped DocumentParameter CAS update. Requires members:document-parameter:update, an active human session, and Owner or Manager authority. operationId: putDocumentParameters parameters: - $ref: "#/parameters/documentParameterRequest" responses: "200": $ref: "#/responses/DocumentParameterResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update document parameters tags: - Document Parameters /emailmessages: get: security: - ApiKeyAuth: [] summary: "Get email messages from data store" operationId: getEmailMessages description: "Retrieves email messages from workflow storage" parameters: - $ref: "#/parameters/emailMessageIdQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" tags: - Emails responses: "200": $ref: "#/responses/EmailMessagesResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" post: security: - ApiKeyAuth: [] summary: Add new email messages to the outgoing queue operationId: postEmailMessages description: Insert new email messages into workflow storage parameters: - $ref: "#/parameters/EmailMessageRequest" responses: "200": $ref: "#/responses/EmailMessagesResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" tags: - Emails /outgoingemailmessages: get: security: - ApiKeyAuth: [] summary: "Get email messages from data store" operationId: getOutgoingEmailMessages description: "Retrieves email messages from workflow storage" parameters: - $ref: "#/parameters/emailMessageIdQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" tags: - Emails responses: "200": $ref: "#/responses/OutgoingEmailMessagesResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" post: security: - ApiKeyAuth: [] summary: Add new email messages to the outgoing queue operationId: postOutgoingEmailMessages description: Insert new email messages into workflow storage parameters: - $ref: "#/parameters/OutgoingEmailMessageRequest" responses: "200": $ref: "#/responses/OutgoingEmailMessagesResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" tags: - Emails /enrollments: get: description: User-global enrollment read. Requires members:enrollment:read and an active human session. Because Enrollment has no TenantID, records are restricted to the authenticated user and tenant managers receive no cross-user visibility. operationId: getEnrollments parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/EnrollmentResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list Enrollments tags: - Enrollments post: description: User-global self-enrollment create. Requires members:enrollment:create and an active human session. UserID is derived from the actor; IDs, audit fields, EnrollmentDate, and Completed are server-owned. operationId: postEnrollments parameters: - $ref: "#/parameters/EnrollmentRequest" responses: "200": $ref: "#/responses/EnrollmentResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new Enrollments tags: - Enrollments put: description: User-global self-enrollment CAS update. Requires members:enrollment:update and an active human session. UserID and CourseID are immutable; completion is monotonic. operationId: putEnrollments parameters: - $ref: "#/parameters/EnrollmentRequest" responses: "200": $ref: "#/responses/EnrollmentResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "409": $ref: "#/responses/Conflict" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update Enrollment tags: - Enrollments /eventcategories: get: description: List or get estate-global event categories for an active member of the configured Keenan Vision tenant. Requires members:event-category:read and compound machine plus native-user authentication. security: - ApiKeyAuth: [] kvSessionCookie: [] operationId: getEventCategories parameters: - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" - $ref: "#/parameters/idQuery" responses: "200": $ref: "#/responses/EventCategoryResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Get a list of Eventcategories tags: - Events post: description: Create one estate-global event category. Requires members:event-category:create and Keenan Vision Owner or Manager access. ID and audit fields are server-owned. security: - ApiKeyAuth: [] kvSessionCookie: [] operationId: postEventCategories parameters: - $ref: "#/parameters/EventCategoryRequest" responses: "200": $ref: "#/responses/EventCategoryResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Create a new EventCategory tags: - Events put: description: CAS-update one estate-global event category. Requires members:event-category:update and Keenan Vision Owner or Manager access. ID and audit fields are server-owned; delete is unavailable. security: - ApiKeyAuth: [] kvSessionCookie: [] operationId: putEventCategories parameters: - $ref: "#/parameters/EventCategoryRequest" responses: "200": $ref: "#/responses/EventCategoryResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Update an EventCategory tags: - Events /events: get: description: List or get events owned by active members of the configured Keenan Vision tenant. Requires members:event:read and compound machine plus native-user authentication. Owners and Managers can read tenant-owned events; Contributors can read only events they organize. security: - ApiKeyAuth: [] kvSessionCookie: [] operationId: getEvents parameters: - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" - $ref: "#/parameters/idQuery" responses: "200": $ref: "#/responses/EventResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Get a list of Events tags: - Events post: description: Create one event owned by an active organizer in the configured Keenan Vision tenant. Requires members:event:create and Keenan Vision Owner or Manager access. AccountID remains read-only until a governed CRM relationship is available. security: - ApiKeyAuth: [] kvSessionCookie: [] operationId: postEvents parameters: - $ref: "#/parameters/EventRequest" responses: "200": $ref: "#/responses/EventResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Create a new Event tags: - Events put: description: CAS-update one event already owned by the configured Keenan Vision tenant. Requires members:event:update and Keenan Vision Owner or Manager access. AccountID and audit fields are server-owned or read-only; delete is unavailable. security: - ApiKeyAuth: [] kvSessionCookie: [] operationId: putEvents parameters: - $ref: "#/parameters/EventRequest" responses: "200": $ref: "#/responses/EventResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Update an Event tags: - Events /favorites: get: description: Tenant/user-scoped favorite read. Requires members:favorite:read plus an active native member session. Managers can read favorites for their managed tenants; other members can read only their own records. operationId: getFavorites parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" - $ref: "#/parameters/Auth0UserIdHeader" responses: "200": $ref: "#/responses/FavoriteResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list Favorites tags: - Favorites post: description: Tenant/user-scoped favorite create. Requires members:favorite:create plus an active native member session. IDs and audit fields are server-owned. operationId: postFavorites parameters: - $ref: "#/parameters/FavoriteRequest" responses: "200": $ref: "#/responses/FavoriteResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new Favorites tags: - Favorites put: description: Full writable-field replacement using ID and LastModifiedDate as a compare-and-swap token. Requires members:favorite:update plus an active native member session. TenantID and UserID cannot move. Delete is unavailable. operationId: putFavorites parameters: - $ref: "#/parameters/FavoriteRequest" responses: "200": $ref: "#/responses/FavoriteResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "409": $ref: "#/responses/Conflict" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update Favorite tags: - Favorites /invoices: get: description: Return a list of Invoice records from the datastore operationId: getInvoices parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/InvoiceResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Get a list Invoices tags: - Invoices post: description: Create Invoices operationId: postInvoices parameters: - $ref: "#/parameters/InvoiceRequest" responses: "200": $ref: "#/responses/InvoiceResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Create new Invoices tags: - Invoices put: description: Update Invoice operationId: putInvoices parameters: - $ref: "#/parameters/InvoiceRequest" responses: "200": $ref: "#/responses/InvoiceResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Update Invoice tags: - Invoices /issuedcertificates: get: description: Sanitized user-global certificate read. Requires members:issued-certificate:read and an active human session. Records are restricted to the authenticated user; verification material is never returned. Issuance, mutation, revocation, and deletion require a separate lifecycle API and are intentionally unavailable here. operationId: getIssuedCertificates parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/IssuedCertificateResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list IssuedCertificates tags: - IssuedCertificates /lessonprogress: get: description: Tenant- and user-scoped lesson-progress read. Requires members:lesson-progress:read and an active human session. Owners and managers can read their tenant; other members can read only their own records. operationId: getLessonProgresses parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/LessonProgressResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list LessonProgresses tags: - LessonProgress post: description: Tenant- and user-scoped lesson-progress create. Requires members:lesson-progress:create and an active human session. Relationship ownership is validated; IDs, audit fields, Completed, and CompletedAt are server-owned. operationId: postLessonProgresses parameters: - $ref: "#/parameters/LessonProgressRequest" responses: "200": $ref: "#/responses/LessonProgressResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new LessonProgresses tags: - LessonProgress put: description: Tenant- and user-scoped lesson-progress CAS update. Requires members:lesson-progress:update and an active human session. TenantID, UserID, EnrollmentID, and LessonID are immutable; completion is monotonic and CompletedAt is server-owned. operationId: putLessonProgresses parameters: - $ref: "#/parameters/LessonProgressRequest" responses: "200": $ref: "#/responses/LessonProgressResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "409": $ref: "#/responses/Conflict" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update LessonProgress tags: - LessonProgress /orders: get: description: Return a list of Order records from the datastore operationId: getOrders parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/OrderResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Get a list Orders tags: - Orders post: description: Create Orders operationId: postOrders parameters: - $ref: "#/parameters/OrderRequest" responses: "200": $ref: "#/responses/OrderResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Create new Orders tags: - Orders put: description: Update Order operationId: putOrders parameters: - $ref: "#/parameters/OrderRequest" responses: "200": $ref: "#/responses/OrderResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Update Order tags: - Orders /paymentmethods: get: description: Return a list of PaymentMethod records from the datastore operationId: getPaymentMethods parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/PaymentMethodResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Get a list PaymentMethods tags: - PaymentMethods post: description: Create PaymentMethods operationId: postPaymentMethods parameters: - $ref: "#/parameters/PaymentMethodRequest" responses: "200": $ref: "#/responses/PaymentMethodResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Create new PaymentMethods tags: - PaymentMethods put: description: Update PaymentMethod operationId: putPaymentMethods parameters: - $ref: "#/parameters/PaymentMethodRequest" responses: "200": $ref: "#/responses/PaymentMethodResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Update PaymentMethod tags: - PaymentMethods /prompts: get: description: Tenant/owner-scoped prompt read. Requires members:prompt:read and an active human session. operationId: getPrompts parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/PromptResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list of Prompts tags: - Prompts post: description: Tenant/owner-scoped prompt create. Requires members:prompt:create. IDs, audit, tenant, user, and usage are governed by Members. operationId: postPrompts parameters: - $ref: "#/parameters/PromptRequest" responses: "200": $ref: "#/responses/PromptResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new Prompts tags: - Prompts put: description: Tenant/owner-scoped full prompt replacement. Requires members:prompt:update and LastModifiedDate CAS. IDs, audit, tenant, user, and usage are governed by Members. operationId: putPrompts parameters: - $ref: "#/parameters/PromptRequest" responses: "200": $ref: "#/responses/PromptResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update Prompts tags: - Prompts /promptanswers: get: description: Tenant/owner-scoped prompt execution-result read. Requires members:prompt-answer:read and an active human session. operationId: getPromptAnswers parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/PromptAnswerResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list of PromptResponses tags: - Prompts post: description: Append an immutable prompt execution result. Requires members:prompt-answer:create. IDs, audit, tenant, and user are governed by Members. operationId: postPromptAnswers parameters: - $ref: "#/parameters/PromptAnswerRequest" responses: "200": $ref: "#/responses/PromptAnswerResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new PromptResponses tags: - Prompts /promptcategories: get: description: Global prompt taxonomy read for active Keenan Vision members. Requires members:prompt-category:read. operationId: getPromptCategories parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/PromptCategoryResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list of PromptCategories tags: - Prompts post: description: Global prompt taxonomy create for an active Keenan Vision Owner or Manager. Requires members:prompt-category:create. operationId: postPromptCategories parameters: - $ref: "#/parameters/PromptCategoryRequest" responses: "200": $ref: "#/responses/PromptCategoryResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new PromptCategories tags: - Prompts put: description: Global prompt taxonomy update for an active Keenan Vision Owner or Manager. Requires members:prompt-category:update and LastModifiedDate CAS. operationId: putPromptCategories parameters: - $ref: "#/parameters/PromptCategoryRequest" responses: "200": $ref: "#/responses/PromptCategoryResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update PromptCategories tags: - Prompts /prompttags: get: description: Global prompt taxonomy read for active Keenan Vision members. Requires members:prompt-tag:read. operationId: getPromptTags parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/PromptTagResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list of PromptTags tags: - Prompts post: description: Global prompt taxonomy create for an active Keenan Vision Owner or Manager. Requires members:prompt-tag:create. operationId: postPromptTags parameters: - $ref: "#/parameters/PromptTagRequest" responses: "200": $ref: "#/responses/PromptTagResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new PromptTags tags: - Prompts put: description: Global prompt taxonomy update for an active Keenan Vision Owner or Manager. Requires members:prompt-tag:update and LastModifiedDate CAS. operationId: putPromptTags parameters: - $ref: "#/parameters/PromptTagRequest" responses: "200": $ref: "#/responses/PromptTagResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update PromptTags tags: - Prompts /researchprojectcompanies: get: description: Tenant-scoped ResearchProjectCompany read. Requires members:research-project-company:read and an active human session. operationId: getResearchProjectCompanies parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/ResearchProjectCompanyResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list of ResearchProjectCompanies tags: - ResearchProjects post: description: Tenant-scoped ResearchProjectCompany create. Requires members:research-project-company:create and an active human session. operationId: postResearchProjectCompanies parameters: - $ref: "#/parameters/ResearchProjectCompanyRequest" responses: "200": $ref: "#/responses/ResearchProjectCompanyResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new ResearchProjectCompanies tags: - ResearchProjects put: description: Tenant-scoped ResearchProjectCompany CAS update. Requires members:research-project-company:update and an active human session. operationId: putResearchProjectCompanies parameters: - $ref: "#/parameters/ResearchProjectCompanyRequest" responses: "200": $ref: "#/responses/ResearchProjectCompanyResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update ResearchProjectCompanies tags: - ResearchProjects /researchprojectdocuments: get: description: Tenant- and user-scoped ResearchProjectDocument read. Requires members:research-project-document:read and an active human session. operationId: getResearchProjectDocuments parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/ResearchProjectDocumentResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list of ResearchProjectDocuments tags: - ResearchProjects post: description: Tenant- and user-scoped ResearchProjectDocument create. Requires members:research-project-document:create and an active human session. operationId: postResearchProjectDocuments parameters: - $ref: "#/parameters/ResearchProjectDocumentRequest" responses: "200": $ref: "#/responses/ResearchProjectDocumentResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new ResearchProjectDocuments tags: - ResearchProjects put: description: Tenant- and user-scoped ResearchProjectDocument CAS update. Requires members:research-project-document:update and an active human session. operationId: putResearchProjectDocuments parameters: - $ref: "#/parameters/ResearchProjectDocumentRequest" responses: "200": $ref: "#/responses/ResearchProjectDocumentResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update ResearchProjectDocuments tags: - ResearchProjects /researchprojectservices: get: description: Tenant- and user-scoped ResearchProjectService read. Requires members:research-project-service:read and an active human session. operationId: getResearchProjectServices parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/ResearchProjectServiceResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list of ResearchProjectServices tags: - ResearchProjects post: description: Tenant- and user-scoped ResearchProjectService create. Requires members:research-project-service:create and an active human session. operationId: postResearchProjectServices parameters: - $ref: "#/parameters/ResearchProjectServiceRequest" responses: "200": $ref: "#/responses/ResearchProjectServiceResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new ResearchProjectServices tags: - ResearchProjects put: description: Tenant- and user-scoped ResearchProjectService CAS update. Requires members:research-project-service:update and an active human session. operationId: putResearchProjectServices parameters: - $ref: "#/parameters/ResearchProjectServiceRequest" responses: "200": $ref: "#/responses/ResearchProjectServiceResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update ResearchProjectServices tags: - ResearchProjects /researchprojectproducts: get: description: Tenant- and user-scoped ResearchProjectProduct read. Requires members:research-project-product:read and an active human session. operationId: getResearchProjectProducts parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/ResearchProjectProductResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list of ResearchProjectProducts tags: - ResearchProjects post: description: Tenant- and user-scoped ResearchProjectProduct create. Requires members:research-project-product:create and an active human session. operationId: postResearchProjectProducts parameters: - $ref: "#/parameters/researchProjectProductRequest" responses: "200": $ref: "#/responses/ResearchProjectProductResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new ResearchProjectProducts tags: - ResearchProjects put: description: Tenant- and user-scoped ResearchProjectProduct CAS update. Requires members:research-project-product:update and an active human session. operationId: putResearchProjectProducts parameters: - $ref: "#/parameters/researchProjectProductRequest" responses: "200": $ref: "#/responses/ResearchProjectProductResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update ResearchProjectProducts tags: - ResearchProjects /researchprojects: get: description: Tenant- and user-scoped ResearchProject read. Requires members:research-project:read and an active human session. operationId: getResearchProjects parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/ResearchProjectResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list of ResearchProjects tags: - ResearchProjects post: description: Tenant- and user-scoped ResearchProject create. Requires members:research-project:create and an active human session. operationId: postResearchProjects parameters: - $ref: "#/parameters/ResearchProjectRequest" responses: "200": $ref: "#/responses/ResearchProjectResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new ResearchProjects tags: - ResearchProjects put: description: Tenant- and user-scoped ResearchProject CAS update. Requires members:research-project:update and an active human session. operationId: putResearchProjects parameters: - $ref: "#/parameters/ResearchProjectRequest" responses: "200": $ref: "#/responses/ResearchProjectResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update ResearchProjects tags: - ResearchProjects /researchprojecttopics: get: description: Tenant- and user-scoped ResearchProjectTopic read. Requires members:research-project-topic:read and an active human session. operationId: getResearchProjectTopics parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/ResearchProjectTopicResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list of ResearchProjectTopics tags: - ResearchProjects post: description: Tenant- and user-scoped ResearchProjectTopic create. Requires members:research-project-topic:create and an active human session. operationId: postResearchProjectTopics parameters: - $ref: "#/parameters/ResearchProjectTopicRequest" responses: "200": $ref: "#/responses/ResearchProjectTopicResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new ResearchProjectTopics tags: - ResearchProjects put: description: Tenant- and user-scoped ResearchProjectTopic CAS update. Requires members:research-project-topic:update and an active human session. operationId: putResearchProjectTopics parameters: - $ref: "#/parameters/ResearchProjectTopicRequest" responses: "200": $ref: "#/responses/ResearchProjectTopicResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update ResearchProjectTopics tags: - ResearchProjects /tenants: get: description: Return a list of Tenant records from the datastore operationId: getTenants parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/nameQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/TenantResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Get a list Tenants tags: - Tenants post: description: Create Tenants operationId: postTenants parameters: - $ref: "#/parameters/TenantRequest" responses: "200": $ref: "#/responses/TenantResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Create new Tenants tags: - Tenants put: description: Update Tenant operationId: putTenants parameters: - $ref: "#/parameters/TenantRequest" responses: "200": $ref: "#/responses/TenantResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Update Tenants tags: - Tenants /templates: get: description: Tenant- and user-scoped Template read. Requires members:template:read and an active human session. operationId: getTemplates parameters: - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" - $ref: "#/parameters/activeQuery" - $ref: "#/parameters/templateIdQuery" - $ref: "#/parameters/isMasterQuery" - $ref: "#/parameters/objectTypeQuery" responses: "200": $ref: "#/responses/TemplateResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list Templates tags: - Templates post: description: Tenant- and user-scoped Template create. Requires members:template:create and an active human session. operationId: postTemplates parameters: - $ref: "#/parameters/TemplateRequest" responses: "200": $ref: "#/responses/TemplateResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new Templates tags: - Templates put: description: Tenant- and user-scoped Template CAS update. Requires members:template:update and an active human session. operationId: putTemplates parameters: - $ref: "#/parameters/TemplateRequest" responses: "200": $ref: "#/responses/TemplateResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update Templates tags: - Templates /tickets: x-provider-state: pending get: description: Provider pending. Ticket tenancy and UserID ownership semantics are not authoritative, and Price is DECIMAL(10,2) while the legacy generated model uses float64. No runtime handler is wired. operationId: getTickets parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/TicketResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get a list Tickets tags: - Tickets post: description: Provider pending. Monetary precision, inventory lifecycle, and tenant ownership must be governed before Ticket creation is wired. operationId: postTickets parameters: - $ref: "#/parameters/TicketRequest" responses: "200": $ref: "#/responses/TicketResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create new Tickets tags: - Tickets put: description: Provider pending. Monetary precision, inventory lifecycle, and tenant ownership must be governed before Ticket update is wired. operationId: putTickets parameters: - $ref: "#/parameters/TicketRequest" responses: "200": $ref: "#/responses/TicketResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Update Ticket tags: - Tickets /tracks: get: description: Reads Tracks whose creator is an active member of the configured Keenan Vision tenant. Owners and Managers may read all such Tracks; Contributors may read only Tracks they created. Requires members:track:read and an active native member session. operationId: getTracks security: - ApiKeyAuth: [] kvSessionCookie: [] parameters: - $ref: "#/parameters/idQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/TrackResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Get governed Tracks tags: - Tracks post: description: Creates one Track for the configured Keenan Vision tenant. Requires members:track:create, an active native Owner or Manager session, and server-owned identity and audit fields. operationId: postTracks security: - ApiKeyAuth: [] kvSessionCookie: [] parameters: - $ref: "#/parameters/TrackRequest" responses: "200": $ref: "#/responses/TrackResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Create a governed Track tags: - Tracks put: description: CAS-updates one governed Track. Requires members:track:update, an active native Owner or Manager session, and the current LastModifiedDate. Creator identity and audit fields remain server-owned. operationId: putTracks security: - ApiKeyAuth: [] kvSessionCookie: [] parameters: - $ref: "#/parameters/TrackRequest" responses: "200": $ref: "#/responses/TrackResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Update a governed Track tags: - Tracks /trackevents: get: description: Reads Track-to-Event associations only when both roots belong to active members of the configured Keenan Vision tenant. Owners and Managers may read all such associations; Contributors may read only associations whose Track creator and Event organizer are both the acting member. Requires members:track-event:read and an active native member session. operationId: getTrackEvents security: - ApiKeyAuth: [] kvSessionCookie: [] parameters: - $ref: "#/parameters/idQuery" - name: trackId in: query type: string required: false - name: eventId in: query type: string required: false - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/TrackEventResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "500": $ref: "#/responses/ServerError" summary: Get governed Track-to-Event associations tags: - TrackEvents post: description: Creates one immutable Track-to-Event association after proving both roots belong to active members of the configured Keenan Vision tenant. Requires members:track-event:create and an active native Owner or Manager session. Identity and audit fields are server-owned. Update and delete are intentionally unsupported. operationId: postTrackEvents security: - ApiKeyAuth: [] kvSessionCookie: [] parameters: - $ref: "#/parameters/TrackEventRequest" responses: "200": $ref: "#/responses/TrackEventResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Create a governed Track-to-Event association tags: - TrackEvents /tracktopics: get: description: Reads Track-to-Topic associations through the configured tenant's governed Track boundary and only when the referenced Research Topic exists. Owners and Managers may read all bounded associations; Contributors may read associations for Tracks they created. Requires members:track-topic:read and an active native member session. operationId: getTrackTopics security: - ApiKeyAuth: [] kvSessionCookie: [] parameters: - $ref: "#/parameters/idQuery" - name: trackId in: query type: string required: false - name: topicId in: query type: string required: false - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/TrackTopicResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "500": $ref: "#/responses/ServerError" summary: Get governed Track-to-Topic associations tags: - TrackTopics post: description: Creates one immutable Track-to-Topic association after proving the Track belongs to the configured tenant and the referenced Research Topic exists. Requires members:track-topic:create and an active native Owner or Manager session. Identity, relationship keys, and audit fields are immutable; update and delete are unsupported. operationId: postTrackTopics security: - ApiKeyAuth: [] kvSessionCookie: [] parameters: - $ref: "#/parameters/TrackTopicRequest" responses: "200": $ref: "#/responses/TrackTopicResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Create a governed Track-to-Topic association tags: - TrackTopics /trackusers: get: description: Reads Track-to-User associations through the configured tenant's governed Track boundary and only for active referenced Users with an active membership in that tenant and an allowed role. Owners and Managers may read all bounded associations; Contributors may read associations for Tracks they created. Requires members:track-user:read and an active native member session. operationId: getTrackUsers security: - ApiKeyAuth: [] kvSessionCookie: [] parameters: - $ref: "#/parameters/idQuery" - name: trackId in: query type: string required: false - name: userId in: query type: string required: false - name: role in: query type: string enum: [Attendee, Moderator, Presenter] required: false - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/TrackUserResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "500": $ref: "#/responses/ServerError" summary: Get governed Track-to-User associations tags: - TrackUsers post: description: Creates one Track-to-User association after proving the Track and active referenced User belong to the configured tenant and the role is Attendee, Moderator, or Presenter. Requires members:track-user:create and an active native Owner or Manager session. Identity, TrackID, UserID, and audit fields are server-owned or immutable. operationId: postTrackUsers security: - ApiKeyAuth: [] kvSessionCookie: [] parameters: - $ref: "#/parameters/TrackUserRequest" responses: "200": $ref: "#/responses/TrackUserResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Create a governed Track-to-User association tags: - TrackUsers put: description: CAS-updates only the allowed role of one bounded Track-to-User association. Requires members:track-user:update, an active native Owner or Manager session, and the current LastModifiedDate. TrackID, UserID, identity, and creator fields remain immutable. Delete is unsupported because recovery-safe removal semantics are not governed. operationId: putTrackUsers security: - ApiKeyAuth: [] kvSessionCookie: [] parameters: - $ref: "#/parameters/TrackUserRequest" responses: "200": $ref: "#/responses/TrackUserResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "409": $ref: "#/responses/Conflict" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" summary: Update a governed Track-to-User role tags: - TrackUsers /transactions: get: description: Return tenant-scoped, payment-token-free Transaction records. Requires members:transaction:read and active Owner or Manager access in tenantId. operationId: getTransactions parameters: - $ref: "#/parameters/transactionIdQuery" - $ref: "#/parameters/transactionTenantId" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/TransactionResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Get governed tenant Transactions tags: - Transactions post: description: Create one tenant-scoped Transaction in pending state. Requires members:transaction:create and active Owner or Manager access. IDs, tenant ownership, lifecycle state, audit fields, and all payment-method references are server-owned. operationId: postTransactions parameters: - $ref: "#/parameters/TransactionRequest" - $ref: "#/parameters/transactionTenantId" responses: "200": $ref: "#/responses/TransactionResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Create a governed Transaction tags: - Transactions put: description: CAS-transition one tenant-scoped Transaction. Requires members:transaction:update, active Owner or Manager access, and the current LastModifiedDate. Amount, currency, transaction date, tenant ownership, relationships, audit fields, and payment-method references are immutable. operationId: putTransactions parameters: - $ref: "#/parameters/TransactionRequest" - $ref: "#/parameters/transactionTenantId" responses: "200": $ref: "#/responses/TransactionResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "409": $ref: "#/responses/Conflict" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] kvSessionCookie: [] summary: Transition a governed Transaction tags: - Transactions /users/onboard: post: description: Async onboard new users operationId: postUsersOnboard parameters: - $ref: "#/parameters/OnboardRequest" responses: "200": $ref: "#/responses/UserResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Async onboard new users tags: - Users /users: get: description: Return a list of User records from the datastore operationId: getUsers parameters: - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" - $ref: "#/parameters/emailQuery" - $ref: "#/parameters/auth0UserIdQuery" - $ref: "#/parameters/identityProviderQuery" - $ref: "#/parameters/identitySubjectQuery" - $ref: "#/parameters/userIdQuery" - $ref: "#/parameters/contactIdQuery" responses: "200": $ref: "#/responses/UserResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Get a list Users tags: - Users post: description: Create new Users operationId: postUsers parameters: - $ref: "#/parameters/UserRequest" responses: "200": $ref: "#/responses/UserResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Create new Users tags: - Users put: description: Update existing users operationId: putUsers parameters: - $ref: "#/parameters/UserRequest" responses: "200": $ref: "#/responses/UserResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Update existing users tags: - Users definitions: Cluster: description: Tenant-owned infrastructure metadata. TenantID, identity, and audit fields are server-owned. type: object required: [Name] properties: ID: type: string maxLength: 36 CreatedByID: type: string maxLength: 36 x-nullable: true readOnly: true CreatedDate: type: string maxLength: 64 x-nullable: true readOnly: true Description: type: string maxLength: 255 x-nullable: true Environment: type: string maxLength: 255 x-nullable: true Gateway: type: string maxLength: 255 x-nullable: true IPAddress: type: string maxLength: 255 x-nullable: true LastModifiedByID: type: string maxLength: 36 x-nullable: true readOnly: true LastModifiedDate: type: string maxLength: 64 x-nullable: true Name: type: string minLength: 1 maxLength: 255 x-nullable: true OwnerID: type: string maxLength: 36 x-nullable: true Ref: type: string maxLength: 255 x-nullable: true Status: type: string maxLength: 255 x-nullable: true Subnet: type: string maxLength: 255 x-nullable: true TenantID: type: string maxLength: 36 x-nullable: true readOnly: true Type: type: string maxLength: 255 x-nullable: true Zone: type: string maxLength: 255 x-nullable: true Track: description: A governed Track root. The schema has no tenant key, so Members derives ownership from the server-owned creator and active Keenan Vision tenant membership. type: object properties: ID: type: string CreatedByID: type: string x-nullable: true CreatedDate: type: string x-nullable: true Description: type: string x-nullable: true ImageAltText: type: string maxLength: 250 x-nullable: true ImageURL: type: string maxLength: 255 x-nullable: true LastModifiedByID: type: string x-nullable: true LastModifiedDate: type: string x-nullable: true Logo: type: string maxLength: 255 x-nullable: true Name: type: string maxLength: 80 Slug: type: string maxLength: 80 x-provider-ownership: creator-active-in-configured-keenan-vision-tenant TrackRequest: description: Exactly one Track record type: object properties: Data: type: array minItems: 1 maxItems: 1 items: $ref: "#/definitions/Track" TrackResponse: description: An array of governed Track records type: object properties: Data: type: array items: $ref: "#/definitions/Track" Meta: $ref: "#/definitions/ResponseMeta" TrackEvent: description: An immutable governed association between a tenant-bounded Track and Event. Both relationship keys and all identity and audit fields are immutable after creation. type: object properties: ID: type: string CreatedByID: type: string x-nullable: true CreatedDate: type: string x-nullable: true EventID: type: string LastModifiedByID: type: string x-nullable: true LastModifiedDate: type: string x-nullable: true TrackID: type: string x-provider-ownership: both-roots-active-in-configured-keenan-vision-tenant TrackEventRequest: description: Exactly one Track-to-Event association type: object properties: Data: type: array minItems: 1 maxItems: 1 items: $ref: "#/definitions/TrackEvent" TrackEventResponse: description: An array of governed Track-to-Event associations type: object properties: Data: type: array items: $ref: "#/definitions/TrackEvent" Meta: $ref: "#/definitions/ResponseMeta" TrackTopic: description: An immutable governed association between a tenant-bounded Track and an existing Research Topic. Relationship identity and audit fields are immutable after creation. type: object properties: ID: type: string CreatedByID: type: string x-nullable: true CreatedDate: type: string x-nullable: true LastModifiedByID: type: string x-nullable: true LastModifiedDate: type: string x-nullable: true TopicID: type: string TrackID: type: string x-provider-ownership: track-creator-active-in-configured-keenan-vision-tenant x-reference-validation: research.topic TrackTopicRequest: description: Exactly one Track-to-Topic association type: object properties: Data: type: array minItems: 1 maxItems: 1 items: $ref: "#/definitions/TrackTopic" TrackTopicResponse: description: An array of governed Track-to-Topic associations type: object properties: Data: type: array items: $ref: "#/definitions/TrackTopic" Meta: $ref: "#/definitions/ResponseMeta" TrackUser: description: A governed association between a tenant-bounded Track and an active User in the same configured tenant. TrackID and UserID are immutable; only Role may be CAS-updated. type: object properties: ID: type: string CreatedByID: type: string x-nullable: true CreatedDate: type: string x-nullable: true LastModifiedByID: type: string x-nullable: true LastModifiedDate: type: string x-nullable: true Role: type: string enum: [Attendee, Moderator, Presenter] TrackID: type: string UserID: type: string x-provider-ownership: track-creator-active-in-configured-keenan-vision-tenant x-reference-validation: active-user-membership-in-configured-keenan-vision-tenant TrackUserRequest: description: Exactly one Track-to-User association or role-only CAS update type: object properties: Data: type: array minItems: 1 maxItems: 1 items: $ref: "#/definitions/TrackUser" TrackUserResponse: description: An array of governed Track-to-User associations type: object properties: Data: type: array items: $ref: "#/definitions/TrackUser" Meta: $ref: "#/definitions/ResponseMeta" AuditFields: type: object properties: id: {type: string, format: uuid, description: Server-generated on create; required in collection PUT bodies.} createdById: {type: string, format: uuid, x-nullable: true, readOnly: true} createdDate: {type: string, format: date-time, x-nullable: true, readOnly: true} lastModifiedById: {type: string, format: uuid, x-nullable: true, readOnly: true} lastModifiedDate: {type: string, format: date-time, x-nullable: true, description: "Server-generated optimistic concurrency token; required for Brand, Service, ServiceScope, and BrandService PUT bodies."} Brand: allOf: - $ref: "#/definitions/AuditFields" - type: object required: [brandKey, name, domain, status] properties: brandKey: {type: string, minLength: 1, maxLength: 80} name: {type: string, minLength: 1, maxLength: 255} domain: {type: string, minLength: 1, maxLength: 255} status: {type: string, enum: [active, inactive, retired]} Service: allOf: - $ref: "#/definitions/AuditFields" - type: object required: [serviceKey, name, ownerSystem, status] properties: serviceKey: {type: string, minLength: 1, maxLength: 80} name: {type: string, minLength: 1, maxLength: 255} description: {type: string, x-nullable: true} ownerSystem: {type: string, enum: [members, crm, research, plex, external]} contractRef: {type: string, maxLength: 255, x-nullable: true} status: {type: string, enum: [draft, active, retired]} BrandService: allOf: - $ref: "#/definitions/AuditFields" - type: object required: [brandId, serviceId, status] properties: brandId: {type: string, format: uuid} serviceId: {type: string, format: uuid} status: {type: string, enum: [active, inactive]} ServiceScope: allOf: - $ref: "#/definitions/AuditFields" - type: object required: [serviceId, scopeKey, status] properties: serviceId: {type: string, format: uuid} scopeKey: {type: string, minLength: 1, maxLength: 120} description: {type: string, x-nullable: true} status: {type: string, enum: [active, retired]} Plan: allOf: - $ref: "#/definitions/AuditFields" - type: object required: [planKey, version, name, status, currency, unitAmount, billingPeriod] properties: planKey: {type: string, minLength: 1, maxLength: 80} version: {type: integer, format: int32, minimum: 1, maximum: 2147483647} name: {type: string, minLength: 1, maxLength: 255} description: {type: string, x-nullable: true} status: {type: string, enum: [draft, active, retired]} currency: {type: string, minLength: 3, maxLength: 3} unitAmount: {type: string, minLength: 1, maxLength: 13, pattern: '^(0|[1-9][0-9]{0,9})(\.[0-9]{1,2})?$', description: "Exact decimal string matching SQL DECIMAL(12,2)."} billingPeriod: {type: string, enum: [none, month, year, custom]} effectiveFrom: {type: string, format: date-time, x-nullable: true} effectiveUntil: {type: string, format: date-time, x-nullable: true} BrandPlan: allOf: - $ref: "#/definitions/AuditFields" - type: object required: [brandId, planId, status] properties: brandId: {type: string, format: uuid} planId: {type: string, format: uuid} status: {type: string, enum: [active, inactive]} PlanService: allOf: - $ref: "#/definitions/AuditFields" - type: object required: [planId, serviceId, grantMode, limitPeriod] properties: planId: {type: string, format: uuid} serviceId: {type: string, format: uuid} grantMode: {type: string, enum: [included, metered]} unit: {type: string, maxLength: 40, x-nullable: true} limitQuantity: {type: string, minLength: 1, maxLength: 21, pattern: '^(0|[1-9][0-9]{0,13})(\.[0-9]{1,6})?$', x-nullable: true, description: "Exact decimal string matching SQL DECIMAL(20,6); null means unlimited. This wave does not meter or decrement it."} limitPeriod: {type: string, enum: [none, day, month, billing_period, lifetime]} Subscription: allOf: - $ref: "#/definitions/AuditFields" - type: object required: [tenantId, planId, status, startsAt] properties: tenantId: {type: string, format: uuid} planId: {type: string, format: uuid} status: {type: string, enum: [trialing, active, past_due, paused, canceled, expired]} startsAt: {type: string, format: date-time} currentPeriodStart: {type: string, format: date-time, x-nullable: true} currentPeriodEnd: {type: string, format: date-time, x-nullable: true} endsAt: {type: string, format: date-time, x-nullable: true} cancelAtPeriodEnd: {type: boolean, default: false} paymentMethodId: {type: string, format: uuid, x-nullable: true} provider: {type: string, minLength: 1, maxLength: 80, x-nullable: true, description: Non-secret provider name; blank values are normalized to null.} externalCustomerId: {type: string, minLength: 1, maxLength: 255, x-nullable: true, description: Non-secret provider reference; blank values are normalized to null.} externalSubscriptionId: {type: string, minLength: 1, maxLength: 255, x-nullable: true, description: Non-secret provider reference; blank values are normalized to null.} Entitlement: allOf: - $ref: "#/definitions/AuditFields" - type: object required: [tenantId, serviceId, source, effect, status, effectiveFrom] properties: tenantId: {type: string, format: uuid} userId: {type: string, format: uuid, x-nullable: true, description: Null means tenant-level; non-null must belong to the tenant.} serviceId: {type: string, format: uuid} subscriptionId: {type: string, format: uuid, x-nullable: true} source: {type: string, enum: [subscription, manual, trial, promotion]} effect: {type: string, enum: [allow, deny]} status: {type: string, enum: [scheduled, active, revoked, expired]} effectiveFrom: {type: string, format: date-time} effectiveUntil: {type: string, format: date-time, x-nullable: true} unit: {type: string, maxLength: 40, x-nullable: true} limitQuantity: {type: string, minLength: 1, maxLength: 21, pattern: '^(0|[1-9][0-9]{0,13})(\.[0-9]{1,6})?$', x-nullable: true, description: "Exact decimal string matching SQL DECIMAL(20,6)."} limitPeriod: {type: string, enum: [none, day, month, billing_period, lifetime], x-nullable: true} revokedAt: {type: string, format: date-time, x-nullable: true, readOnly: true} revokedById: {type: string, format: uuid, x-nullable: true, readOnly: true} EffectiveEntitlement: type: object required: [tenantId, serviceId, effect, provenance, evaluatedAt, limit] properties: tenantId: {type: string, format: uuid} userId: {type: string, format: uuid, x-nullable: true} serviceId: {type: string, format: uuid} effect: {type: string, enum: [allow, deny]} effectiveFrom: {type: string, format: date-time, x-nullable: true} effectiveUntil: {type: string, format: date-time, x-nullable: true} evaluatedAt: {type: string, format: date-time} provenance: {type: string, enum: [user_entitlement, tenant_entitlement, subscription_plan]} limit: {$ref: "#/definitions/DescriptiveLimit"} DescriptiveLimit: type: object required: [unlimited, period] properties: unlimited: {type: boolean} unit: {type: string, maxLength: 40, x-nullable: true} quantity: {type: string, minLength: 1, maxLength: 21, pattern: '^(0|[1-9][0-9]{0,13})(\.[0-9]{1,6})?$', x-nullable: true, description: "Exact decimal string matching SQL DECIMAL(20,6)."} period: {type: string, enum: [none, day, month, billing_period, lifetime]} enforced: {type: boolean, default: false, description: Always false in this wave; usage accounting is deferred.} AuthorizedClient: allOf: - $ref: "#/definitions/AuditFields" - type: object required: [tenantId, clientIdentifier, clientType, displayName, status] description: Non-secret connection metadata. Token, secret, API-key, and cookie properties are deliberately absent. properties: tenantId: {type: string, format: uuid} userId: {type: string, format: uuid, x-nullable: true, description: Null means tenant-level; non-null must belong to the tenant.} clientIdentifier: {type: string, minLength: 1, maxLength: 255} clientType: {type: string, enum: [mcp, api]} displayName: {type: string, minLength: 1, maxLength: 255} softwareId: {type: string, maxLength: 255, x-nullable: true} softwareVersion: {type: string, maxLength: 80, x-nullable: true} clientUri: {type: string, maxLength: 2048, x-nullable: true} externalConnectionId: {type: string, maxLength: 255, x-nullable: true, description: Non-secret external reference.} status: {type: string, enum: [pending, active, revoked, expired]} approvedAt: {type: string, format: date-time, x-nullable: true, readOnly: true} lastUsedAt: {type: string, format: date-time, x-nullable: true, readOnly: true} expiresAt: {type: string, format: date-time, x-nullable: true} revokedAt: {type: string, format: date-time, x-nullable: true, readOnly: true} revokedById: {type: string, format: uuid, x-nullable: true, readOnly: true} AuthorizedClientScope: allOf: - $ref: "#/definitions/AuditFields" - type: object required: [authorizedClientId, serviceScopeId] properties: authorizedClientId: {type: string, format: uuid} serviceScopeId: {type: string, format: uuid} TenantMembership: allOf: - $ref: "#/definitions/TenantMembershipAuditFields" - type: object required: [tenantId, userId, email, accessLevel, status] properties: tenantId: {type: string, minLength: 1, maxLength: 36} userId: {type: string, format: uuid} email: {type: string, format: email, readOnly: true} fullName: {type: string, x-nullable: true, readOnly: true} accessLevel: {type: string, enum: [owner, manager, member, read_only]} status: {type: string, enum: [active, suspended, revoked]} TenantMembershipAuditFields: type: object required: [id, createdDate, lastModifiedDate] properties: id: {type: string, format: uuid, description: Server-generated membership identifier.} createdById: {type: string, format: uuid, x-nullable: true, readOnly: true} createdDate: {type: string, format: date-time, description: Server-owned UTC creation timestamp.} lastModifiedById: {type: string, format: uuid, x-nullable: true, readOnly: true} lastModifiedDate: {type: string, format: date-time, description: Server-owned optimistic concurrency token.} TenantMembershipCreate: type: object required: [tenantId, accessLevel] description: Exactly one of userId or email is required; Members validates the exclusive selector transactionally. properties: tenantId: {type: string, minLength: 1, maxLength: 36} userId: {type: string, format: uuid, x-nullable: true} email: {type: string, format: email, x-nullable: true} accessLevel: {type: string, enum: [owner, manager, member, read_only]} status: {type: string, enum: [active, suspended, revoked], default: active} TenantMembershipUpdate: type: object required: [lastModifiedDate] properties: accessLevel: {type: string, enum: [owner, manager, member, read_only], x-nullable: true} status: {type: string, enum: [active, suspended, revoked], x-nullable: true} lastModifiedDate: {type: string, format: date-time, description: Optimistic concurrency token from the latest representation.} ManageableTenant: type: object required: [id, tenantName, actorAccessLevel] properties: id: {type: string, minLength: 1, maxLength: 36} tenantName: {type: string} tenantType: {type: string, x-nullable: true} status: {type: string, x-nullable: true} active: {type: boolean, x-nullable: true} actorAccessLevel: {type: string, enum: [estate_administrator, owner, manager]} PortalMeta: type: object properties: operationId: {type: string} serverTimestamp: {type: string, format: date-time} limit: {type: integer, format: int64} offset: {type: integer, format: int64} BrandRequest: {type: object, required: [Data], properties: {Data: {type: array, items: {$ref: "#/definitions/Brand"}}}} BrandResponse: {type: object, required: [Data, Meta], properties: {Data: {type: array, items: {$ref: "#/definitions/Brand"}}, Meta: {$ref: "#/definitions/PortalMeta"}}} ServiceRequest: {type: object, required: [Data], properties: {Data: {type: array, items: {$ref: "#/definitions/Service"}}}} ServiceResponse: {type: object, required: [Data, Meta], properties: {Data: {type: array, items: {$ref: "#/definitions/Service"}}, Meta: {$ref: "#/definitions/PortalMeta"}}} BrandServiceRequest: {type: object, required: [Data], properties: {Data: {type: array, items: {$ref: "#/definitions/BrandService"}}}} BrandServiceResponse: {type: object, required: [Data, Meta], properties: {Data: {type: array, items: {$ref: "#/definitions/BrandService"}}, Meta: {$ref: "#/definitions/PortalMeta"}}} ServiceScopeRequest: {type: object, required: [Data], properties: {Data: {type: array, items: {$ref: "#/definitions/ServiceScope"}}}} ServiceScopeResponse: {type: object, required: [Data, Meta], properties: {Data: {type: array, items: {$ref: "#/definitions/ServiceScope"}}, Meta: {$ref: "#/definitions/PortalMeta"}}} PlanRequest: {type: object, required: [Data], properties: {Data: {type: array, items: {$ref: "#/definitions/Plan"}}}} PlanResponse: {type: object, required: [Data, Meta], properties: {Data: {type: array, items: {$ref: "#/definitions/Plan"}}, Meta: {$ref: "#/definitions/PortalMeta"}}} BrandPlanRequest: {type: object, required: [Data], properties: {Data: {type: array, items: {$ref: "#/definitions/BrandPlan"}}}} BrandPlanResponse: {type: object, required: [Data, Meta], properties: {Data: {type: array, items: {$ref: "#/definitions/BrandPlan"}}, Meta: {$ref: "#/definitions/PortalMeta"}}} PlanServiceRequest: {type: object, required: [Data], properties: {Data: {type: array, items: {$ref: "#/definitions/PlanService"}}}} PlanServiceResponse: {type: object, required: [Data, Meta], properties: {Data: {type: array, items: {$ref: "#/definitions/PlanService"}}, Meta: {$ref: "#/definitions/PortalMeta"}}} SubscriptionRequest: {type: object, required: [Data], properties: {Data: {type: array, items: {$ref: "#/definitions/Subscription"}}}} SubscriptionResponse: {type: object, required: [Data, Meta], properties: {Data: {type: array, items: {$ref: "#/definitions/Subscription"}}, Meta: {$ref: "#/definitions/PortalMeta"}}} EntitlementRequest: {type: object, required: [Data], properties: {Data: {type: array, items: {$ref: "#/definitions/Entitlement"}}}} EntitlementResponse: {type: object, required: [Data, Meta], properties: {Data: {type: array, items: {$ref: "#/definitions/Entitlement"}}, Meta: {$ref: "#/definitions/PortalMeta"}}} EffectiveEntitlementResponse: {type: object, required: [Data, Meta], properties: {Data: {type: array, items: {$ref: "#/definitions/EffectiveEntitlement"}}, Meta: {$ref: "#/definitions/PortalMeta"}}} AuthorizedClientRequest: {type: object, required: [Data], properties: {Data: {type: array, items: {$ref: "#/definitions/AuthorizedClient"}}}} AuthorizedClientResponse: {type: object, required: [Data, Meta], properties: {Data: {type: array, items: {$ref: "#/definitions/AuthorizedClient"}}, Meta: {$ref: "#/definitions/PortalMeta"}}} AuthorizedClientScopeRequest: {type: object, required: [Data], properties: {Data: {type: array, items: {$ref: "#/definitions/AuthorizedClientScope"}}}} AuthorizedClientScopeResponse: {type: object, required: [Data, Meta], properties: {Data: {type: array, items: {$ref: "#/definitions/AuthorizedClientScope"}}, Meta: {$ref: "#/definitions/PortalMeta"}}} TenantMembershipCreateRequest: {type: object, required: [Data], properties: {Data: {$ref: "#/definitions/TenantMembershipCreate"}}} TenantMembershipUpdateRequest: {type: object, required: [Data], properties: {Data: {$ref: "#/definitions/TenantMembershipUpdate"}}} TenantMembershipResponse: {type: object, required: [Data, Meta], properties: {Data: {$ref: "#/definitions/TenantMembership"}, Meta: {$ref: "#/definitions/PortalMeta"}}} TenantMembershipListResponse: {type: object, required: [Data, Meta], properties: {Data: {type: array, items: {$ref: "#/definitions/TenantMembership"}}, Meta: {$ref: "#/definitions/PortalMeta"}}} ManageableTenantResponse: {type: object, required: [Data, Meta], properties: {Data: {type: array, items: {$ref: "#/definitions/ManageableTenant"}}, Meta: {$ref: "#/definitions/PortalMeta"}}} OnboardRequest: description: Self-service onboarding request. The plaintext password is hashed server-side with the members pepper; it is never stored or logged in plaintext. type: object required: - email - password properties: email: description: Login email (stored lowercased) type: string format: email password: type: string format: password description: Plaintext password; Members enforces 12-64 valid UTF-8 bytes before hashing. firstName: description: First name type: string lastName: description: Last name type: string companyName: description: Company name type: string PasswordChangeRequest: description: Secret-bearing request. Values are never logged, stored raw, echoed, or generated into response models. type: object required: [currentPassword, newPassword] properties: currentPassword: type: string format: password description: Plaintext current password; verified only in memory and never logged. newPassword: type: string format: password description: Plaintext new password; Members enforces 12-64 valid UTF-8 bytes. PasswordRecoveryRequest: description: Recovery selector accepted uniformly regardless of account state. type: object required: [email] properties: email: type: string format: email maxLength: 320 PasswordRecoveryCompletion: description: Secret-bearing single-use recovery completion request. type: object required: [token, newPassword] properties: token: type: string minLength: 32 maxLength: 512 newPassword: type: string format: password description: Plaintext new password; Members enforces 12-64 valid UTF-8 bytes. PasswordRecoveryAccepted: type: object required: [status] properties: status: type: string enum: [accepted] EmailAuthenticationRequest: description: Initial email-authentication selector accepted uniformly regardless of account or verification state. type: object required: [email] properties: email: type: string format: email maxLength: 320 EmailAuthenticationCompletion: description: Secret-bearing, single-use initial email-authentication completion request. type: object required: [token] properties: token: type: string minLength: 32 maxLength: 512 EmailAuthenticationSession: description: Sanitized native user created by an initial email-authentication completion. type: object required: [user] properties: user: $ref: "../../lib/swagger/defs/user.yaml#/User" AttendeeRequest: description: An array of Attendee objects properties: Data: items: $ref: "../../lib/swagger/defs/attendee.yaml#/Attendee" type: array type: object AttendeeResponse: description: An array of Attendee objects properties: Data: items: $ref: "../../lib/swagger/defs/attendee.yaml#/Attendee" type: array type: object ClusterRequest: description: Exactly one governed Cluster object required: [Data] properties: Data: items: $ref: "#/definitions/Cluster" minItems: 1 maxItems: 1 type: array type: object ClusterResponse: description: An array of governed tenant Cluster objects properties: Data: items: $ref: "#/definitions/Cluster" type: array Meta: $ref: "#/definitions/ResponseMeta" type: object Course: description: Estate-global course catalog record. Tenant ownership is intentionally absent from the current schema. type: object properties: ID: type: string CreatedByID: type: string x-nullable: true CreatedDate: type: string x-nullable: true Description: type: string x-nullable: true Fulldescription: type: string x-nullable: true ImageAltText: type: string x-nullable: true ImageURL: type: string x-nullable: true InstructorID: type: string x-nullable: true LastModifiedByID: type: string x-nullable: true LastModifiedDate: type: string x-nullable: true Logo: type: string x-nullable: true Price: description: Exact base-10 representation of DECIMAL(10,2). type: string pattern: '^[0-9]{1,8}(\.[0-9]{1,2})?$' x-nullable: true Slug: type: string maxLength: 80 x-nullable: true TemplateID: type: string x-nullable: true Title: type: string maxLength: 255 x-nullable: true CourseSection: description: Estate-global section linked to one Course. type: object properties: ID: type: string Content: type: string x-nullable: true CourseID: type: string x-nullable: true CreatedByID: type: string x-nullable: true CreatedDate: type: string x-nullable: true ImageAltText: type: string x-nullable: true ImageURL: type: string x-nullable: true LastModifiedByID: type: string x-nullable: true LastModifiedDate: type: string x-nullable: true Logo: type: string x-nullable: true Order: type: integer format: int64 x-nullable: true Slug: type: string maxLength: 80 x-nullable: true Title: type: string maxLength: 255 x-nullable: true CourseLesson: description: Estate-global lesson linked to one CourseSection. type: object properties: ID: type: string Content: type: string x-nullable: true CreatedByID: type: string x-nullable: true CreatedDate: type: string x-nullable: true ImageAltText: type: string x-nullable: true ImageURL: type: string x-nullable: true LastModifiedByID: type: string x-nullable: true LastModifiedDate: type: string x-nullable: true Logo: type: string x-nullable: true Order: type: integer format: int64 x-nullable: true SectionID: description: Persisted as coursesectionid. type: string x-nullable: true Slug: type: string maxLength: 80 x-nullable: true Title: type: string maxLength: 255 x-nullable: true VideoURL: type: string x-nullable: true CourseLessonRequest: description: Exactly one CourseLesson object properties: Data: items: $ref: "#/definitions/CourseLesson" minItems: 1 maxItems: 1 type: array type: object CourseLessonResponse: description: An array of CourseLesson objects properties: Data: items: $ref: "#/definitions/CourseLesson" type: array Meta: $ref: "#/definitions/ResponseMeta" type: object CourseRequest: description: Exactly one Course object properties: Data: items: $ref: "#/definitions/Course" minItems: 1 maxItems: 1 type: array type: object CourseResponse: description: An array of Course objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "#/definitions/Course" type: array type: object CourseSectionRequest: description: Exactly one CourseSection object properties: Data: items: $ref: "#/definitions/CourseSection" minItems: 1 maxItems: 1 type: array type: object CourseSectionResponse: description: An array of CourseSection objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "#/definitions/CourseSection" type: array type: object DatabaseMetadata: description: Credential-free metadata for a Database provisioned and owned by a Tenant type: object required: - ID - TenantID properties: ID: description: Server-owned Database record ID type: string format: uuid Active: description: Whether the Database is active type: boolean x-nullable: true ClusterID: description: Optional Cluster in the same Tenant type: string format: uuid x-nullable: true CreatedDate: description: Server-owned creation timestamp type: string format: date-time x-nullable: true DatabaseName: description: Physical Database name type: string x-nullable: true LastModifiedDate: description: Server-owned modification timestamp type: string format: date-time x-nullable: true Status: description: Database status metadata type: string x-nullable: true TenantID: description: Tenant that owns the Database type: string format: uuid Type: description: Database engine type type: string x-nullable: true DatabaseMetadataResponse: description: Tenant-bound Database metadata with DSN and provisioning credentials omitted type: object properties: Data: type: array items: $ref: "#/definitions/DatabaseMetadata" Meta: $ref: "#/definitions/ResponseMeta" DatabaseRequest: description: An array of Database objects properties: Data: items: $ref: "../../lib/swagger/defs/database.yaml#/Database" type: array type: object DatabaseResponse: description: An array of Database objects properties: Data: items: $ref: "../../lib/swagger/defs/database.yaml#/Database" type: array Meta: $ref: "#/definitions/ResponseMeta" type: object Document: description: Tenant-owned content document type: object properties: ID: type: string AccessControlList: type: string x-nullable: true Author: type: string x-nullable: true ContentType: type: string x-nullable: true CreatedByID: type: string x-nullable: true CreatedDate: type: string x-nullable: true Description: type: string x-nullable: true DocumentDate: type: string x-nullable: true DocumentType: type: string x-nullable: true FolderID: type: string x-nullable: true ImageAltText: type: string x-nullable: true ImageURL: type: string x-nullable: true Language: type: string x-nullable: true LastModifiedByID: type: string x-nullable: true LastModifiedDate: type: string x-nullable: true Logo: type: string x-nullable: true Name: type: string x-nullable: true ObjectID: type: string x-nullable: true ObjectType: type: string x-nullable: true Slug: type: string x-nullable: true Source: type: string x-nullable: true Status: type: string x-nullable: true TenantID: type: string x-nullable: true Title: type: string x-nullable: true URL: type: string x-nullable: true UserID: type: string x-nullable: true Version: type: string x-nullable: true Folder: description: Tenant-owned content folder type: object properties: ID: type: string AccountID: type: string x-nullable: true CreatedByID: type: string x-nullable: true CreatedDate: type: string x-nullable: true Description: type: string x-nullable: true LastModifiedByID: type: string x-nullable: true LastModifiedDate: type: string x-nullable: true Name: type: string x-nullable: true ObjectID: type: string x-nullable: true ObjectType: type: string x-nullable: true ParentFolderID: type: string x-nullable: true Status: type: string x-nullable: true TenantID: type: string x-nullable: true UserID: type: string x-nullable: true DocumentParameter: description: Tenant-owned document parameter type: object properties: ID: type: string CreatedByID: type: string x-nullable: true CreatedDate: type: string x-nullable: true DeletedDate: type: string x-nullable: true DocumentID: type: string x-nullable: true IsDeleted: type: boolean x-nullable: true LastModifiedByID: type: string x-nullable: true LastModifiedDate: type: string x-nullable: true Name: type: string x-nullable: true TenantID: type: string x-nullable: true UserID: type: string x-nullable: true Value: type: string x-nullable: true DocumentRequest: description: An array of Document objects properties: Data: items: $ref: "#/definitions/Document" type: array type: object DocumentResponse: description: An array of Document objects properties: Data: items: $ref: "#/definitions/Document" type: array Meta: $ref: "#/definitions/ResponseMeta" type: object FolderRequest: description: An array of Folder objects properties: Data: items: $ref: "#/definitions/Folder" type: array type: object FolderResponse: description: An array of Folder objects properties: Data: items: $ref: "#/definitions/Folder" type: array Meta: $ref: "#/definitions/ResponseMeta" type: object DocumentParameterRequest: description: An array of DocumentParameter objects required: - Data properties: Data: items: $ref: "#/definitions/DocumentParameter" minItems: 1 maxItems: 100 type: array type: object DocumentParameterResponse: description: An array of DocumentParameter objects properties: Data: items: $ref: "#/definitions/DocumentParameter" type: array Meta: $ref: "#/definitions/ResponseMeta" type: object EmailMessageRequest: description: An array Send Email Message objects properties: data: items: $ref: "../../lib/swagger/defs/email-message.yaml#/EmailMessage" type: array meta: $ref: "#/definitions/RequestMeta" type: object EmailMessagesResponse: description: An array user objects properties: data: items: $ref: "../../lib/swagger/defs/email-message.yaml#/EmailMessage" type: array meta: $ref: "#/definitions/ResponseMeta" type: object Enrollment: description: User-global enrollment. TenantID is intentionally absent from the current schema, so cross-user tenant-manager access is unavailable. type: object properties: ID: type: string Completed: type: boolean x-nullable: true CourseID: type: string x-nullable: true CreatedByID: type: string x-nullable: true CreatedDate: type: string x-nullable: true EnrollmentDate: type: string format: date x-nullable: true LastModifiedByID: type: string x-nullable: true LastModifiedDate: type: string x-nullable: true UserID: type: string x-nullable: true EnrollmentRequest: description: Exactly one Enrollment object properties: Data: items: $ref: "#/definitions/Enrollment" minItems: 1 maxItems: 1 type: array type: object EnrollmentResponse: description: An array of Enrollment objects properties: Data: items: $ref: "#/definitions/Enrollment" type: array type: object EventRequest: description: An array of Event objects properties: Data: items: $ref: "../../lib/swagger/defs/event.yaml#/Event" type: array type: object EventResponse: description: An array of Event objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "../../lib/swagger/defs/event.yaml#/Event" type: array type: object EventCategoryRequest: description: An array of EventCategory objects properties: Data: items: $ref: "../../lib/swagger/defs/event-category.yaml#/EventCategory" type: array type: object EventCategoryResponse: description: An array of EventCategory objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "../../lib/swagger/defs/event-category.yaml#/EventCategory" type: array type: object FavoriteRequest: description: An array of Favorite objects properties: Data: items: $ref: "../../lib/swagger/defs/favorite.yaml#/Favorite" type: array type: object FavoriteResponse: description: An array of Favorite objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "../../lib/swagger/defs/favorite.yaml#/Favorite" type: array type: object InvoiceRequest: description: An array of Invoice objects properties: Data: items: $ref: "../../lib/swagger/defs/invoice.yaml#/Invoice" type: array type: object InvoiceResponse: description: An array of Invoice objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "../../lib/swagger/defs/invoice.yaml#/Invoice" type: array type: object IssuedCertificate: description: Sanitized user-global issuance evidence. VerificationCode is intentionally excluded from this contract. type: object properties: ID: type: string AccountID: type: string x-nullable: true CreatedByID: type: string x-nullable: true CreatedDate: type: string x-nullable: true EnrollmentID: type: string x-nullable: true ExpirationDate: type: string x-nullable: true IssueDate: type: string x-nullable: true LastModifiedByID: type: string x-nullable: true LastModifiedDate: type: string x-nullable: true TemplateID: type: string x-nullable: true UserID: type: string x-nullable: true IssuedCertificateResponse: description: An array of IssuedCertificate objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "#/definitions/IssuedCertificate" type: array type: object LessonProgress: description: Tenant-scoped progress for one enrollment and lesson. type: object properties: ID: type: string Completed: type: boolean CompletedAt: type: string x-nullable: true CreatedByID: type: string x-nullable: true CreatedDate: type: string x-nullable: true EnrollmentID: type: string x-nullable: true LastModifiedByID: type: string x-nullable: true LastModifiedDate: type: string x-nullable: true LessonID: type: string x-nullable: true TenantID: type: string x-nullable: true UserID: type: string x-nullable: true LessonProgressRequest: description: Exactly one LessonProgress object properties: Data: items: $ref: "#/definitions/LessonProgress" minItems: 1 maxItems: 1 type: array type: object LessonProgressResponse: description: An array of LessonProgress objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "#/definitions/LessonProgress" type: array type: object OutgoingEmailMessageRequest: description: An array New Email Message objects properties: data: items: $ref: "../../lib/swagger/defs/outgoing-email-message.yaml#/OutgoingEmailMessage" type: array type: object OutgoingEmailMessagesResponse: description: An array New Email Message objects properties: data: items: $ref: "../../lib/swagger/defs/outgoing-email-message.yaml#/OutgoingEmailMessage" type: array meta: $ref: "#/definitions/ResponseMeta" type: object OrderRequest: description: An array of Order objects properties: Data: items: $ref: "../../lib/swagger/defs/order.yaml#/Order" type: array type: object OrderResponse: description: An array of Order objects properties: Data: items: $ref: "../../lib/swagger/defs/order.yaml#/Order" type: array type: object Pagination: properties: Limit: format: int64 type: integer POffset: format: int64 type: integer PageSize: format: int64 type: integer SetSize: format: int64 type: integer type: object PaymentMethodRequest: description: An array of PaymentMethod objects properties: Data: items: $ref: "../../lib/swagger/defs/payment-method.yaml#/PaymentMethod" type: array type: object PaymentMethodResponse: description: An array of PaymentMethod objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "../../lib/swagger/defs/payment-method.yaml#/PaymentMethod" type: array type: object PromptAnswerRequest: description: An array of Prompt objects properties: Data: items: $ref: "../../lib/swagger/defs/prompt-answer.yaml#/PromptAnswer" type: array type: object PromptAnswerResponse: description: An array of PromptResponse objects properties: Data: items: $ref: "../../lib/swagger/defs/prompt-answer.yaml#/PromptAnswer" type: array Meta: $ref: "#/definitions/ResponseMeta" type: object PromptRequest: description: An array of Prompt objects properties: Data: items: $ref: "../../lib/swagger/defs/prompt.yaml#/Prompt" type: array type: object PromptResponse: description: An array of Prompt objects properties: Data: items: $ref: "../../lib/swagger/defs/prompt.yaml#/Prompt" type: array Meta: $ref: "#/definitions/ResponseMeta" type: object PromptCategoryRequest: description: An array of PromptCategory objects properties: Data: items: $ref: "../../lib/swagger/defs/prompt-category.yaml#/PromptCategory" type: array type: object PromptCategoryResponse: description: An array of PromptCategory objects properties: Data: items: $ref: "../../lib/swagger/defs/prompt-category.yaml#/PromptCategory" type: array Meta: $ref: "#/definitions/ResponseMeta" type: object PromptTagRequest: description: An array of PromptTag objects properties: Data: items: $ref: "../../lib/swagger/defs/prompt-tag.yaml#/PromptTag" type: array type: object PromptTagResponse: description: An array of PromptTag objects properties: Data: items: $ref: "../../lib/swagger/defs/prompt-tag.yaml#/PromptTag" type: array Meta: $ref: "#/definitions/ResponseMeta" type: object RequestMeta: properties: ExternalAccount: description: Account Number of the Reseller or OEM type: string x-nullable: true required: - ExternalAccount type: object ResearchProjectCompanyRequest: description: An array of ResearchProjectCompany objects properties: Data: items: $ref: "../../lib/swagger/defs/research-project-company.yaml#/ResearchProjectCompany" type: array type: object ResearchProjectCompanyResponse: description: An array of ResearchProjectCompany objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "../../lib/swagger/defs/research-project-company.yaml#/ResearchProjectCompany" type: array type: object ResearchProjectRequest: description: An array of ResearchProject objects properties: Data: items: $ref: "../../lib/swagger/defs/research-project.yaml#/ResearchProject" type: array type: object ResearchProjectResponse: description: An array of ResearchProject objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "../../lib/swagger/defs/research-project.yaml#/ResearchProject" type: array type: object ResearchProjectDocumentRequest: description: An array of ResearchProjectDocumentRequest objects properties: Data: items: $ref: "../../lib/swagger/defs/research-project-document.yaml#/ResearchProjectDocument" type: array type: object ResearchProjectDocumentResponse: description: An array of ResearchProjectDocumentResponse objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "../../lib/swagger/defs/research-project-document.yaml#/ResearchProjectDocument" type: array type: object ResearchProjectProductRequest: description: An array of ResearchProjectProduct objects properties: Data: items: $ref: "../../lib/swagger/defs/research-project-product.yaml#/ResearchProjectProduct" type: array type: object ResearchProjectProductResponse: description: An array of ResearchProjectProduct objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "../../lib/swagger/defs/research-project-product.yaml#/ResearchProjectProduct" type: array type: object ResearchProjectServiceResponse: description: An array of ResearchProjectService objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "../../lib/swagger/defs/research-project-service.yaml#/ResearchProjectService" type: array type: object ResearchProjectServiceRequest: description: An array of ResearchProjectService objects properties: Data: items: $ref: "../../lib/swagger/defs/research-project-service.yaml#/ResearchProjectService" type: array type: object ResearchProjectTopicRequest: description: An array of ResearchProjectTopic objects properties: Data: items: $ref: "../../lib/swagger/defs/research-project-topic.yaml#/ResearchProjectTopic" type: array type: object ResearchProjectTopicResponse: description: An array of ResearchProjectTopic objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "../../lib/swagger/defs/research-project-topic.yaml#/ResearchProjectTopic" type: array type: object ResponseMeta: properties: Contact: description: Microservice Contact Info type: string Copyright: description: Copyright Info type: string License: description: License Information and Restrictions type: string OperationID: description: Operation ID type: string Pagination: $ref: "#/definitions/Pagination" RequestIP: description: Request IP Address type: string RequestType: description: Request Type type: string RequestURL: description: Request URL type: string ServerInfo: description: Data Server Info type: string ServerResponseTime: description: Data Server Response Time (ms) type: string ServerTimestamp: description: Backend Server Timestamp type: string ExternalAccount: description: Account Number used for recording transactions type: string type: object RoleRequest: description: An array of Role objects properties: Date: items: $ref: "../../lib/swagger/defs/role.yaml#/Role" type: array type: object RoleResponse: description: An array of Role objects properties: Data: items: $ref: "../../lib/swagger/defs/role.yaml#/Role" type: array Meta: $ref: "#/definitions/ResponseMeta" type: object Template: description: Tenant-owned content template type: object properties: ID: type: string CompanyID: type: string x-nullable: true CreatedByID: type: string x-nullable: true CreatedDate: type: string x-nullable: true Description: type: string x-nullable: true HTML: type: string x-nullable: true IsActive: type: boolean x-nullable: true IsMaster: type: boolean x-nullable: true LastModifiedByID: type: string x-nullable: true LastModifiedDate: type: string x-nullable: true Name: type: string x-nullable: true ObjectType: type: string x-nullable: true OwnerID: type: string x-nullable: true RecordTypeName: type: string x-nullable: true TenantID: type: string x-nullable: true Type: type: string x-nullable: true URL: type: string x-nullable: true TemplateRequest: description: An array of Templates properties: Data: items: $ref: "#/definitions/Template" type: array type: object TemplateResponse: description: An array of Templates properties: Data: items: $ref: "#/definitions/Template" type: array Meta: $ref: "#/definitions/ResponseMeta" type: object TenantRequest: description: An array of Tenant objects properties: Data: items: $ref: "../../lib/swagger/defs/tenant.yaml#/Tenant" type: array type: object TenantResponse: description: An array of Tenant objects properties: Data: items: $ref: "../../lib/swagger/defs/tenant.yaml#/Tenant" type: array Meta: $ref: "#/definitions/ResponseMeta" type: object TicketRequest: description: An array of Ticket objects properties: Data: items: $ref: "../../lib/swagger/defs/ticket.yaml#/Ticket" type: array type: object TicketResponse: description: An array of Ticket objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "../../lib/swagger/defs/ticket.yaml#/Ticket" type: array type: object Transaction: description: Tenant-owned commercial transaction metadata. PaymentMethodID and processor material are deliberately absent. TenantID, identity, audit fields, amount, currency, and transaction date become server-owned after creation. type: object properties: ID: type: string format: uuid readOnly: true Amount: type: string pattern: '^(0|[1-9][0-9]{0,7})(\.[0-9]{1,2})?$' description: Exact non-negative DECIMAL(10,2) text; never represented as float64. CreatedByID: type: string format: uuid x-nullable: true readOnly: true CreatedDate: type: string format: date-time x-nullable: true readOnly: true Currency: type: string pattern: '^[A-Z]{3}$' LastModifiedByID: type: string format: uuid x-nullable: true readOnly: true LastModifiedDate: type: string format: date-time x-nullable: true Status: type: string enum: [pending, completed, failed, refunded] x-nullable: true TenantID: type: string format: uuid x-nullable: true readOnly: true TransactionDate: type: string format: date-time x-nullable: true TransactionRequest: description: Exactly one governed Transaction object required: [Data] properties: Data: items: $ref: "#/definitions/Transaction" minItems: 1 maxItems: 1 type: array type: object TransactionResponse: description: An array of governed, payment-token-free Transaction objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "#/definitions/Transaction" type: array type: object UserRequest: properties: Data: items: $ref: "../../lib/swagger/defs/user.yaml#/User" type: array type: object UserResponse: description: An array of Print-Ready ingest Objects properties: Data: items: $ref: "../../lib/swagger/defs/user.yaml#/User" type: array Meta: $ref: "#/definitions/ResponseMeta" type: object