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 ClusterRequest: description: An array of Cluster records 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" 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 a Database in: query name: databaseId type: string required: true 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" 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" 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: Return a list of Attendee records from the datastore 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: [] summary: Get a list Attendees tags: - Attendees post: description: Create Attendees 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: [] summary: Create new Attendees tags: - Attendees put: description: Update Attendee operationId: putAttendees 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: [] summary: Update Attendee tags: - Attendees /clusters: get: description: Return a list of Cluster records from the datastore operationId: getClusters parameters: - $ref: "#/parameters/clusterIdQuery" - $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: [] summary: Get a list Clusters tags: - Clusters post: description: Create Clusters operationId: postClusters parameters: - $ref: "#/parameters/ClusterRequest" 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: [] summary: Create new Clusters tags: - Clusters put: description: Update Cluster operationId: putClusters parameters: - $ref: "#/parameters/ClusterRequest" 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: [] summary: Update Clustera 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: Return a list of Database records from the datastore operationId: getDatabases parameters: - $ref: "#/parameters/databaseIdQuery" - $ref: "#/parameters/limitQuery" - $ref: "#/parameters/offsetQuery" responses: "200": $ref: "#/responses/DatabaseResponse" "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 Databases tags: - Databases post: description: Create Databases operationId: postDatabases parameters: - $ref: "#/parameters/databaseRequest" responses: "200": $ref: "#/responses/DatabaseResponse" "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 Databases tags: - Databases put: description: Update Database operationId: putDatabases parameters: - $ref: "#/parameters/databaseRequest" responses: "200": $ref: "#/responses/DatabaseResponse" "401": $ref: "#/responses/Unauthorized" "403": $ref: "#/responses/AccessForbidden" "404": $ref: "#/responses/NotFound" "422": $ref: "#/responses/UnprocessableEntity" "500": $ref: "#/responses/ServerError" security: - ApiKeyAuth: [] summary: Update Databases 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. 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- and user-scoped DocumentParameter create. Requires members:document-parameter:create and an active human session. 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- and user-scoped DocumentParameter CAS update. Requires members:document-parameter:update and an active human session. 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: security: - ApiKeyAuth: [] 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: security: - ApiKeyAuth: [] 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 /events: get: security: - ApiKeyAuth: [] 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: security: - ApiKeyAuth: [] 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 /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: get: description: Return a list of Ticket records from the datastore 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: [] summary: Get a list Tickets tags: - Tickets post: description: Create Tickets 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: [] summary: Create new Tickets tags: - Tickets put: description: Update Ticket 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: [] summary: Update Ticket tags: - Tickets /transactions: get: description: Return a list of Transaction records from the datastore operationId: getTransactions parameters: - $ref: "#/parameters/idQuery" - $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: [] summary: Get a list of Transactions tags: - Transactions post: description: Create Transactions operationId: postTransactions parameters: - $ref: "#/parameters/TransactionRequest" 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: [] summary: Create new Transactions tags: - Transactions put: description: Update Transaction operationId: putTransactions parameters: - $ref: "#/parameters/TransactionRequest" 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: [] summary: Update 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: 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: properties: Data: items: $ref: "../../lib/swagger/defs/cluster.yaml#/Cluster" type: array type: object ClusterResponse: description: An array of cluster objects properties: Data: items: $ref: "../../lib/swagger/defs/cluster.yaml#/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 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 properties: Data: items: $ref: "#/definitions/DocumentParameter" 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 TransactionRequest: description: An array of Transaction objects properties: Data: items: $ref: "../../lib/swagger/defs/transaction.yaml#/Transaction" type: array type: object TransactionResponse: description: An array of Transaction objects properties: Meta: $ref: "#/definitions/ResponseMeta" Data: items: $ref: "../../lib/swagger/defs/transaction.yaml#/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