openapi: 3.0.3
info:
  title: MuninX API
  version: 2026-06-21
  description: >-
    The MuninX API is available at `https://api.muninx.com`.


    Most requests require a personal API token sent as a bearer token. See
    [Authentication](https://docs.muninx.com/api/authentication/) for token creation, permissions, and revocation.


    Error responses documented with the `application/problem+json` media type use the schema shown for that endpoint.


    [Download the OpenAPI file](https://docs.muninx.com/openapi/muninx.openapi.yaml). The published OpenAPI file is the
    authoritative contract for request parameters, filtering, pagination, response status codes, and schemas.
  license:
    name: Proprietary
servers:
  - url: https://api.muninx.com
    description: Production API
tags:
  - name: Tickets
    description: Tickets endpoints in the MuninX API.
  - name: Users
    description: Manage users and authentication
  - name: Tokens
    description: Manage and exchange user API tokens
  - name: User Notification Settings
    description: Manage user notification preferences
  - name: Analytics
    description: Authenticated ticket analytics queries.
  - name: Messages
    description: Messages endpoints in the MuninX API.
  - description: Optional companies, accounts, clients, or groups receiving support within the authenticated tenant organization.
    name: Customer organizations
  - description: The MuninX workspace for the authenticated account. Every user and API token belongs to exactly one tenant
      organization. These operations manage that workspace's identity and tenant-wide settings.
    name: Tenant organizations
  - name: Search
    description: Search endpoints in the MuninX API.
paths:
  /analytics:
    post:
      tags:
        - Analytics
      summary: Returns ticket analytics for the authenticated account
      description: >
        Computes aggregated ticket metrics scoped to the authenticated tenant.

        Requests are automatically filtered by the caller's role: customers are scoped to `creator = <user email>`, and
        agents to `assignee = <user email>`.

        Results are limited to 100 rows.

        Time-based metrics are returned in seconds (`avg-resolution-time-sec`, `avg-response-time-sec`,
        `avg-first-reply-sec`).

        Empty result sets are returned as a single empty result object.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/analytics_AnalyticsRequest"
            examples:
              countByStatus:
                summary: Count tickets by status for last 30 days
                value:
                  metric: count
                  group_by: status
                  from: -30d
              avgResponseTime:
                summary: Average response time excluding zeroes, recent updates only
                value:
                  metric: avg_response_time
                  group_by: ""
                  from: -30d
                  filters:
                    updated_at: -1d
              solvedPerAgent:
                summary: Solved tickets per agent updated in last 30 days
                value:
                  metric: count
                  group_by: assignee
                  from: -60d
                  filters:
                    status: solved
                    updated_at: -30d
              avgFirstReply:
                summary: Average first reply time for the past week
                value:
                  metric: avg_first_reply_time
                  group_by: ""
                  from: -7d
                  filters:
                    status: open
              avgResolutionByPriority:
                summary: Average resolution time grouped by priority
                value:
                  metric: avg_resolution_time
                  group_by: priority
                  from: -90d
      responses:
        "200":
          description: Analytics results
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/analytics_AnalyticsResults"
              examples:
                groupedCount:
                  summary: Count by status example
                  value:
                    data:
                      - group_value: Open
                        ticket-count: 42
                      - group_value: Pending
                        ticket-count: 17
                      - group_value: Solved
                        ticket-count: 95
                    meta:
                      metric: count
                      group-by: status
                      from: -30d
                      to: ""
                      filters: {}
                ungroupedAverages:
                  summary: Single-row average example
                  value:
                    data:
                      - avg-response-time-sec: 23
                    meta:
                      metric: avg_response_time
                      group-by: ""
                      from: -30d
                      to: ""
                      filters:
                        updated_at: -1d
        "400":
          description: Invalid request
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/analytics_Problem"
              examples:
                missingFrom:
                  value:
                    title: Bad Request
                    status: 400
                    detail: from must be specified
                    code: missing_from
                    instance: /analytics
                    requestId: 4f7f9d77-97a4-4ac3-8d09-9c5643ed6e53
                unsupportedMetric:
                  value:
                    title: Bad Request
                    status: 400
                    detail: Unsupported metric
                    code: unsupported_metric
                    instance: /analytics
                unsupportedGroupBy:
                  value:
                    title: Bad Request
                    status: 400
                    detail: "group_by must be one of: status, priority, creator, assignee, customer_organization"
                    code: unsupported_group_by
                    instance: /analytics
                unsupportedFilter:
                  value:
                    title: Bad Request
                    status: 400
                    detail: "filter must be one of: id, title, status, priority, creator, assignee, customer_organization, team, updated_at"
                    code: unsupported_filter
                    instance: /analytics
        "401":
          description: Unauthorized (missing/invalid token)
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/analytics_Problem"
        "403":
          description: Forbidden
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/analytics_Problem"
        "500":
          description: Internal error while querying analytics
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/analytics_Problem"
      operationId: analyticsAnalyticsPostAnalytics
  /customer-organizations:
    get:
      description: Lists optional grouping records for supported companies, accounts, clients, or groups inside the
        authenticated tenant organization. Tenant admins and agents can perform this operation. Results can be filtered
        by the implemented statuses `active` and `suspended`.
      operationId: organizationsListCustomerOrganizations
      parameters:
        - description: "Optional exact status filter: active or suspended"
          in: query
          name: status
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/organizations_CustomerOrganizations"
        "400":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "401":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "403":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "500":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
      security:
        - bearerAuth: []
      summary: List customer organizations
      tags:
        - Customer organizations
    post:
      description: Creates an optional grouping record for a supported company, account, client, or group inside the
        authenticated tenant organization. Only tenant admins can perform this operation. Domains must be unique across
        customer organizations in the tenant, with at most 5 domains per organization. New customer organizations have
        active status.
      operationId: organizationsCreateCustomerOrganization
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/organizations_CustomerOrganization"
        description: Customer Organization
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/organizations_CustomerOrganization"
        "400":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "401":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "403":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "409":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "500":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
      security:
        - bearerAuth: []
      summary: Create customer organization
      tags:
        - Customer organizations
  /customer-organizations/lookup:
    get:
      description: Finds the customer organization associated with an exact, case-insensitive email domain inside the
        authenticated tenant organization. Tenant admins and agents can perform this operation.
      operationId: organizationsLookupCustomerOrganizationByDomain
      parameters:
        - description: Email domain (exact match, case-insensitive)
          in: query
          name: domain
          required: true
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/organizations_CustomerOrganization"
        "400":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "401":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "403":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "404":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "409":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "500":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
      security:
        - bearerAuth: []
      summary: Lookup customer organization by domain
      tags:
        - Customer organizations
  /customer-organizations/{id}:
    delete:
      description: Deletes a customer organization from the authenticated tenant organization and also deletes all customer
        users associated with it. Only tenant admins can perform this operation.
      operationId: organizationsDeleteCustomerOrganization
      parameters:
        - description: Customer Organization ID
          in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        "204":
          description: No Content
          content:
            "*/*":
              schema:
                type: string
        "400":
          description: problem+json
          content:
            "*/*":
              schema:
                additionalProperties: true
                type: object
        "401":
          description: problem+json
          content:
            "*/*":
              schema:
                additionalProperties: true
                type: object
        "403":
          description: problem+json
          content:
            "*/*":
              schema:
                additionalProperties: true
                type: object
        "404":
          description: problem+json
          content:
            "*/*":
              schema:
                additionalProperties: true
                type: object
        "500":
          description: problem+json
          content:
            "*/*":
              schema:
                additionalProperties: true
                type: object
      security:
        - bearerAuth: []
      summary: Delete customer organization
      tags:
        - Customer organizations
    get:
      description: Gets a supported company, account, client, or group by ID within the authenticated tenant organization.
        Tenant admins and agents can perform this operation.
      operationId: organizationsGetCustomerOrganization
      parameters:
        - description: Customer Organization ID
          in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/organizations_CustomerOrganization"
        "400":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "401":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "403":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "404":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "500":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
      security:
        - bearerAuth: []
      summary: Get customer organization
      tags:
        - Customer organizations
    patch:
      description: Partially updates a customer organization inside the authenticated tenant organization. Only tenant admins
        can perform this operation. Domains must be unique across customer organizations in the tenant, with at most 5
        domains per organization. Status must be `active` or `suspended`.
      operationId: organizationsUpdateCustomerOrganization
      parameters:
        - description: Customer Organization ID
          in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/organizations_CustomerOrgUpdates"
        description: Updates
        required: true
      responses:
        "200":
          description: Customer org updated
          content:
            application/json:
              schema:
                type: string
        "400":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "401":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "403":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "404":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "409":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "500":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
      security:
        - bearerAuth: []
      summary: Update customer organization
      tags:
        - Customer organizations
  /customer-organizations/{id}/avatar:
    put:
      description: Uploads and resizes the logo for a customer organization inside the authenticated tenant organization. Only
        tenant admins can perform this operation.
      operationId: organizationsUpdateCustomerOrganizationAvatar
      parameters:
        - description: Customer Organization ID
          in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        $ref: "#/components/requestBodies/organizations_updateCustomerOrganizationAvatar"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                additionalProperties:
                  type: string
                type: object
        "400":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "401":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "403":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "500":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
      security:
        - bearerAuth: []
      summary: Update customer organization avatar
      tags:
        - Customer organizations
  /messages:
    get:
      summary: List ticket messages
      description: |
        Returns messages for a ticket using cursor-based pagination.
        Customer users do not receive internal messages.
      operationId: messagesListTicketMessages
      security:
        - bearerAuth: []
      parameters:
        - in: query
          name: ticket-id
          required: true
          schema:
            type: string
          description: Ticket identifier whose messages will be returned.
        - in: query
          name: limit
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 25
          description: Maximum number of messages to return.
        - in: query
          name: pageToken
          schema:
            type: string
          description: Cursor returned by the previous messages page.
      responses:
        "200":
          description: Messages page
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/messages_MessagesPage"
        "400":
          $ref: "#/components/responses/messages_BadRequest"
        "401":
          $ref: "#/components/responses/messages_Unauthorized"
        "404":
          $ref: "#/components/responses/messages_NotFound"
        "500":
          $ref: "#/components/responses/messages_InternalServerError"
      tags:
        - Messages
    post:
      summary: Create message
      description: |
        Adds a message to a ticket. The message can optionally set a new ticket
        status, skip the follow-up ticket update, or skip notification emails.
      operationId: messagesCreateMessage
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/messages_NewMessageRequest"
      responses:
        "200":
          description: Created message reference
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/messages_CreatedMessage"
        "400":
          $ref: "#/components/responses/messages_BadRequest"
        "401":
          $ref: "#/components/responses/messages_Unauthorized"
        "403":
          $ref: "#/components/responses/messages_Forbidden"
        "404":
          $ref: "#/components/responses/messages_NotFound"
        "500":
          $ref: "#/components/responses/messages_InternalServerError"
      tags:
        - Messages
  /notification-settings:
    put:
      security:
        - bearerAuth: []
      summary: Update notification settings
      description: Updates the current user's notification preferences.
      tags:
        - User Notification Settings
      operationId: usersUpdateNotificationSettings
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/users_NotificationSettingsUpdates"
            example:
              on-ticket-assigned: "true"
              on-reply: "false"
              on-status-update: "true"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: string
              example: User Notification Settings Updated
        "400":
          $ref: "#/components/responses/users_Problem"
        "401":
          $ref: "#/components/responses/users_Problem"
        "403":
          $ref: "#/components/responses/users_Problem"
        "500":
          $ref: "#/components/responses/users_Problem"
  /notification-settings/{email}:
    get:
      security:
        - bearerAuth: []
      summary: Get notification settings
      description: Retrieves the notification preferences for the given user. Use `me` for the current user.
      tags:
        - User Notification Settings
      operationId: usersGetNotificationSettings
      parameters:
        - $ref: "#/components/parameters/users_UserEmailPath"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/users_NotificationSettings"
              example:
                on-ticket-assigned: true
                on-reply: true
                on-status-update: false
        "401":
          $ref: "#/components/responses/users_Problem"
        "403":
          $ref: "#/components/responses/users_Problem"
        "404":
          $ref: "#/components/responses/users_Problem"
        "500":
          $ref: "#/components/responses/users_Problem"
  /search:
    post:
      summary: Search tickets
      operationId: searchSearchTickets
      description: Searches ticket content and returns grouped ticket IDs. Results are scoped by JWT tenant, user, and role claims.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/search_SearchRequest"
      responses:
        "200":
          description: Grouped ticket search results
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/search_SearchResponse"
        "400":
          description: Invalid request body, invalid filters, missing claims, or invalid query.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/search_Problem"
        "401":
          description: Missing, invalid, or unauthorized bearer token.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/search_Problem"
        "500":
          description: Search backend or unexpected server failure.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/search_Problem"
      tags:
        - Search
  /tenants:
    patch:
      description: Partially updates settings for the authenticated tenant's MuninX workspace. Tenant admins can update the
        workspace display name, customer access policy, allowed and blocked domains, owner, and reply identity. Billing
        plan and Stripe customer ID are service-only fields.
      operationId: organizationsUpdateTenantOrganization
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/organizations_OrgUpdates"
        description: Updates
        required: true
      responses:
        "200":
          description: Org updated
          content:
            application/json:
              schema:
                type: string
        "400":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "401":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "403":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "500":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
      security:
        - bearerAuth: []
      summary: Update tenant organization
      tags:
        - Tenant organizations
  /tenants/{id}:
    get:
      description: Gets a MuninX workspace by tenant organization ID. Use `this` as the ID to select the tenant organization
        identified by the authenticated token.
      operationId: organizationsGetTenantOrganization
      parameters:
        - description: Organization ID or 'this'
          in: path
          name: id
          required: true
          example: this
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/organizations_TenantOrganization"
        "400":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "401":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "403":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "404":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "500":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
      security:
        - bearerAuth: []
      summary: Get tenant organization
      tags:
        - Tenant organizations
  /tenants/{id}/ai-policy:
    get:
      description: Gets the tenant-wide AI policy for a MuninX workspace. Use `this` as the ID to select the tenant
        organization identified by the authenticated token.
      operationId: organizationsGetTenantAIPolicy
      parameters:
        - description: Organization ID or 'this'
          in: path
          name: id
          required: true
          example: this
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/organizations_OrgAIPolicy"
        "400":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "401":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "403":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "404":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "500":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
      security:
        - bearerAuth: []
      summary: Get AI policy
      tags:
        - Tenant organizations
    put:
      description: Replaces the tenant-wide AI policy for a MuninX workspace. Use `this` as the ID to select the tenant
        organization identified by the authenticated token.
      operationId: organizationsUpdateTenantAIPolicy
      parameters:
        - description: Organization ID or 'this'
          in: path
          name: id
          required: true
          example: this
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/organizations_OrgAIPolicy"
        description: AI policy settings
        required: true
      responses:
        "200":
          description: Policy updated
          content:
            application/json:
              schema:
                type: string
        "400":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "401":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "403":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "404":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "500":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
      security:
        - bearerAuth: []
      summary: Update AI policy
      tags:
        - Tenant organizations
  /tenants/{id}/auto-solve-settings:
    get:
      description: Gets ticket auto-solve and auto-close settings for a tenant organization. Use `this` as the ID to select
        the tenant organization identified by the authenticated token.
      operationId: organizationsGetTenantAutoSolveSettings
      parameters:
        - description: Organization ID or 'this'
          in: path
          name: id
          required: true
          example: this
          schema:
            type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/organizations_AutoSolveSettings"
        "400":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "401":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "403":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "404":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "500":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
      security:
        - bearerAuth: []
      summary: Get auto-solve and auto-close settings
      tags:
        - Tenant organizations
    put:
      description: Replaces ticket auto-solve and auto-close settings for a tenant organization. Use `this` as the ID to
        select the tenant organization identified by the authenticated token.
      operationId: organizationsUpdateTenantAutoSolveSettings
      parameters:
        - description: Organization ID or 'this'
          in: path
          name: id
          required: true
          example: this
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/organizations_AutoSolveSettings"
        description: Auto-solve and auto-close settings
        required: true
      responses:
        "200":
          description: Settings updated
          content:
            application/json:
              schema:
                type: string
        "400":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "401":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "403":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "404":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "500":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
      security:
        - bearerAuth: []
      summary: Update auto-solve and auto-close settings
      tags:
        - Tenant organizations
  /tenants/{id}/avatar:
    put:
      description: Uploads and resizes the workspace logo for the tenant organization identified by the authenticated token.
        Only tenant admins can perform this operation. Use `this` as the ID to select that tenant organization.
      operationId: organizationsUpdateTenantOrganizationAvatar
      parameters:
        - description: Tenant organization ID or 'this'
          in: path
          name: id
          required: true
          example: this
          schema:
            type: string
      requestBody:
        $ref: "#/components/requestBodies/organizations_updateCustomerOrganizationAvatar"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                additionalProperties:
                  type: string
                type: object
        "400":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "401":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "403":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
        "500":
          description: problem+json
          content:
            application/json:
              schema:
                additionalProperties: true
                type: object
      security:
        - bearerAuth: []
      summary: Update tenant avatar
      tags:
        - Tenant organizations
  /tickets:
    get:
      summary: List tickets
      description: |
        Returns the tickets visible to the authenticated user within the current tenant.
        Customers cannot filter by `creator` or `assignee`, and agents cannot filter by `assignee`.
        Filtering by both `creator` and `participant` in the same request is rejected.
      security:
        - bearerAuth: []
      parameters:
        - in: query
          name: limit
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 25
          description: Maximum number of tickets to return.
        - in: query
          name: pageToken
          schema:
            type: string
          description: Cursor returned by the previous page.
        - in: query
          name: creator
          schema:
            type: string
          description: Filter by ticket creator email.
        - in: query
          name: assignee
          schema:
            type: string
          description: Filter by ticket assignee email.
        - in: query
          name: participant
          schema:
            type: string
          description: Filter by participant email.
        - in: query
          name: state
          schema:
            type: string
          description: Comma-separated list of statuses (allowed values `new`, `open`, `pending`, `closed`, `solved`, `on-hold`).
        - in: query
          name: priority
          schema:
            type: string
          description: Comma-separated list of priorities (allowed values `low`, `medium`, `high`, `urgent`).
        - in: query
          name: customer-organization
          schema:
            type: string
          description: Filter by the ID of the customer organization.
      responses:
        "200":
          description: List of tickets
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/tickets_Tickets"
      tags:
        - Tickets
      operationId: ticketsTicketsGetTickets
    post:
      summary: Create ticket
      description: |
        Creates a ticket and immediately adds the initial message.
        Participants must be valid email addresses. Values are trimmed, lowercased,
        and deduplicated case-insensitively.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/tickets_NewTicketRequest"
      responses:
        "200":
          description: Created ticket reference
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                required:
                  - id
      tags:
        - Tickets
      operationId: ticketsTicketsPostTickets
  /tickets/{id}:
    get:
      summary: Get ticket
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Ticket
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/tickets_Ticket"
      tags:
        - Tickets
      operationId: ticketsTicketsGetTicketsId
    patch:
      summary: Update ticket
      security:
        - bearerAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/tickets_TicketUpdates"
      responses:
        "200":
          description: Updated ticket
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/tickets_Ticket"
        "400":
          description: Invalid update. Ticket titles are immutable and cannot be included in this request.
          content:
            application/problem+json:
              schema:
                $ref: "#/components/schemas/tickets_Problem"
              example:
                title: Bad Request
                status: 400
                detail: ticket title cannot be updated
                code: immutable_field
                instance: /tickets/example-ticket-id
      tags:
        - Tickets
      operationId: ticketsTicketsPatchTicketsId
  /tokens:
    post:
      security:
        - bearerAuth: []
      summary: Create API token
      description: Creates a user API token and returns the raw token once.
      tags:
        - Tokens
      operationId: usersCreateToken
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/users_CreateTokenRequest"
            example:
              name: CI token
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/users_CreatedTokenResponse"
              example:
                id: 5f60c89c-66eb-4fa5-8c5e-0de8f505f2c8
                name: CI token
                token: muninx_api_token_value
                created_at: 2026-06-11T10:00:00Z
        "400":
          $ref: "#/components/responses/users_Problem"
        "401":
          $ref: "#/components/responses/users_Problem"
        "403":
          $ref: "#/components/responses/users_Problem"
        "500":
          $ref: "#/components/responses/users_Problem"
    get:
      security:
        - bearerAuth: []
      summary: List API tokens
      description: Lists API token metadata for the current authenticated user. Raw token values are not returned.
      tags:
        - Tokens
      operationId: usersListTokens
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/users_TokenSummary"
              example:
                - id: 5f60c89c-66eb-4fa5-8c5e-0de8f505f2c8
                  name: CI token
                  created_at: 2026-06-11T10:00:00Z
        "401":
          $ref: "#/components/responses/users_Problem"
        "403":
          $ref: "#/components/responses/users_Problem"
        "500":
          $ref: "#/components/responses/users_Problem"
  /tokens/{id}:
    delete:
      security:
        - bearerAuth: []
      summary: Delete API token
      description: Deletes one of the current authenticated user's API tokens.
      tags:
        - Tokens
      operationId: usersDeleteToken
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
          description: API token ID.
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: string
              example: Token deleted
        "400":
          $ref: "#/components/responses/users_Problem"
        "401":
          $ref: "#/components/responses/users_Problem"
        "403":
          $ref: "#/components/responses/users_Problem"
        "500":
          $ref: "#/components/responses/users_Problem"
  /users:
    get:
      security:
        - bearerAuth: []
      summary: List users
      description: Returns users visible to the caller based on their role. Supports optional comma-separated filters.
      tags:
        - Users
      operationId: usersListUsers
      parameters:
        - in: query
          name: type
          schema:
            type: string
          description: Filter by user types. Accepted values are `admin`, `agent`, and `customer`.
          example: admin,agent
        - in: query
          name: status
          schema:
            type: string
          description: Filter by status. Accepted values are `active` and `suspended`.
          example: active,suspended
        - in: query
          name: agent-type
          schema:
            type: string
          description: Filter by agent type. Accepted values are `human`, `ai-assisted`, and `ai-autonomous`.
          example: human,ai-assisted
        - in: query
          name: organization
          schema:
            type: string
          description: Filter by organization ID.
        - in: query
          name: auto-assign-tickets
          schema:
            type: string
            enum:
              - "true"
              - "false"
          description: Filter by auto-assign-tickets flag.
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/users_Users"
              example:
                users:
                  - email: alice@acme.com
                    name: Alice
                    last-name: Doe
                    organization: acme
                    type: admin
                    agent-type: human
                    status: active
                    auto-assign-tickets: true
                  - email: bob@acme.com
                    name: Bob
                    last-name: Smith
                    organization: acme
                    type: agent
                    agent-type: ai-assisted
                    status: pending
                    auto-assign-tickets: false
        "400":
          $ref: "#/components/responses/users_Problem"
        "401":
          $ref: "#/components/responses/users_Problem"
        "403":
          $ref: "#/components/responses/users_Problem"
        "500":
          $ref: "#/components/responses/users_Problem"
    post:
      security:
        - bearerAuth: []
      summary: Invite user in organization
      description: Creates a pending user for an existing organization and sends an activation email. Admins and agents
        require an `agent-type`; customers cannot have one.
      tags:
        - Users
      operationId: usersInviteUser
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/users_NewUserInOrgRequest"
            example:
              email: jane.doe@customer.com
              name: Jane
              last-name: Doe
              type: customer
              organization: acme-customer-1
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: string
              example: A confirmation email has been sent to the new user's email
        "400":
          $ref: "#/components/responses/users_Problem"
        "401":
          $ref: "#/components/responses/users_Problem"
        "403":
          $ref: "#/components/responses/users_Problem"
        "500":
          $ref: "#/components/responses/users_Problem"
  /users/{email}:
    get:
      security:
        - bearerAuth: []
      summary: Get user
      description: Get a user by email. Use `me` to get the current user.
      tags:
        - Users
      operationId: usersGetUser
      parameters:
        - $ref: "#/components/parameters/users_UserEmailPath"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/users_User"
        "401":
          $ref: "#/components/responses/users_Problem"
        "403":
          $ref: "#/components/responses/users_Problem"
        "404":
          $ref: "#/components/responses/users_Problem"
        "500":
          $ref: "#/components/responses/users_Problem"
    put:
      security:
        - bearerAuth: []
      summary: Update user
      description: Updates user fields. Only admins can update role, status, organization, auto-assign, or agent type.
      tags:
        - Users
      operationId: usersUpdateUser
      parameters:
        - $ref: "#/components/parameters/users_UserEmailPath"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/users_UserUpdates"
            example:
              name: Alice
              last-name: Doe
              type: agent
              agent-type: human
              organization: acme
              status: suspended
              auto-assign-tickets: "true"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: string
              example: User updated
        "400":
          $ref: "#/components/responses/users_Problem"
        "401":
          $ref: "#/components/responses/users_Problem"
        "403":
          $ref: "#/components/responses/users_Problem"
        "500":
          $ref: "#/components/responses/users_Problem"
    delete:
      security:
        - bearerAuth: []
      summary: Delete user
      tags:
        - Users
      operationId: usersDeleteUser
      parameters:
        - $ref: "#/components/parameters/users_UserEmailPath"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: string
              example: User Deleted
        "400":
          $ref: "#/components/responses/users_Problem"
        "401":
          $ref: "#/components/responses/users_Problem"
        "403":
          $ref: "#/components/responses/users_Problem"
        "500":
          $ref: "#/components/responses/users_Problem"
  /users/{email}/activation-email:
    post:
      security:
        - bearerAuth: []
      summary: Resend activation email
      description: Sends the activation email again for a pending user.
      tags:
        - Users
      operationId: usersResendActivationEmail
      parameters:
        - $ref: "#/components/parameters/users_UserEmailPath"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: string
              example: Confirmation email sent
        "400":
          $ref: "#/components/responses/users_Problem"
        "401":
          $ref: "#/components/responses/users_Problem"
        "403":
          $ref: "#/components/responses/users_Problem"
        "500":
          $ref: "#/components/responses/users_Problem"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  schemas:
    tickets_Problem:
      type: object
      properties:
        type:
          type: string
        title:
          type: string
        status:
          type: integer
        detail:
          type: string
        instance:
          type: string
        code:
          type: string
        requestId:
          type: string
    tickets_Ticket:
      type: object
      properties:
        id:
          type: string
        tenant-organization:
          type: string
        creator:
          type: string
        participants:
          type: array
          items:
            type: string
        customer-organization:
          type: string
        assignee:
          type: string
        team:
          type: string
        created-at:
          type: string
          format: date-time
        updated-at:
          type: string
          format: date-time
        status:
          type: string
          description: Ticket status.
          enum:
            - new
            - open
            - pending
            - on-hold
            - solved
            - closed
        priority:
          type: string
          description: Ticket priority.
          enum:
            - low
            - medium
            - high
            - urgent
        title:
          type: string
        message-count:
          type: integer
        first-reply-sec:
          type: integer
        avg-reply-sec:
          type: integer
        max-reply-sec:
          type: integer
        resolution-time-sec:
          type: integer
        auto-solve-enabled:
          type: boolean
          nullable: true
        auto-solve-at:
          type: string
          format: date-time
        auto-close-at:
          type: string
          format: date-time
      required:
        - id
        - tenant-organization
        - creator
        - participants
        - customer-organization
        - assignee
        - team
        - status
        - priority
        - title
        - created-at
        - updated-at
        - message-count
        - first-reply-sec
        - avg-reply-sec
        - max-reply-sec
        - resolution-time-sec
        - auto-solve-enabled
        - auto-solve-at
        - auto-close-at
    tickets_TicketUpdates:
      type: object
      properties:
        organization:
          type: string
          description: Only admins can modify the organization.
        participants:
          type: array
          items:
            type: string
          description: Updated list of valid participant email addresses. Values are trimmed, lowercased, and deduplicated
            case-insensitively.
        assignee:
          type: string
          description: Only admins can reassign a ticket.
        status:
          type: string
          description: User-selectable ticket status. Tickets are closed only by the tenant organization's auto-close settings
            after they remain solved for the configured duration.
          enum:
            - new
            - open
            - pending
            - on-hold
            - solved
        priority:
          type: string
          enum:
            - low
            - medium
            - high
            - urgent
        message-count:
          type: integer
        first-reply-sec:
          type: integer
          description: Service users only.
        avg-reply-sec:
          type: integer
          description: Service users only.
        max-reply-sec:
          type: integer
          description: Service users only.
        resolution-time-sec:
          type: integer
          description: Service users only.
        skip-notifications:
          type: boolean
          description: If true, this update will not trigger ticket notification emails.
      additionalProperties: false
    tickets_NewTicketRequest:
      type: object
      properties:
        priority:
          type: string
          enum:
            - low
            - medium
            - high
            - urgent
        title:
          type: string
          minLength: 1
          pattern: .*\S.*
        body:
          type: string
          minLength: 1
          pattern: .*\S.*
        participants:
          type: array
          items:
            type: string
          description: Valid email addresses that should be subscribed to the ticket. Values are trimmed, lowercased, and
            deduplicated case-insensitively.
      required:
        - priority
        - title
        - body
    tickets_Tickets:
      type: object
      properties:
        tickets:
          type: array
          items:
            $ref: "#/components/schemas/tickets_Ticket"
        nextPageToken:
          type: string
          description: Cursor for the next page of tickets.
        limit:
          type: integer
          description: Page size applied to this response.
      required:
        - tickets
        - limit
    users_Problem:
      type: object
      description: RFC 9457 problem details.
      properties:
        type:
          type: string
          format: uri
        title:
          type: string
        status:
          type: integer
          format: int32
        detail:
          type: string
        instance:
          type: string
          format: uri
      additionalProperties: true
    users_NewUserInOrgRequest:
      type: object
      required:
        - email
        - name
        - last-name
        - type
      properties:
        email:
          type: string
          format: email
        name:
          type: string
        last-name:
          type: string
        organization:
          type: string
          description: Used for customers. Agents and admins are assigned to the authenticated tenant organization.
        type:
          $ref: "#/components/schemas/users_UserType"
        agent-type:
          $ref: "#/components/schemas/users_AgentType"
        challenge:
          type: string
          description: Optional challenge override. Normally generated automatically.
        created-at:
          type: string
          format: date-time
    users_UserUpdates:
      type: object
      properties:
        name:
          type: string
        last-name:
          type: string
        type:
          $ref: "#/components/schemas/users_UserType"
        organization:
          type: string
        auto-assign-tickets:
          type: string
          enum:
            - "true"
            - "false"
        status:
          type: string
          enum:
            - active
            - suspended
        agent-type:
          $ref: "#/components/schemas/users_AgentType"
    users_CreateTokenRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
    users_CreatedTokenResponse:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        token:
          type: string
          description: Raw API token. Returned only when the token is created.
        created_at:
          type: string
          format: date-time
    users_TokenSummary:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        created_at:
          type: string
          format: date-time
    users_User:
      type: object
      properties:
        name:
          type: string
        last-name:
          type: string
        email:
          type: string
          format: email
        created-at:
          type: string
          format: date-time
        password:
          type: string
          description: Omitted from normal API responses.
        type:
          $ref: "#/components/schemas/users_UserType"
        organization:
          type: string
        status:
          type: string
          enum:
            - pending
            - active
            - suspended
        auto-assign-tickets:
          type: boolean
        agent-type:
          $ref: "#/components/schemas/users_AgentType"
    users_Users:
      type: object
      properties:
        users:
          type: array
          items:
            $ref: "#/components/schemas/users_User"
    users_NotificationSettings:
      type: object
      properties:
        on-ticket-assigned:
          type: boolean
        on-reply:
          type: boolean
        on-status-update:
          type: boolean
    users_NotificationSettingsUpdates:
      type: object
      properties:
        on-ticket-assigned:
          type: string
          enum:
            - "true"
            - "false"
        on-reply:
          type: string
          enum:
            - "true"
            - "false"
        on-status-update:
          type: string
          enum:
            - "true"
            - "false"
    users_UserType:
      type: string
      enum:
        - admin
        - agent
        - customer
    users_AgentType:
      type: string
      enum:
        - human
        - ai-assisted
        - ai-autonomous
    analytics_AnalyticsRequest:
      type: object
      required:
        - metric
        - from
      additionalProperties: false
      properties:
        metric:
          type: string
          description: Aggregation to compute
          enum:
            - count
            - avg_resolution_time
            - avg_response_time
            - avg_first_reply_time
        group_by:
          type: string
          description: Ticket field to group by.
          enum:
            - ""
            - status
            - priority
            - creator
            - assignee
            - customer_organization
          default: ""
          example: status
        from:
          type: string
          description: Start date, either YYYY-MM-DD or a relative day offset such as -30d.
          example: -30d
        to:
          type: string
          description: Optional end date, either YYYY-MM-DD or a relative day offset such as -1d. Defaults to the current date if
            omitted.
          example: 2025-08-01
        filters:
          type: object
          additionalProperties: false
          properties:
            id:
              type: string
              description: Filter by exact ticket ID.
            title:
              type: string
              description: Filter by exact ticket title.
            status:
              type: string
              enum:
                - open
                - pending
                - on-hold
                - solved
                - closed
              description: Filter by status (validated server-side).
            priority:
              type: string
              enum:
                - low
                - medium
                - high
                - urgent
              description: Filter by priority (validated server-side).
            creator:
              type: string
              description: Filter by exact creator email.
            assignee:
              type: string
              description: Filter by exact assignee email.
            customer_organization:
              type: string
              description: Filter by exact customer organization ID.
            team:
              type: string
              description: Filter by exact team value.
            updated_at:
              type: string
              description: Include tickets updated after this value (YYYY-MM-DD or -Xd).
          description: >
            Supported string filters are combined with AND. Equality is used by default (`key = value`).

            `status` and `priority` are normalized and validated server-side.

            `updated_at` is handled as `updated_at > value` and supports YYYY-MM-DD or -Xd.

            Requests are automatically scoped by role: customers are constrained to their own tickets (`creator`),
            agents are constrained to tickets they own (`assignee`).
          example:
            status: open
            priority: low
    analytics_AnalyticsMeta:
      type: object
      properties:
        metric:
          type: string
        group-by:
          type: string
        from:
          type: string
        to:
          type: string
        filters:
          type: object
          additionalProperties:
            oneOf:
              - type: string
              - type: number
              - type: boolean
    analytics_AnalyticsSingleResult:
      type: object
      description: Only the property for the requested metric is present; `group_value` is present only when `group_by` is set.
      properties:
        group_value:
          type: string
          description: Present only when grouped
        ticket-count:
          type: integer
          format: int64
        avg-resolution-time-sec:
          type: number
          format: double
        avg-response-time-sec:
          type: number
          format: double
        avg-first-reply-sec:
          type: number
          format: double
    analytics_AnalyticsResults:
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/analytics_AnalyticsSingleResult"
        meta:
          $ref: "#/components/schemas/analytics_AnalyticsMeta"
    analytics_Problem:
      type: object
      description: RFC 9457 problem details response emitted by the shared Gin error middleware.
      properties:
        type:
          type: string
          description: Optional URI reference identifying the problem type.
        title:
          type: string
          example: Bad Request
        status:
          type: integer
          example: 400
        detail:
          type: string
          example: from must be specified
        instance:
          type: string
          example: /analytics
        code:
          type: string
          example: missing_from
        requestId:
          type: string
          description: Request correlation ID when available.
    messages_CreatedMessage:
      type: object
      properties:
        id:
          type: string
          description: Created message identifier.
      required:
        - id
      additionalProperties: false
    messages_ErrorResponse:
      type: object
      description: Error envelope emitted by the shared Gin error middleware.
      properties:
        code:
          type: string
        message:
          type: string
        error:
          type: string
      additionalProperties: true
    messages_MessageResponse:
      type: object
      properties:
        author:
          type: string
          description: Author email, or organization display name when organization reply identity is enabled.
        author-role:
          type: string
          enum:
            - admin
            - agent
            - customer
            - organization
            - service
        posted-at:
          type: string
          format: date-time
        type:
          type: string
          enum:
            - external
            - internal
        body:
          type: string
      required:
        - author
        - author-role
        - posted-at
        - type
        - body
      additionalProperties: false
    messages_MessagesPage:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: "#/components/schemas/messages_MessageResponse"
        nextPageToken:
          type: string
          description: Cursor for the next page of messages.
        limit:
          type: integer
          description: Page size applied to this response.
      required:
        - items
        - limit
      additionalProperties: false
    messages_NewMessageRequest:
      type: object
      properties:
        ticket-id:
          type: string
          description: Ticket identifier to add the message to.
        body:
          type: string
          minLength: 1
          description: Message body. Must contain at least one non-whitespace character.
        type:
          type: string
          description: Message visibility type.
          enum:
            - external
            - internal
        new-status:
          type: string
          description: Optional status to apply to the ticket after creating the message.
          enum:
            - new
            - open
            - pending
            - on-hold
            - solved
            - closed
        skip-ticket-update:
          type: boolean
          description: If true, message creation will not update the associated ticket.
        skip-notifications:
          type: boolean
          description: If true, message creation will not send notification emails to ticket participants.
      required:
        - ticket-id
        - body
        - type
      additionalProperties: false
    organizations_AutoSolveSettings:
      properties:
        close-after-hours:
          description: Defines how long the ticket will be closed after it was Solved
          type: integer
        email-participants-on-solve:
          type: boolean
        enabled:
          type: boolean
        solve-after-hours:
          type: integer
        solve-message:
          type: string
      type: object
    organizations_CustomerOrgUpdates:
      properties:
        display-name:
          type: string
        domains:
          items:
            type: string
          type: array
        external-ref:
          type: string
        notes:
          type: string
        status:
          type: string
      type: object
    organizations_CustomerOrganization:
      properties:
        created-at:
          type: string
        display-name:
          type: string
        domains:
          items:
            type: string
          type: array
        external-ref:
          type: string
        id:
          type: string
        notes:
          type: string
        status:
          description: active, suspended
          type: string
        tenant-id:
          type: string
        updated-at:
          type: string
      type: object
    organizations_CustomerOrganizations:
      properties:
        customer-organizations:
          items:
            $ref: "#/components/schemas/organizations_CustomerOrganization"
          type: array
      type: object
    organizations_OrgAIPolicy:
      properties:
        ai-instructions:
          type: string
        allow-ai-web-search:
          type: boolean
        allowed-web-search-domains:
          items:
            type: string
          type: array
        blacklist-policy-md:
          type: string
        confidence-threshold:
          description: If below this threshold will escalate 0-100
          type: integer
        policy-type:
          description: '"whitelist" or "blacklist"'
          type: string
        tone:
          type: string
        whitelist-policy-md:
          type: string
      type: object
    organizations_OrgUpdates:
      properties:
        allowed-domains:
          description: Domains allowed when customer access is restricted.
          items:
            type: string
          type: array
        blocked-domains:
          description: Domains blocked from customer access.
          items:
            type: string
          type: array
        customer-access-type:
          description: "Customer signup policy: open, closed, or restricted."
          enum:
            - open
            - closed
            - restricted
          type: string
        display-name:
          description: Workspace display name.
          type: string
        owner:
          description: Admin email that owns the workspace.
          type: string
        plan:
          description: Billing plan. Service users only.
          type: string
        reply-identity:
          description: Identity shown on agent replies.
          enum:
            - agent
            - organization
          type: string
        stripe-id:
          description: Stripe customer ID. Service users only.
          type: string
      type: object
    organizations_TenantOrganization:
      properties:
        allowed-domains:
          items:
            type: string
          type: array
        blocked-domains:
          items:
            type: string
          type: array
        created-at:
          type: string
        customer-access-type:
          description: open, closed, restricted
          type: string
        display-name:
          type: string
        id:
          type: string
        owner:
          type: string
        plan:
          type: string
        reply-identity:
          type: string
        stripe-id:
          type: string
      type: object
    search_FilterOptions:
      type: object
      properties:
        kind:
          type: array
          description: Restrict search to specific ticket document kinds. Customer users never receive internal messages.
          items:
            type: string
            enum:
              - title
              - description
              - message
              - internal_message
        author-id:
          type: string
        created-at-from:
          type: integer
          format: int64
          description: Inclusive lower bound for the document creation Unix timestamp.
        created-at-to:
          type: integer
          format: int64
          description: Inclusive upper bound for the document creation Unix timestamp.
    search_SearchRequest:
      type: object
      required:
        - q
      properties:
        q:
          type: string
          example: expired login link
        per-page:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
          example: 20
          description: Results per page. Values above 100 are clamped to 100; missing or non-positive values default to 20.
        page:
          type: integer
          minimum: 1
          default: 1
          example: 1
          description: One-based page number. Missing or non-positive values default to 1.
        group-limit:
          type: integer
          minimum: 1
          maximum: 25
          default: 3
          example: 3
          description: Maximum matching documents considered per ticket group. Values above 25 are clamped to 25; missing or
            non-positive values default to 3.
        include-preview:
          type: boolean
          default: false
          description: Return a short snippet from the matched content instead of the full body.
        filters:
          $ref: "#/components/schemas/search_FilterOptions"
    search_SearchResponse:
      type: object
      properties:
        ticket-ids:
          type: array
          items:
            type: string
          description: Ticket IDs grouped from matching Typesense documents.
        found:
          type: integer
          format: int32
          example: 42
        page:
          type: integer
        per-page:
          type: integer
        group-limit:
          type: integer
        filter-by:
          type: string
          description: Typesense filter expression applied after RBAC and request filters.
        next-page:
          type: integer
          nullable: true
          description: Next page number when more results are available; omitted on the last page.
        previews:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/search_Preview"
          description: Optional snippets keyed by ticket id when include-preview is true. Includes the document kind that matched
            (message, title, etc.).
    search_Preview:
      type: object
      properties:
        snippet:
          type: string
        kind:
          type: string
          enum:
            - title
            - description
            - message
            - internal_message
    search_Problem:
      type: object
      description: RFC 9457 problem details response emitted by the shared error middleware.
      properties:
        type:
          type: string
        title:
          type: string
          example: Bad Request
        status:
          type: integer
          example: 400
        detail:
          type: string
          example: search query cannot be empty
        instance:
          type: string
          example: /search
        code:
          type: string
          example: missing_query
        requestId:
          type: string
  parameters:
    users_UserEmailPath:
      in: path
      name: email
      required: true
      schema:
        type: string
      description: User email address. Some endpoints also accept `me`.
      example: me
  responses:
    users_Problem:
      description: RFC 9457 problem details
      content:
        application/problem+json:
          schema:
            $ref: "#/components/schemas/users_Problem"
    messages_BadRequest:
      description: Invalid request.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/messages_ErrorResponse"
    messages_Unauthorized:
      description: Missing, invalid, or expired bearer token.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/messages_ErrorResponse"
    messages_Forbidden:
      description: Authenticated user is not allowed to perform the requested action.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/messages_ErrorResponse"
    messages_NotFound:
      description: The requested resource does not exist or is not accessible.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/messages_ErrorResponse"
    messages_InternalServerError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/messages_ErrorResponse"
  requestBodies:
    organizations_updateCustomerOrganizationAvatar:
      content:
        multipart/form-data:
          schema:
            type: object
            properties:
              avatar:
                description: Avatar image (jpg, png, webp). Max 5MB.
                type: string
                format: binary
            required:
              - avatar
      required: true
